1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-22 07:29:01 +00:00

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.
This commit is contained in:
dmiller
2020-05-15 18:18:18 +00:00
parent bfef89e943
commit 875a51fb0f

View File

@@ -166,6 +166,8 @@ extern NmapOps o;
extern "C" int g_has_npcap_loopback; extern "C" int g_has_npcap_loopback;
#endif #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 { int HssPredicate::operator() (const HostScanStats *lhs, const HostScanStats *rhs) const {
const struct sockaddr_storage *lss, *rss; const struct sockaddr_storage *lss, *rss;
@@ -916,6 +918,7 @@ void UltraScanInfo::Init(std::vector<Target *> &Targets, struct scan_lists *pts,
tcp_scan = udp_scan = sctp_scan = prot_scan = false; tcp_scan = udp_scan = sctp_scan = prot_scan = false;
ping_scan = noresp_open_scan = ping_scan_arp = ping_scan_nd = false; ping_scan = noresp_open_scan = ping_scan_arp = ping_scan_nd = false;
memset((char *) &ptech, 0, sizeof(ptech)); memset((char *) &ptech, 0, sizeof(ptech));
perf.init();
switch (scantype) { switch (scantype) {
case FIN_SCAN: case FIN_SCAN:
case XMAS_SCAN: case XMAS_SCAN:
@@ -963,10 +966,14 @@ void UltraScanInfo::Init(std::vector<Target *> &Targets, struct scan_lists *pts,
case PING_SCAN_ARP: case PING_SCAN_ARP:
ping_scan = true; ping_scan = true;
ping_scan_arp = 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; break;
case PING_SCAN_ND: case PING_SCAN_ND:
ping_scan = true; ping_scan = true;
ping_scan_nd = true; ping_scan_nd = true;
perf.pingtime = RLD_TIME_MS * 1000 / 4;
break; break;
default: default:
break; break;
@@ -974,8 +981,6 @@ void UltraScanInfo::Init(std::vector<Target *> &Targets, struct scan_lists *pts,
set_default_port_state(Targets, scantype); set_default_port_state(Targets, scantype);
perf.init();
/* Keep a completed host around for a standard TCP MSL (2 min) */ /* Keep a completed host around for a standard TCP MSL (2 min) */
completedHostLifetime = 120000; completedHostLifetime = 120000;
memset(&lastCompletedHostRemoval, 0, sizeof(lastCompletedHostRemoval)); 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 /* For rate limit detection, we delay the first time a new tryno
is seen, as long as we are scanning at least 2 ports */ is seen, as long as we are scanning at least 2 ports */
if (probe->tryno + 1 > (int) host->rld.max_tryno_sent && 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.max_tryno_sent = probe->tryno + 1;
host->rld.rld_waiting = true; 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 { } else {
host->rld.rld_waiting = false; host->rld.rld_waiting = false;
retransmitProbe(USI, host, probe); retransmitProbe(USI, host, probe);