mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 14:11:29 +00:00
Switch from pcap_next to pcap_next_ex to check for errors
This change supports #1394. When the network goes down, Nmap ought to stop instead of slowing to an infinite crawl.
This commit is contained in:
@@ -955,7 +955,7 @@ int my_pcap_get_selectable_fd(pcap_t *p) {
|
||||
fd is selectable? If not, it's possible for the fd to become selectable, then
|
||||
for pcap_dispatch to buffer two or more frames, and return only the first one
|
||||
Because select doesn't know about pcap's buffer, the fd does not become
|
||||
selectable again, even though another pcap_next would succeed. On these
|
||||
selectable again, even though another pcap_next_ex would succeed. On these
|
||||
platforms, we must do a non-blocking read from the fd before doing a select
|
||||
on the fd.
|
||||
|
||||
@@ -4172,7 +4172,7 @@ int datalink_offset(int datalink)
|
||||
the function returns 0 and the output parameters are undefined. */
|
||||
static int read_reply_pcap(pcap_t *pd, long to_usec,
|
||||
bool (*accept_callback)(const unsigned char *, const struct pcap_pkthdr *, int, size_t),
|
||||
unsigned char **p, struct pcap_pkthdr *head, struct timeval *rcvdtime,
|
||||
const unsigned char **p, struct pcap_pkthdr **head, struct timeval *rcvdtime,
|
||||
int *datalink, size_t *offset)
|
||||
{
|
||||
static int warning = 0;
|
||||
@@ -4207,6 +4207,7 @@ static int read_reply_pcap(pcap_t *pd, long to_usec,
|
||||
do {
|
||||
|
||||
*p = NULL;
|
||||
int pcap_status = 0;
|
||||
/* It may be that protecting this with !pcap_selectable_fd_one_to_one is not
|
||||
necessary, that it is always safe to do a nonblocking read in this way on
|
||||
all platforms. But I have only tested it on Solaris. */
|
||||
@@ -4217,22 +4218,32 @@ static int read_reply_pcap(pcap_t *pd, long to_usec,
|
||||
assert(nonblock == 0);
|
||||
rc = pcap_setnonblock(pd, 1, NULL);
|
||||
assert(rc == 0);
|
||||
*p = (u8 *) pcap_next(pd, head);
|
||||
pcap_status = pcap_next_ex(pd, head, p);
|
||||
rc = pcap_setnonblock(pd, nonblock, NULL);
|
||||
assert(rc == 0);
|
||||
}
|
||||
|
||||
if (*p == NULL) {
|
||||
/* Nonblocking pcap_next didn't get anything. */
|
||||
if (pcap_status == PCAP_ERROR) {
|
||||
// TODO: Gracefully end the scan.
|
||||
netutil_fatal("Error from pcap_next_ex: %s\n", pcap_geterr(pd));
|
||||
}
|
||||
|
||||
if (pcap_status == 0 || *p == NULL) {
|
||||
/* Nonblocking pcap_next_ex didn't get anything. */
|
||||
if (pcap_select(pd, to_usec) == 0)
|
||||
timedout = 1;
|
||||
else
|
||||
*p = (u8 *) pcap_next(pd, head);
|
||||
pcap_status = pcap_next_ex(pd, head, p);
|
||||
}
|
||||
|
||||
if (*p != NULL && accept_callback(*p, head, *datalink, *offset)) {
|
||||
if (pcap_status == PCAP_ERROR) {
|
||||
// TODO: Gracefully end the scan.
|
||||
netutil_fatal("Error from pcap_next_ex: %s\n", pcap_geterr(pd));
|
||||
}
|
||||
|
||||
if (pcap_status == 1 && *p != NULL && accept_callback(*p, *head, *datalink, *offset)) {
|
||||
break;
|
||||
} else if (*p == NULL) {
|
||||
} else if (pcap_status == 0 || *p == NULL) {
|
||||
/* Should we timeout? */
|
||||
if (to_usec == 0) {
|
||||
timedout = 1;
|
||||
@@ -4264,9 +4275,9 @@ static int read_reply_pcap(pcap_t *pd, long to_usec,
|
||||
gettimeofday(&tv_end, NULL);
|
||||
*rcvdtime = tv_end;
|
||||
#else
|
||||
rcvdtime->tv_sec = head->ts.tv_sec;
|
||||
rcvdtime->tv_usec = head->ts.tv_usec;
|
||||
assert(head->ts.tv_sec);
|
||||
rcvdtime->tv_sec = (*head)->ts.tv_sec;
|
||||
rcvdtime->tv_usec = (*head)->ts.tv_usec;
|
||||
assert((*head)->ts.tv_sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4308,8 +4319,8 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac,
|
||||
struct in_addr *senderIP, long to_usec,
|
||||
struct timeval *rcvdtime,
|
||||
void (*trace_callback)(int, const u8 *, u32, struct timeval *)) {
|
||||
unsigned char *p;
|
||||
struct pcap_pkthdr head;
|
||||
const unsigned char *p;
|
||||
struct pcap_pkthdr *head;
|
||||
int datalink;
|
||||
size_t offset;
|
||||
int rc;
|
||||
@@ -4360,8 +4371,8 @@ int read_ns_reply_pcap(pcap_t *pd, u8 *sendermac,
|
||||
struct sockaddr_in6 *senderIP, long to_usec,
|
||||
struct timeval *rcvdtime,
|
||||
void (*trace_callback)(int, const u8 *, u32, struct timeval *)) {
|
||||
unsigned char *p;
|
||||
struct pcap_pkthdr head;
|
||||
const unsigned char *p;
|
||||
struct pcap_pkthdr *head;
|
||||
int datalink;
|
||||
size_t offset;
|
||||
int rc;
|
||||
|
||||
Reference in New Issue
Block a user