1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-10 07:01:32 +00:00

Do a non-blocking check for events when pcap data is available

For platforms without selectable pcap handles (e.g. Windows), the
arrival of data for a pcap read would previously skip checking for any
triggered non-pcap events in that loop iteration. This is not usually a
problem because the next loop will be triggered immediately, picking up
the non-pcap events before any further pcap data arrives. However,
excessive pcap data on a handle in immediate mode might prevent the
engine loop from checking for non-pcap events for long enough to result
in timeouts. Instead, do a non-blocking check for triggered events in
this case and handle those in the same loop iteration.
This commit is contained in:
dmiller
2024-10-09 17:40:10 +00:00
parent 167fafe65c
commit 532938f49c
5 changed files with 63 additions and 64 deletions

View File

@@ -289,14 +289,14 @@ int epoll_loop(struct npool *nsp, int msec_timeout) {
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
} else
#endif
#endif
{
results_left = epoll_wait(einfo->epfd, einfo->events, einfo->evlen, combined_msecs);
if (results_left == -1)
sock_err = socket_errno();
// Make the epoll_wait call non-blocking
combined_msecs = 0;
}
#endif
#endif
results_left = epoll_wait(einfo->epfd, einfo->events, einfo->evlen, combined_msecs);
if (results_left == -1)
sock_err = socket_errno();
gettimeofday(&nsock_tod, NULL); /* Due to epoll delay */
} while (results_left == -1 && sock_err == EINTR); /* repeat only if signal occurred */

View File

@@ -360,29 +360,28 @@ int iocp_loop(struct npool *nsp, int msec_timeout) {
/* okay, something was read. */
gettimeofday(&nsock_tod, NULL);
iterate_through_pcap_events(nsp);
// Only do a non-blocking check for completed IO on the non-pcap events
combined_msecs = 0;
}
else
#endif
#endif
{
/* It is mandatory these values are reset before calling GetQueuedCompletionStatusEx */
iinfo->entries_removed = 0;
memset(iinfo->eov_list, 0, iinfo->capacity * sizeof(OVERLAPPED_ENTRY));
bRet = GetQueuedCompletionStatusEx(iinfo->iocp, iinfo->eov_list, iinfo->capacity, &iinfo->entries_removed, combined_msecs, FALSE);
/* It is mandatory these values are reset before calling GetQueuedCompletionStatusEx */
iinfo->entries_removed = 0;
memset(iinfo->eov_list, 0, iinfo->capacity * sizeof(OVERLAPPED_ENTRY));
bRet = GetQueuedCompletionStatusEx(iinfo->iocp, iinfo->eov_list, iinfo->capacity, &iinfo->entries_removed, combined_msecs, FALSE);
gettimeofday(&nsock_tod, NULL); /* Due to iocp delay */
if (!bRet) {
sock_err = socket_errno();
if (!iinfo->eov && sock_err != WAIT_TIMEOUT) {
nsock_log_error("nsock_loop error %d: %s", sock_err, socket_strerror(sock_err));
nsp->errnum = sock_err;
return -1;
}
}
else {
iterate_through_event_lists(nsp);
gettimeofday(&nsock_tod, NULL); /* Due to iocp delay */
if (!bRet) {
sock_err = socket_errno();
if (!iinfo->eov && sock_err != WAIT_TIMEOUT) {
nsock_log_error("nsock_loop error %d: %s", sock_err, socket_strerror(sock_err));
nsp->errnum = sock_err;
return -1;
}
}
else {
iterate_through_event_lists(nsp);
}
/* iterate through timers and expired events */
process_expired_events(nsp);

View File

@@ -261,6 +261,17 @@ int kqueue_loop(struct npool *nsp, int msec_timeout) {
* timeout) */
combined_msecs = MIN((unsigned)event_msecs, (unsigned)msec_timeout);
#if HAVE_PCAP
#ifndef PCAP_CAN_DO_SELECT
/* do non-blocking read on pcap devices that doesn't support select()
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
// Make the kevent call non-blocking
combined_msecs = 0;
}
#endif
#endif
/* Set up the timeval pointer we will give to kevent() */
memset(&ts, 0, sizeof(struct timespec));
if (combined_msecs >= 0) {
@@ -271,20 +282,9 @@ int kqueue_loop(struct npool *nsp, int msec_timeout) {
ts_p = NULL;
}
#if HAVE_PCAP
#ifndef PCAP_CAN_DO_SELECT
/* do non-blocking read on pcap devices that doesn't support select()
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
} else
#endif
#endif
{
results_left = kevent(kinfo->kqfd, NULL, 0, kinfo->events, kinfo->evlen, ts_p);
if (results_left == -1)
sock_err = socket_errno();
}
results_left = kevent(kinfo->kqfd, NULL, 0, kinfo->events, kinfo->evlen, ts_p);
if (results_left == -1)
sock_err = socket_errno();
gettimeofday(&nsock_tod, NULL); /* Due to kevent delay */
} while (results_left == -1 && sock_err == EINTR); /* repeat only if signal occurred */

View File

@@ -339,14 +339,14 @@ int poll_loop(struct npool *nsp, int msec_timeout) {
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
} else
#endif
#endif
{
results_left = Poll(pinfo->events, pinfo->max_fd + 1, combined_msecs);
if (results_left == -1)
sock_err = socket_errno();
// Make the Poll call non-blocking
combined_msecs = 0;
}
#endif
#endif
results_left = Poll(pinfo->events, pinfo->max_fd + 1, combined_msecs);
if (results_left == -1)
sock_err = socket_errno();
gettimeofday(&nsock_tod, NULL); /* Due to poll delay */
} while (results_left == -1 && sock_err == EINTR); /* repeat only if signal occurred */

View File

@@ -281,6 +281,17 @@ int select_loop(struct npool *nsp, int msec_timeout) {
* timeout) */
combined_msecs = MIN((unsigned)event_msecs, (unsigned)msec_timeout);
#if HAVE_PCAP
#ifndef PCAP_CAN_DO_SELECT
/* do non-blocking read on pcap devices that doesn't support select()
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
// Make the select call non-blocking
combined_msecs = 0;
}
#endif
#endif
/* Set up the timeval pointer we will give to select() */
memset(&select_tv, 0, sizeof(select_tv));
if (combined_msecs > 0) {
@@ -295,27 +306,16 @@ int select_loop(struct npool *nsp, int msec_timeout) {
select_tv_p = NULL;
}
#if HAVE_PCAP
#ifndef PCAP_CAN_DO_SELECT
/* do non-blocking read on pcap devices that doesn't support select()
* If there is anything read, just leave this loop. */
if (pcap_read_on_nonselect(nsp)) {
/* okay, something was read. */
} else
#endif
#endif
{
/* Set up the descriptors for select */
sinfo->fds_results_r = sinfo->fds_master_r;
sinfo->fds_results_w = sinfo->fds_master_w;
sinfo->fds_results_x = sinfo->fds_master_x;
/* Set up the descriptors for select */
sinfo->fds_results_r = sinfo->fds_master_r;
sinfo->fds_results_w = sinfo->fds_master_w;
sinfo->fds_results_x = sinfo->fds_master_x;
results_left = fselect(sinfo->max_sd + 1, &sinfo->fds_results_r,
&sinfo->fds_results_w, &sinfo->fds_results_x, select_tv_p);
results_left = fselect(sinfo->max_sd + 1, &sinfo->fds_results_r,
&sinfo->fds_results_w, &sinfo->fds_results_x, select_tv_p);
if (results_left == -1)
sock_err = socket_errno();
}
if (results_left == -1)
sock_err = socket_errno();
gettimeofday(&nsock_tod, NULL); /* Due to select delay */
} while (results_left == -1 && sock_err == EINTR); /* repeat only if signal occurred */