diff --git a/nping/ProbeMode.cc b/nping/ProbeMode.cc index 5a21a861a..3b72d8811 100644 --- a/nping/ProbeMode.cc +++ b/nping/ProbeMode.cc @@ -1491,14 +1491,46 @@ char *ProbeMode::getBPFFilterString(){ * we might have sent. Returns non-NULL target pointer if found. Otherwise * returns NULL. */ static NpingTarget *is_response_icmp(const unsigned char *packet, unsigned int packetlen) { + const void *data; + unsigned int datalen; + struct abstract_ip_hdr packethdr; NpingTarget *trg; - trg = o.targets.findTarget(getSrcSockAddrFromIPPacket((u8*)packet, packetlen)); - if (trg == NULL) { - trg = o.targets.findTarget(getDestAddrFromICMPPacket((u8*)packet, packetlen)); + /* Parse the outermost IP header (for its source address). */ + datalen = packetlen; + data = ip_get_data(packet, &datalen, &packethdr); + if (data == NULL) + return NULL; + + trg = o.targets.findTarget(&packethdr.src); + if (trg != NULL) + return trg; + + /* If that didn't work, check if this is ICMP with an encapsulated IP + header. */ + if (packethdr.proto == IPPROTO_ICMP) { + struct ip *ip; + unsigned int iplen; + struct sockaddr_storage ss; + struct sockaddr_in *sin = (struct sockaddr_in *) &ss; + + if (datalen < 8) + return NULL; + ip = (struct ip *) ((char *) data + 8); + iplen = datalen - 8; + /* Make sure there is enough header to have a dest address. */ + if (iplen < 20) + return NULL; + if (ip->ip_v != 4) + return NULL; + sin->sin_family = AF_INET; + sin->sin_addr = ip->ip_dst; + trg = o.targets.findTarget(&ss); + + return trg; } - return trg; + return NULL; } diff --git a/nping/utils_net.cc b/nping/utils_net.cc index 6d0b053ab..00211d5a7 100644 --- a/nping/utils_net.cc +++ b/nping/utils_net.cc @@ -1259,36 +1259,6 @@ struct sockaddr_storage *getSrcSockAddrFromIPPacket(u8 *pkt, size_t pktLen){ } /* End of getSrcSockAddrFromPacket() */ -struct sockaddr_storage *getDestAddrFromICMPPacket(u8 *pkt, size_t pktLen){ - static struct sockaddr_storage ss; - struct sockaddr_in *s_ip4=(struct sockaddr_in *)&ss; - struct ip *i4=(struct ip*)pkt; - struct ip *orig_i4=NULL; - memset(&ss, 0, sizeof(struct sockaddr_storage)); - - if(pkt==NULL || pktLen < 48) /* 48 = First IP hdr + ICMP pkt + Embedded IP hdr */ - return NULL; - - if( i4->ip_v == 4 ){ - /* Let's make sure we can trust i4->ip_hl field. We just check if we - * have enough bytes to access the DST Addr of the original IP header that - * is included in the ICMP packet. */ - if ( (size_t)(i4->ip_hl*4 + 8 + 16 + 4) > pktLen ) - return NULL; - /* Let's make sure the ICMP pkt contains an IPv4 packet */ - orig_i4=(struct ip*)( pkt + (8 + i4->ip_hl*4) ); - if( orig_i4->ip_v != 4 ) - return NULL; - s_ip4->sin_family=AF_INET; - memcpy(&(s_ip4->sin_addr.s_addr), pkt + i4->ip_hl*4 + 8 + 16, 4); - return &ss; - } - else { - return NULL; - } -} /* End of getDestAddrFromICMPPacket */ - - diff --git a/nping/utils_net.h b/nping/utils_net.h index 6f43d116e..3c7e1e83a 100644 --- a/nping/utils_net.h +++ b/nping/utils_net.h @@ -142,7 +142,6 @@ int send_packet(NpingTarget *target, int rawfd, u8 *pkt, size_t pktLen); int print_dnet_interface(const struct intf_entry *entry, void *arg) ; int print_interfaces_dnet(); struct sockaddr_storage *getSrcSockAddrFromIPPacket(u8 *pkt, size_t pktLen); -struct sockaddr_storage *getDestAddrFromICMPPacket(u8 *pkt, size_t pktLen); u8 *getUDPheaderLocation(u8 *pkt, size_t pktLen); u8 *getTCPheaderLocation(u8 *pkt, size_t pktLen); u8 getProtoFromIPPacket(u8 *pkt, size_t pktLen);