mirror of
https://github.com/nmap/nmap.git
synced 2025-12-18 21:49:01 +00:00
Don't try to do FD_ISSET on a nonselectable pcap descriptor.
The Nsock select engine stores readiness information in a mask instead of doing an FD_ISSET against the descriptor every time. This is a good idea, but it removed a special case in the pre-engines code: in case PCAP_CAN_DO_SELECT is not defined, we can't do FD_ISSET on the descriptor because it is -1. Here we check for that occurrence and set EV_READ in the mask so that a non-blocking pcap read can happen every iteration.
This commit is contained in:
@@ -349,25 +349,22 @@ int select_loop(mspool *nsp, int msec_timeout) {
|
||||
|
||||
/* ---- INTERNAL FUNCTIONS ---- */
|
||||
|
||||
/* Iterate through all the event lists (such as connect_events, read_events,
|
||||
* timer_events, etc) and take action for those that have completed (due to
|
||||
* timeout, i/o, etc) */
|
||||
void iterate_through_event_lists(mspool *nsp) {
|
||||
gh_list_elem *current, *next, *last, *timer_last;
|
||||
static int get_evmask(const mspool *nsp, const msiod *nsi) {
|
||||
struct select_engine_info *sinfo = (struct select_engine_info *)nsp->engine_data;
|
||||
int sd, evmask;
|
||||
|
||||
/* Clear it -- We will find the next event as we go through the list */
|
||||
nsp->next_ev.tv_sec = 0;
|
||||
evmask = EV_NONE;
|
||||
|
||||
last = GH_LIST_LAST_ELEM(&nsp->active_iods);
|
||||
timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);
|
||||
|
||||
for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods);
|
||||
current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) {
|
||||
msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current);
|
||||
|
||||
if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending) {
|
||||
int sd, evmask = EV_NONE;
|
||||
#if HAVE_PCAP
|
||||
#ifndef PCAP_CAN_DO_SELECT
|
||||
if (nsi->pcap) {
|
||||
/* Always assume readable for a non-blocking read. We can't check FD_ISSET
|
||||
because we don't have a pcap_desc. */
|
||||
evmask |= EV_READ;
|
||||
return evmask;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_PCAP
|
||||
if (nsi->pcap)
|
||||
@@ -385,8 +382,27 @@ void iterate_through_event_lists(mspool *nsp) {
|
||||
if (FD_ISSET(sd, &sinfo->fds_results_x))
|
||||
evmask |= EV_EXCEPT;
|
||||
|
||||
process_iod_events(nsp, nsi, evmask);
|
||||
}
|
||||
return evmask;
|
||||
}
|
||||
|
||||
/* Iterate through all the event lists (such as connect_events, read_events,
|
||||
* timer_events, etc) and take action for those that have completed (due to
|
||||
* timeout, i/o, etc) */
|
||||
void iterate_through_event_lists(mspool *nsp) {
|
||||
gh_list_elem *current, *next, *last, *timer_last;
|
||||
|
||||
/* Clear it -- We will find the next event as we go through the list */
|
||||
nsp->next_ev.tv_sec = 0;
|
||||
|
||||
last = GH_LIST_LAST_ELEM(&nsp->active_iods);
|
||||
timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events);
|
||||
|
||||
for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods);
|
||||
current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) {
|
||||
msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current);
|
||||
|
||||
if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending)
|
||||
process_iod_events(nsp, nsi, get_evmask(nsp, nsi));
|
||||
|
||||
next = GH_LIST_ELEM_NEXT(current);
|
||||
if (nsi->state == NSIOD_STATE_DELETED) {
|
||||
|
||||
@@ -982,10 +982,7 @@ void process_event(mspool *nsp, gh_list *evlist, msevent *nse, int ev) {
|
||||
if (nsp->tracelevel > 5)
|
||||
nsock_trace(nsp, "PCAP iterating %lu", nse->id);
|
||||
|
||||
#if PCAP_CAN_DO_SELECT
|
||||
if (ev & EV_READ)
|
||||
#endif
|
||||
{
|
||||
if (ev & EV_READ) {
|
||||
/* buffer empty? check it! */
|
||||
if (FILESPACE_LENGTH(&(nse->iobuf)) == 0)
|
||||
do_actual_pcap_read(nse);
|
||||
|
||||
Reference in New Issue
Block a user