diff --git a/libnetutil/netutil.cc b/libnetutil/netutil.cc index c872f4868..38b423d1a 100644 --- a/libnetutil/netutil.cc +++ b/libnetutil/netutil.cc @@ -4415,17 +4415,13 @@ static bool accept_ns(const unsigned char *p, const struct pcap_pkthdr *head, int datalink, size_t offset) { struct icmpv6_hdr *icmp6_header; - struct icmpv6_msg_nd *na; - if (head->caplen < offset + IP6_HDR_LEN + 32) + if (head->caplen < offset + IP6_HDR_LEN + ICMPV6_HDR_LEN) return false; icmp6_header = (struct icmpv6_hdr *)(p + offset + IP6_HDR_LEN); - na = (struct icmpv6_msg_nd *)(p + offset + IP6_HDR_LEN + ICMPV6_HDR_LEN); return icmp6_header->icmpv6_type == ICMPV6_NEIGHBOR_ADVERTISEMENT && - icmp6_header->icmpv6_code == 0 && - na->icmpv6_option_type == 2 && - na->icmpv6_option_length == 1; + icmp6_header->icmpv6_code == 0; } /* Attempts to read one IPv6/Ethernet Neighbor Solicitation reply packet from the pcap @@ -4439,7 +4435,7 @@ static bool accept_ns(const unsigned char *p, const struct pcap_pkthdr *head, by Nmap only. Any other calling this should pass NULL instead. */ int read_ns_reply_pcap(pcap_t *pd, u8 *sendermac, struct sockaddr_in6 *senderIP, long to_usec, - struct timeval *rcvdtime, + struct timeval *rcvdtime, bool *has_mac, void (*trace_callback)(int, const u8 *, u32, struct timeval *)) { const unsigned char *p; struct pcap_pkthdr *head; @@ -4453,7 +4449,16 @@ int read_ns_reply_pcap(pcap_t *pd, u8 *sendermac, return 0; na = (struct icmpv6_msg_nd *)(p + offset + IP6_HDR_LEN + ICMPV6_HDR_LEN); - memcpy(sendermac, &na->icmpv6_mac, 6); + if (head->caplen >= ((unsigned char *)na - p) + sizeof(struct icmpv6_msg_nd) && + na->icmpv6_option_type == 2 && + na->icmpv6_option_length == 1) { + *has_mac = true; + memcpy(sendermac, &na->icmpv6_mac, 6); + } + else { + *has_mac = false; + } + senderIP->sin6_family = AF_INET6; memcpy(&senderIP->sin6_addr.s6_addr, &na->icmpv6_target, 16); if (trace_callback != NULL) { @@ -4491,6 +4496,7 @@ bool doND(const char *dev, const u8 *srcmac, int timeleft; int listenrounds; int rc; + bool has_mac; pcap_t *pd; struct sockaddr_storage rcvdIP; rcvdIP.ss_family = AF_INET6; @@ -4566,7 +4572,7 @@ bool doND(const char *dev, const u8 *srcmac, listenrounds++; /* Now listen until we reach our next timeout or get an answer */ rc = read_ns_reply_pcap(pd, targetmac, (struct sockaddr_in6 *) &rcvdIP, timeleft, - &rcvdtime, traceND_callback); + &rcvdtime, &has_mac, traceND_callback); if (rc == -1) netutil_fatal("%s: Received -1 response from read_ns_reply_pcap", __func__); if (rc == 1) { diff --git a/libnetutil/netutil.h b/libnetutil/netutil.h index 51e17f81a..617cf9de6 100644 --- a/libnetutil/netutil.h +++ b/libnetutil/netutil.h @@ -580,7 +580,7 @@ int read_arp_reply_pcap(pcap_t *pd, u8 *sendermac, void (*traceArp_callback)(int, const u8 *, u32 , struct timeval *)); int read_ns_reply_pcap(pcap_t *pd, u8 *sendermac, struct sockaddr_in6 *senderIP, long to_usec, - struct timeval *rcvdtime, + struct timeval *rcvdtime, bool *has_mac, void (*traceArp_callback)(int, const u8 *, u32 , struct timeval *)); /* Attempts to read one IP packet from the pcap descriptor pd. Input parameters are pd, diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index 89652dc01..0541cff0b 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -1660,7 +1660,7 @@ bool get_ns_result(UltraScanInfo *USI, struct timeval *stime) { to_usec = TIMEVAL_SUBTRACT(*stime, USI->now); if (to_usec < 2000) to_usec = 2000; - rc = read_na_pcap(USI->pd, rcvdmac, &rcvdIP, to_usec, &rcvdtime, &has_mac); + rc = read_ns_reply_pcap(USI->pd, rcvdmac, &rcvdIP, to_usec, &rcvdtime, &has_mac, PacketTrace::traceND); gettimeofday(&USI->now, NULL); if (rc == -1) fatal("Received -1 response from read_arp_reply_pcap"); diff --git a/tcpip.cc b/tcpip.cc index 78d5b91c7..174373b38 100644 --- a/tcpip.cc +++ b/tcpip.cc @@ -1620,87 +1620,6 @@ const u8 *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec, return p; } -/* Attempts to read one IPv6 Neighbor Solicitation reply packet from the pcap - descriptor pd. If it receives one, fills in sendermac (must pass - in 6 bytes), senderIP, and rcvdtime (can be NULL if you don't care) - and returns 1. If it times out and reads no Neighbor Advertisement, returns - 0. to_usec is the timeout period in microseconds. Use 0 to avoid - blocking to the extent possible. Returns -1 or exits if there is - an error. The last parameter is a pointer to a callback function - that can be used for packet tracing. This is intended to be used - by Nmap only. Any other calling this should pass NULL instead. */ -int read_na_pcap(pcap_t *pd, u8 *sendermac, struct sockaddr_in6 *senderIP, long to_usec, - struct timeval *rcvdtime, bool *has_mac) { - const struct ip *ip_tmp; - struct icmpv6_hdr *icmp6_header; - struct icmpv6_msg_nd *na; - struct timeval tv_start, tv_end; - const void *data = NULL; - unsigned int datalen; - static int warning = 0; - int timedout = 0; - struct abstract_ip_hdr hdr; - struct link_header linknfo; - - - if (to_usec < 0) { - if (!warning) { - warning = 1; - error("WARNING: Negative timeout value (%lu) passed to %s() -- using 0", to_usec, __func__); - } - to_usec = 0; - } - - if (to_usec > 0) { - gettimeofday(&tv_start, NULL); - } - - do { - ip_tmp = (struct ip *) readip_pcap(pd, &datalen, to_usec, rcvdtime, &linknfo, true); - if (ip_tmp) { //Check Neighbor Advertisement Packet. - /* OK, we got a packet. Most packet validity tests are taken care - * of in readip_pcap, so this is simple - */ - data = ip_get_data(ip_tmp, &datalen, &hdr); - if (data == NULL) - continue; - if (hdr.proto == IPPROTO_ICMPV6) { - icmp6_header = (struct icmpv6_hdr *)data; - na = (struct icmpv6_msg_nd *) ((unsigned char*)data + ICMPV6_HDR_LEN); - if (icmp6_header->icmpv6_type == ICMPV6_NEIGHBOR_ADVERTISEMENT && - icmp6_header->icmpv6_code == 0) { - //Set target IPv6 address - senderIP->sin6_family = AF_INET6; - memcpy(&senderIP->sin6_addr.s6_addr, &na->icmpv6_target, 16); - //Set MAC - if (datalen == ICMPV6_HDR_LEN + sizeof(struct icmpv6_msg_nd)) { - if (na->icmpv6_option_type == 2 && na->icmpv6_option_length == 1) { - *has_mac = true; - memcpy(sendermac, &na->icmpv6_mac, 6); - } - } else { - *has_mac = false; - } - } - } - } else { - /* Should we timeout? */ - if (to_usec == 0) { - timedout = 1; - } else if (to_usec > 0) { - gettimeofday(&tv_end, NULL); - if (TIMEVAL_SUBTRACT(tv_end, tv_start) >= to_usec) { - timedout = 1; - } - } - } - } while (!timedout && !ip_tmp); - - if (timedout) - return 0; - return 1; -} - // Returns whether the packet receive time value obtained from libpcap // (and thus by readip_pcap()) should be considered valid. When // invalid (Windows and Amiga), readip_pcap returns the time you called it. diff --git a/tcpip.h b/tcpip.h index afc105144..35c1813ef 100644 --- a/tcpip.h +++ b/tcpip.h @@ -442,9 +442,6 @@ const u8 *readipv4_pcap(pcap_t *pd, unsigned int *len, long to_usec, const u8 *readip_pcap(pcap_t *pd, unsigned int *len, long to_usec, struct timeval *rcvdtime, struct link_header *linknfo, bool validate); -int read_na_pcap(pcap_t *pd, u8 *sendermac, struct sockaddr_in6 *senderIP, long to_usec, - struct timeval *rcvdtime, bool *has_mac); - /* Examines the given tcp packet and obtains the TCP timestamp option information if available. Note that the CALLER must ensure that "tcp" contains a valid header (in particular the th_off must be the