Index: scan_engine.h =================================================================== --- scan_engine.h (revision 31696) +++ scan_engine.h (working copy) @@ -156,6 +156,14 @@ u8 code; }; +struct ppkt { /* Beginning of ICMP Echo/Timestamp header */ + u8 type; + u8 code; + u16 checksum; + u16 id; + u16 seq; +}; + #define PS_NONE 0 #define PS_TCP 1 #define PS_UDP 2 Index: scan_engine.cc =================================================================== --- scan_engine.cc (revision 31696) +++ scan_engine.cc (working copy) @@ -342,7 +342,7 @@ bool check_tryno_pingseq(unsigned int tryno, unsigned int pingseq) const { return (pingseq == 0 && tryno == this->tryno) || (pingseq > 0 && pingseq == this->pingseq); } - + u16 ident; /* Unique identity of this probe (if used). */ u8 tryno; /* Try (retransmission) number of this probe */ u8 pingseq; /* 0 if this is not a scanping. Otherwise a posative ping seq#. */ /* If true, probe is considered no longer active due to timeout, but it @@ -2527,6 +2527,46 @@ return true; } +static bool icmp_probe_match(const UltraScanInfo *USI, const UltraProbe *probe, + const struct ppkt *ping, + const struct sockaddr_storage *target_src, + const struct sockaddr_storage *src, + const struct sockaddr_storage *dst, + u8 proto, + u32 ipid) { + /* Check if it is ICMP or ICMPV6. */ + if (probe->protocol() != IPPROTO_ICMPV6 && probe->protocol() != IPPROTO_ICMP) + return false; + + /* Ensure the connection info matches. */ + if (sockaddr_storage_cmp(target_src, dst) != 0) + return false; + + /* Don't match a timestamp request with an echo reply, for example. */ + if (proto == IPPROTO_ICMP && + ((ping->type == 0 && probe->pspec()->pd.icmp.type != 8) || + (ping->type == 14 && probe->pspec()->pd.icmp.type != 13) || + (ping->type == 18 && probe->pspec()->pd.icmp.type != 17))) + return false; + if (proto == IPPROTO_ICMPV6 && + (ping->type == 129 && probe->pspec()->pd.icmpv6.type != 128)) + return false; + + /* Sometimes we get false results when scanning localhost with + -p- because we scan localhost with src port = dst port and + see our outgoing packet and think it is a response. */ + if (probe->dport() == probe->sport() && + sockaddr_storage_cmp(src, dst) == 0 && + probe->ipid() == ipid) + return false; /* We saw the packet we ourselves sent */ + + /* Check that the randomly-generated ping ident matches. */ + if (ntohs(ping->id) != probe->ident) + return false; + + return true; +} + static bool tcp_probe_match(const UltraScanInfo *USI, const UltraProbe *probe, const HostScanStats *hss, const struct tcp_hdr *tcp, const struct sockaddr_storage *src, const struct sockaddr_storage *dst, @@ -3656,6 +3696,7 @@ hss->probeSent(packetlen); send_ip_packet(USI->rawsd, ethptr, hss->target->TargetSockAddr(), packet, packetlen); free(packet); + probe->ident = icmp_ident; } } else if (pspec->type == PS_ICMPV6) { struct sockaddr_storage source; @@ -3675,6 +3716,7 @@ hss->probeSent(packetlen); send_ip_packet(USI->rawsd, ethptr, hss->target->TargetSockAddr(), packet, packetlen); free(packet); + probe->ident = icmp_ident; } else assert(0); /* Now that the probe has been sent, add it to the Queue for this host */ @@ -4959,13 +5001,7 @@ struct link_header linkhdr; struct ip *ip_tmp; unsigned int bytes; - struct ppkt { - unsigned char type; - unsigned char code; - unsigned short checksum; - unsigned short id; - unsigned short seq; - } *ping; + struct ppkt *ping; long to_usec; HostScanStats *hss = NULL; std::list::iterator probeI; @@ -5060,31 +5096,9 @@ probeI--; probe = *probeI; - /* Check if it is ICMP or ICMPV6. */ - if (probe->protocol() != IPPROTO_ICMPV6 && probe->protocol() != IPPROTO_ICMP) + if (!icmp_probe_match(USI, probe, ping, &target_src, &hdr.src, &hdr.dst, hdr.proto, hdr.ipid)) continue; - /* Ensure the connection info matches. */ - if (sockaddr_storage_cmp(&target_src, &hdr.dst) != 0) - continue; - /* Don't match a timestamp request with an echo reply, for example. */ - if (hdr.proto == IPPROTO_ICMP && - ((ping->type == 0 && probe->pspec()->pd.icmp.type != 8) || - (ping->type == 14 && probe->pspec()->pd.icmp.type != 13) || - (ping->type == 18 && probe->pspec()->pd.icmp.type != 17))) - continue; - if (hdr.proto == IPPROTO_ICMPV6 && - (ping->type == 129 && probe->pspec()->pd.icmpv6.type != 128)) - continue; - - /* Sometimes we get false results when scanning localhost with - -p- because we scan localhost with src port = dst port and - see our outgoing packet and think it is a response. */ - if (probe->dport() == probe->sport() && - sockaddr_storage_cmp(&hdr.src, &hdr.dst) == 0 && - probe->ipid() == hdr.ipid) - continue; /* We saw the packet we ourselves sent */ - goodone = true; newstate = HOST_UP;