diff --git a/scan_engine.cc b/scan_engine.cc index 9398ffd3d..fcf4774da 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -152,6 +152,18 @@ extern NmapOps o; extern "C" int g_has_npcap_loopback; #endif + +int HssPredicate::operator() (HostScanStats *lhs, HostScanStats *rhs) { + return 0 > sockaddr_storage_cmp(lhs->target->TargetSockAddr(), rhs->target->TargetSockAddr()); +} + +int SockAddrPredicate::operator() (HostScanStats *lhs, HostScanStats *rhs) { + const struct sockaddr_storage *lss, *rss; + lss = (lhs) ? lhs->target->TargetSockAddr() : ss; + rss = (rhs) ? rhs->target->TargetSockAddr() : ss; + return 0 > sockaddr_storage_cmp(lss, rss); +} + void UltraScanInfo::log_overall_rates(int logt) { log_write(logt, "Overall sending rates: %.2f packets / s", send_rate_meter.getOverallPacketRate(&now)); if (send_rate_meter.getNumBytes() > 0) @@ -751,14 +763,19 @@ UltraScanInfo::UltraScanInfo() { } UltraScanInfo::~UltraScanInfo() { - while (!incompleteHosts.empty()) { - delete incompleteHosts.front(); - incompleteHosts.pop_front(); + std::set::iterator hostI; + + for (hostI = incompleteHosts.begin(); hostI != incompleteHosts.end(); hostI++) { + delete *hostI; } - while (!completedHosts.empty()) { - delete completedHosts.front(); - completedHosts.pop_front(); + + for (hostI = completedHosts.begin(); hostI != completedHosts.end(); hostI++) { + delete *hostI; } + + incompleteHosts.clear(); + completedHosts.clear(); + delete gstats; delete SPM; if (rawsd >= 0) { @@ -805,7 +822,7 @@ HostScanStats *UltraScanInfo::nextIncompleteHost() { /* Return a number between 0.0 and 1.0 inclusive indicating how much of the scan is done. */ double UltraScanInfo::getCompletionFraction() { - std::list::iterator hostI; + std::set::iterator hostI; double total; /* Add 1 for each completed host. */ @@ -958,7 +975,7 @@ void UltraScanInfo::Init(std::vector &Targets, struct scan_lists *pts, } hss = new HostScanStats(Targets[targetno], this); - incompleteHosts.push_back(hss); + incompleteHosts.insert(hss); } numInitialTargets = Targets.size(); nextI = incompleteHosts.begin(); @@ -1062,7 +1079,7 @@ unsigned int UltraScanInfo::numProbesPerHost() { bool UltraScanInfo::sendOK(struct timeval *when) { struct timeval lowhtime = {0}; struct timeval tmptv; - std::list::iterator host; + std::set::iterator host; bool ggood = false; bool thisHostGood = false; bool foundgood = false; @@ -1120,27 +1137,23 @@ bool UltraScanInfo::sendOK(struct timeval *when) { /* Find a HostScanStats by its IP address in the incomplete and completed lists. Returns NULL if none are found. */ HostScanStats *UltraScanInfo::findHost(struct sockaddr_storage *ss) { - std::list::iterator hss; - struct sockaddr_storage target_addr; - size_t target_addr_len; + std::set::iterator hss; - for (hss = incompleteHosts.begin(); hss != incompleteHosts.end(); hss++) { - target_addr_len = sizeof(target_addr); - (*hss)->target->TargetSockAddr(&target_addr, &target_addr_len); - if (sockaddr_storage_cmp(&target_addr, ss) == 0) { - if (o.debugging > 2) - log_write(LOG_STDOUT, "Found %s in incomplete hosts list.\n", (*hss)->target->targetipstr()); - return *hss; - } + SockAddrPredicate p(ss); + HostScanStats *fakeHss = NULL; + + hss = std::lower_bound(incompleteHosts.begin(), incompleteHosts.end(), fakeHss, p); + if (hss != incompleteHosts.end()) { + if (o.debugging > 2) + log_write(LOG_STDOUT, "Found %s in incomplete hosts list.\n", (*hss)->target->targetipstr()); + return *hss; } - for (hss = completedHosts.begin(); hss != completedHosts.end(); hss++) { - target_addr_len = sizeof(target_addr); - (*hss)->target->TargetSockAddr(&target_addr, &target_addr_len); - if (sockaddr_storage_cmp(&target_addr, ss) == 0) { - if (o.debugging > 2) - log_write(LOG_STDOUT, "Found %s in completed hosts list.\n", (*hss)->target->targetipstr()); - return *hss; - } + + hss = std::lower_bound(completedHosts.begin(), completedHosts.end(), fakeHss, p); + if (hss != completedHosts.end()) { + if (o.debugging > 2) + log_write(LOG_STDOUT, "Found %s in completed hosts list.\n", (*hss)->target->targetipstr()); + return *hss; } return NULL; @@ -1150,7 +1163,7 @@ HostScanStats *UltraScanInfo::findHost(struct sockaddr_storage *ss) { is here to replace numIncompleteHosts() < n, which would have to walk through the entire list. */ bool UltraScanInfo::numIncompleteHostsLessThan(unsigned int n) { - std::list::iterator hostI; + std::set::iterator hostI; unsigned int count; count = 0; @@ -1170,7 +1183,7 @@ static bool pingprobe_is_better(const probespec *new_probe, int new_state, list, and remove any hosts from completedHosts which have exceeded their lifetime. Returns the number of hosts removed. */ int UltraScanInfo::removeCompletedHosts() { - std::list::iterator hostI, nxt; + std::set::iterator hostI, nxt; HostScanStats *hss = NULL; int hostsRemoved = 0; bool timedout = false; @@ -1236,7 +1249,7 @@ int UltraScanInfo::removeCompletedHosts() { } } hss->completiontime = now; - completedHosts.push_front(hss); + completedHosts.insert(hss); incompleteHosts.erase(hostI); hostsRemoved++; /* Consider making this host the new global ping host during its @@ -2280,7 +2293,7 @@ static void sendGlobalPingProbe(UltraScanInfo *USI) { } static void doAnyPings(UltraScanInfo *USI) { - std::list::iterator hostI; + std::set::iterator hostI; HostScanStats *hss = NULL; gettimeofday(&USI->now, NULL); @@ -2355,7 +2368,7 @@ static void retransmitProbe(UltraScanInfo *USI, HostScanStats *hss, /* Go through the ProbeQueue of each host, identify any timed out probes, then try to retransmit them as appropriate */ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) { - std::list::iterator hostI; + std::set::iterator hostI; std::list::iterator probeI; /* A cache of the last processed probe from each host, to avoid re-examining a bunch of probes to find the next one that needs to be retransmitted. */ @@ -2435,8 +2448,7 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) { /* Print occasional remaining time estimates, as well as debugging information */ static void printAnyStats(UltraScanInfo *USI) { - - std::list::iterator hostI; + std::set::iterator hostI; HostScanStats *hss; struct ultra_timing_vals hosttm; @@ -2506,7 +2518,7 @@ static void waitForResponses(UltraScanInfo *USI) { /* Go through the data structures, making appropriate changes (such as expiring probes, noting when hosts are complete, etc. */ static void processData(UltraScanInfo *USI) { - std::list::iterator hostI; + std::set::iterator hostI; std::list::iterator probeI, nextProbeI; HostScanStats *host = NULL; UltraProbe *probe = NULL; diff --git a/scan_engine.h b/scan_engine.h index 3bc72934e..a4da9d9e9 100644 --- a/scan_engine.h +++ b/scan_engine.h @@ -135,6 +135,8 @@ #include "tcpip.h" #include #include +#include +#include struct probespec_tcpdata { u16 dport; @@ -649,6 +651,20 @@ struct ultra_scan_performance_vars : public scan_performance_vars { void init(); }; +struct HssPredicate { +public: + int operator() (HostScanStats *lhs, HostScanStats *rhs); +}; + +struct SockAddrPredicate { +public: + SockAddrPredicate(struct sockaddr_storage *ss) { + this->ss = ss; + } + int operator() (HostScanStats *lhs, HostScanStats *rhs); + struct sockaddr_storage *ss; +}; + class UltraScanInfo { public: UltraScanInfo(); @@ -730,11 +746,11 @@ public: /* Any function which messes with (removes elements from) incompleteHosts may have to manipulate nextI */ - std::list incompleteHosts; + std::set incompleteHosts; /* Hosts are moved from incompleteHosts to completedHosts as they are completed. We keep them around because sometimes responses come back very late, after we consider a host completed. */ - std::list completedHosts; + std::set completedHosts; /* How long (in msecs) we keep a host in completedHosts */ unsigned int completedHostLifetime; /* The last time we went through completedHosts to remove hosts */ @@ -751,7 +767,7 @@ public: private: unsigned int numInitialTargets; - std::list::iterator nextI; + std::set::iterator nextI; }; diff --git a/scan_engine_connect.cc b/scan_engine_connect.cc index c8c27e367..980ff78ee 100644 --- a/scan_engine_connect.cc +++ b/scan_engine_connect.cc @@ -479,7 +479,7 @@ bool do_one_select_round(UltraScanInfo *USI, struct timeval *stime) { int timeleft; ConnectScanInfo *CSI = USI->gstats->CSI; int sd; - std::list::iterator hostI; + std::set::iterator hostI; HostScanStats *host; UltraProbe *probe = NULL; int optval; @@ -520,7 +520,7 @@ bool do_one_select_round(UltraScanInfo *USI, struct timeval *stime) { and find the relevant ones. Note the peculiar structure of the loop--we iterate through both incompleteHosts and completedHosts, because global timing pings are sent to hosts in completedHosts. */ - std::list::iterator incompleteHostI, completedHostI; + std::set::iterator incompleteHostI, completedHostI; incompleteHostI = USI->incompleteHosts.begin(); completedHostI = USI->completedHosts.begin(); while ((incompleteHostI != USI->incompleteHosts.end()