Nmap Development mailing list archives
[PATCH] Save space/time: completedHosts "lifetimes"
From: Kris Katterjohn <katterjohn () gmail com>
Date: Wed, 17 Sep 2008 18:42:38 -0500
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hey everyone, I've been thinking about the completedHosts list used in ultra_scan. It's used to hold the hosts which have completed in case a late reply comes. But if you're doing a larger scan that ends up being quite slow overall, but with hosts completing throughout, keeping these completed hosts wastes quite a lot of space. An example of this situation is a no-ping SYN scan with a large hostgroup (so a single ultra_scan run is slow). And there's also the fact that this list can be traversed (after incompleteHosts) when searching to see if a received packet is for us or not. When doing a large scan, Nmap doesn't have a very strict pcap filter, so there is a potential for the oft traversal of this large list for essentially no gain. It doesn't even need to be that massive of a scan to have completed hosts waiting for a while in this list. I tested with -T3 and -T4, and had hosts completing throughout the ultra_scan run. Any completed hosts would be sitting for a long time using the slower timing options. So I propose (patch attached) limiting the lifetime of these hosts to the standard TCP MSL (two minutes). This should be ample time for any late replies, especially since this is after the normal wait period (which is why the host is classified as "completed"). I would like a shorter time, but I think this value is a good median for making sure there's more than enough time for a reply, and still removing hosts from the list often. I make sure not to remove a host if it's the one used for port-scan pings, since I don't think anything stops it from entering this list. Since one issue is traversing this large list a lot, I have it set to only run through the list to remove hosts every 1/2 the lifetime, which would be once a minute per my patch. And the further along in the scan these traversals occur, the smaller this list will likely be compared to the list currently traversed. This seems to work great in my testing, with a lot of hosts being removed from the list long before the ultra_scan run is over. But I'm certainly not a master of the ultra_scan code, so a subtle bug could have snuck it. Or a more obvious one I just haven't run into. Or maybe there is another reason all of these hosts are kept around the whole time that I'm not seeing. So if you could test the patch out and let me know how it goes (especially if it causes problems), I'd appreciate it. Thanks, Kris Katterjohn -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iQIVAwUBSNGV6/9K37xXYl36AQLN7xAApuRxUnwPLlCvi7Y2zQMV4WaWvm/AHf1o 3oOrDaFqM08DMqtlBqeB7CpOw8MCkkXMjjdaSVUuP5RicG4+pltFqGIkMy4GQO0E mRgR1SJe04XtcggciEtUgi8h8R0ddnK2ivilMkW6sbJKk+HSwRmKjoQ6WuX9mewe PmutvzQYQNaOjB+OdWCPOO1LC5VB5BcWX0Ic/Bw7kRy+FiZAlP+3t2ou3DYCglta pfIHNIbbrV6AcTKonPDAQlsUAvtAM8o4NI0jc9/L7Zj/yb0vNW1lTuc3mPxJaROa 6OdG583CDcnak8Ev/7q4OcZpZWisOgvYUjM0WdLi/gRpsazTGC4ThLB4gwQUm1N/ fayLXm2NlHTkPpFmYUX/5wZzwu8ACc9NF5CPl4hWfk5Zyrq5juZWhmQR/OhRAVLw mEDunZbWg0wWhXyQFY/ebYm0cQAtsrwdcPggIxODhAHOTomNuCAhKsJxzKbJpFZI Lp9OPHVq2lVTCNhiSsz/igdcAAK3fiERmLzFnHbfeqGapv921hBaWmG7SU4d5Hub Z7C1Kio0InpVGydnIB6ZERwfMVT/G0I93G1+/yn9qZoPouOr/FwVadXMIdUnGS41 M2UbPnn+FX+iGDGbjSyAi6TC8WFFyTSVk3UP9b0yrYrUPJheI+9eaU++DIfAMjCr y9vr1t8l5xA= =HrAr -----END PGP SIGNATURE-----
Index: scan_engine.cc =================================================================== --- scan_engine.cc (revision 10219) +++ scan_engine.cc (working copy) @@ -494,6 +494,7 @@ void retransmitBench(); bool completed(); /* Whether or not the scan of this Target has completed */ + struct timeval completiontime; /* When this Target completed */ /* This function provides the proper cwnd and ccthresh to use. It may differ from versions in timing member var because when no @@ -604,7 +605,8 @@ NULL. */ HostScanStats *nextIncompleteHost(); /* Removes any hosts that have completed their scans from the incompleteHosts - list. Returns the number of hosts removed. */ + list, and remove any hosts from completedHosts which have exceeded their + lifetime. Returns the number of hosts removed. */ int removeCompletedHosts(); /* Find a HostScanStats by its IP address in the incomplete and completed lists. Returns NULL if none are found. */ @@ -641,6 +643,10 @@ completed. We keep them around because sometimes responses come back very late, after we consider a host completed. */ list<HostScanStats *> completedHosts; + /* How long (in msecs) we keep a host in completedHosts */ + unsigned int completedHostLifetime; + /* The last time we went through completedHosts to remove hosts */ + struct timeval lastCompletedHostRemoval; ScanProgressMeter *SPM; PacketRateMeter send_rate_meter; @@ -1083,6 +1089,7 @@ numprobes_sent = 0; numpings_sent = 0; numprobes_replied_to = 0; + memset(&completiontime, 0, sizeof(completiontime)); init_ultra_timing_vals(&timing, TIMING_HOST, 1, &(USI->perf), &USI->now); bench_tryno = 0; memset(&sdn, 0, sizeof(sdn)); @@ -1482,6 +1489,10 @@ init_perf_values(&perf); + /* Keep a completed host around for a standard TCP MSL (2 min) */ + completedHostLifetime = 120000; + memset(&lastCompletedHostRemoval, 0, sizeof(lastCompletedHostRemoval)); + for(targetno = 0; targetno < Targets.size(); targetno++) { if (Targets[targetno]->timedOut(&now)) { num_timedout++; @@ -1678,12 +1689,33 @@ } /* Removes any hosts that have completed their scans from the incompleteHosts - list. Returns the number of hosts removed. */ + list, and remove any hosts from completedHosts which have exceeded their + lifetime. Returns the number of hosts removed. */ int UltraScanInfo::removeCompletedHosts() { list<HostScanStats *>::iterator hostI, nxt; HostScanStats *hss = NULL; int hostsRemoved = 0; bool timedout = false; + + /* We don't want to run this all of the time */ + if ((unsigned) TIMEVAL_MSEC_SUBTRACT(now, lastCompletedHostRemoval) > completedHostLifetime / 2) { + for (hostI = completedHosts.begin(); hostI != completedHosts.end(); hostI = nxt) { + nxt = hostI; + nxt++; + hss = (*hostI); + + /* Keep it if it's our port scan ping host */ + if (hss == gstats->pinghost) + continue; + + if ((unsigned) TIMEVAL_MSEC_SUBTRACT(now, hss->completiontime) > completedHostLifetime) { + completedHosts.erase(hostI); + hostsRemoved++; + } + } + lastCompletedHostRemoval = now; + } + for(hostI = incompleteHosts.begin(); hostI != incompleteHosts.end(); hostI = nxt) { nxt = hostI; @@ -1722,6 +1754,7 @@ log_write(LOG_PLAIN, "* %s\n", probespec2ascii((probespec *) (*iter)->pspec(), tmpbuf, sizeof(tmpbuf))); } } + hss->completiontime = now; completedHosts.push_front(hss); incompleteHosts.erase(hostI); hostsRemoved++;
_______________________________________________ Sent through the nmap-dev mailing list http://cgi.insecure.org/mailman/listinfo/nmap-dev Archived at http://SecLists.Org
Current thread:
- [PATCH] Save space/time: completedHosts "lifetimes" Kris Katterjohn (Sep 17)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" David Fifield (Sep 29)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" Kris Katterjohn (Sep 29)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" David Fifield (Sep 29)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" Brandon Enright (Sep 29)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" Kris Katterjohn (Sep 29)
- Re: [PATCH] Save space/time: completedHosts "lifetimes" David Fifield (Sep 29)