1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-19 22:19:02 +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:
david
2012-04-05 03:30:09 +00:00
parent 4a541fc367
commit 05c713d22a
2 changed files with 39 additions and 26 deletions

View File

@@ -349,25 +349,22 @@ int select_loop(mspool *nsp, int msec_timeout) {
/* ---- INTERNAL FUNCTIONS ---- */ /* ---- INTERNAL FUNCTIONS ---- */
/* Iterate through all the event lists (such as connect_events, read_events, static int get_evmask(const mspool *nsp, const msiod *nsi) {
* 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;
struct select_engine_info *sinfo = (struct select_engine_info *)nsp->engine_data; 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 */ evmask = EV_NONE;
nsp->next_ev.tv_sec = 0;
last = GH_LIST_LAST_ELEM(&nsp->active_iods); #if HAVE_PCAP
timer_last = GH_LIST_LAST_ELEM(&nsp->timer_events); #ifndef PCAP_CAN_DO_SELECT
if (nsi->pcap) {
for (current = GH_LIST_FIRST_ELEM(&nsp->active_iods); /* Always assume readable for a non-blocking read. We can't check FD_ISSET
current != NULL && GH_LIST_ELEM_PREV(current) != last; current = next) { because we don't have a pcap_desc. */
msiod *nsi = (msiod *)GH_LIST_ELEM_DATA(current); evmask |= EV_READ;
return evmask;
if (nsi->state != NSIOD_STATE_DELETED && nsi->events_pending) { }
int sd, evmask = EV_NONE; #endif
#endif
#if HAVE_PCAP #if HAVE_PCAP
if (nsi->pcap) if (nsi->pcap)
@@ -385,9 +382,28 @@ void iterate_through_event_lists(mspool *nsp) {
if (FD_ISSET(sd, &sinfo->fds_results_x)) if (FD_ISSET(sd, &sinfo->fds_results_x))
evmask |= EV_EXCEPT; 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); next = GH_LIST_ELEM_NEXT(current);
if (nsi->state == NSIOD_STATE_DELETED) { if (nsi->state == NSIOD_STATE_DELETED) {
gh_list_remove_elem(&nsp->active_iods, current); gh_list_remove_elem(&nsp->active_iods, current);

View File

@@ -982,10 +982,7 @@ void process_event(mspool *nsp, gh_list *evlist, msevent *nse, int ev) {
if (nsp->tracelevel > 5) if (nsp->tracelevel > 5)
nsock_trace(nsp, "PCAP iterating %lu", nse->id); nsock_trace(nsp, "PCAP iterating %lu", nse->id);
#if PCAP_CAN_DO_SELECT if (ev & EV_READ) {
if (ev & EV_READ)
#endif
{
/* buffer empty? check it! */ /* buffer empty? check it! */
if (FILESPACE_LENGTH(&(nse->iobuf)) == 0) if (FILESPACE_LENGTH(&(nse->iobuf)) == 0)
do_actual_pcap_read(nse); do_actual_pcap_read(nse);