1
0
mirror of https://github.com/nmap/nmap.git synced 2026-02-09 23:16:32 +00:00

Consolidate duplicate functions read_na_pcap and read_ns_reply_pcap.

This commit is contained in:
dmiller
2020-01-13 23:33:30 +00:00
parent 4ffeb09ad3
commit 86f80305a1
5 changed files with 17 additions and 95 deletions

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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");

View File

@@ -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.

View File

@@ -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