From 875a51fb0f2001f99e4f1c593246d9a429869c0f Mon Sep 17 00:00:00 2001 From: dmiller Date: Fri, 15 May 2020 18:18:18 +0000 Subject: [PATCH] Be more parallel with ARP discovery Two essential changes: 1. (ab)Use the ratelimit detection feature to hold off sending retransmissions, preferring to send new ARP probes. Late responses will still be recorded, but no longer counted as drops. This also gives each target the longest amount of time to respond. 2. Send timing pings much more frequently. Since we're not sending any retransmissions until timeout + ratelimit, we wouldn't otherwise have any data on drops in order to speed up or slow down. Results are faster ARP scans with fewer missed targets. See #92. --- scan_engine.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scan_engine.cc b/scan_engine.cc index 40210ab60..ac66eadb5 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -166,6 +166,8 @@ extern NmapOps o; extern "C" int g_has_npcap_loopback; #endif +/* How long extra to wait before retransmitting for rate-limit detection */ +#define RLD_TIME_MS 1000 int HssPredicate::operator() (const HostScanStats *lhs, const HostScanStats *rhs) const { const struct sockaddr_storage *lss, *rss; @@ -916,6 +918,7 @@ void UltraScanInfo::Init(std::vector &Targets, struct scan_lists *pts, tcp_scan = udp_scan = sctp_scan = prot_scan = false; ping_scan = noresp_open_scan = ping_scan_arp = ping_scan_nd = false; memset((char *) &ptech, 0, sizeof(ptech)); + perf.init(); switch (scantype) { case FIN_SCAN: case XMAS_SCAN: @@ -963,10 +966,14 @@ void UltraScanInfo::Init(std::vector &Targets, struct scan_lists *pts, case PING_SCAN_ARP: ping_scan = true; ping_scan_arp = true; + /* For ARP and ND scan, we send pings more frequently. Otherwise we can't + * notice drops until we start sending retransmits after RLD_TIME_MS. */ + perf.pingtime = RLD_TIME_MS * 1000 / 4; break; case PING_SCAN_ND: ping_scan = true; ping_scan_nd = true; + perf.pingtime = RLD_TIME_MS * 1000 / 4; break; default: break; @@ -974,8 +981,6 @@ void UltraScanInfo::Init(std::vector &Targets, struct scan_lists *pts, set_default_port_state(Targets, scantype); - perf.init(); - /* Keep a completed host around for a standard TCP MSL (2 min) */ completedHostLifetime = 120000; memset(&lastCompletedHostRemoval, 0, sizeof(lastCompletedHostRemoval)); @@ -2476,10 +2481,10 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) { /* For rate limit detection, we delay the first time a new tryno is seen, as long as we are scanning at least 2 ports */ if (probe->tryno + 1 > (int) host->rld.max_tryno_sent && - USI->gstats->numprobes > 1) { + (USI->gstats->numprobes > 1 || USI->ping_scan_arp || USI->ping_scan_nd)) { host->rld.max_tryno_sent = probe->tryno + 1; host->rld.rld_waiting = true; - TIMEVAL_MSEC_ADD(host->rld.rld_waittime, USI->now, 1000); + TIMEVAL_MSEC_ADD(host->rld.rld_waittime, USI->now, RLD_TIME_MS); } else { host->rld.rld_waiting = false; retransmitProbe(USI, host, probe);