From 6784954eee0697b9b477e03d7e5e2c2bc6118c3c Mon Sep 17 00:00:00 2001 From: david Date: Fri, 25 Jan 2013 06:26:23 +0000 Subject: [PATCH] Use more automatic memory management in nmap_dns.cc. --- Target.cc | 2 +- Target.h | 2 +- nmap.cc | 2 - nmap_dns.cc | 198 +++++++++++++++++++--------------------------------- nmap_dns.h | 3 - 5 files changed, 75 insertions(+), 132 deletions(-) diff --git a/Target.cc b/Target.cc index eaf686fe8..b776a7e14 100644 --- a/Target.cc +++ b/Target.cc @@ -348,7 +348,7 @@ const struct in6_addr *Target::v6sourceip() const { /* You can set to NULL to erase a name or if it failed to resolve -- or just don't call this if it fails to resolve */ -void Target::setHostName(char *name) { +void Target::setHostName(const char *name) { char *p; if (hostname) { free(hostname); diff --git a/Target.h b/Target.h index 07fd522c3..5f0b7bd5d 100644 --- a/Target.h +++ b/Target.h @@ -199,7 +199,7 @@ class Target { away when you setTargetSockAddr(), so make sure you do these in proper order */ - void setHostName(char *name); + void setHostName(const char *name); /* Generates a printable string consisting of the host's IP address and hostname (if available). Eg "www.insecure.org (64.71.184.53)" or "fe80::202:e3ff:fe14:1102". The name is diff --git a/nmap.cc b/nmap.cc index 55b3ec226..e482d5d55 100644 --- a/nmap.cc +++ b/nmap.cc @@ -2128,8 +2128,6 @@ static bool target_needs_new_hostgroup(std::vector &targets, const Tar void nmap_free_mem() { PortList::freePortMap(); cp_free(); - free_dns_servers(); - free_etchosts(); free_services(); AllProbes::service_scan_free(); traceroute_hop_cache_clear(); diff --git a/nmap_dns.cc b/nmap_dns.cc index bac1e868b..763d3eaec 100644 --- a/nmap_dns.cc +++ b/nmap_dns.cc @@ -244,7 +244,7 @@ struct request; struct host_elem; struct dns_server { - char *hostname; + std::string hostname; sockaddr_storage addr; size_t addr_len; nsock_iod nsd; @@ -267,7 +267,7 @@ struct request { }; struct host_elem { - char *name; + std::string name; u32 addr; u8 cache_hits; }; @@ -275,14 +275,14 @@ struct host_elem { //------------------- Globals --------------------- -static std::list servs; +static std::list servs; static std::list new_reqs; static std::list cname_reqs; static int total_reqs; static nsock_pool dnspool=NULL; /* The DNS cache, not just for entries from /etc/hosts. */ -static std::list etchosts[HASH_TABLE_SIZE]; +static std::list etchosts[HASH_TABLE_SIZE]; static int stat_actual, stat_ok, stat_nx, stat_sf, stat_trans, stat_dropped, stat_cname; static struct timeval starttv; @@ -296,7 +296,7 @@ static ScanProgressMeter *SPM; //------------------- Prototypes and macros --------------------- static void put_dns_packet_on_wire(request *req); -static char *lookup_etchosts(u32 ip); +static const char *lookup_etchosts(u32 ip); static void addto_etchosts(u32 ip, const char *hname); #define ACTION_FINISHED 0 @@ -321,19 +321,19 @@ static void output_summary() { static void check_capacities(dns_server *tpserv) { if (tpserv->capacity < CAPACITY_MIN) tpserv->capacity = CAPACITY_MIN; if (tpserv->capacity > CAPACITY_MAX) tpserv->capacity = CAPACITY_MAX; - if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "CAPACITY <%s> = %d\n", tpserv->hostname, tpserv->capacity); + if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "CAPACITY <%s> = %d\n", tpserv->hostname.c_str(), tpserv->capacity); } // Closes all nsis created in connect_dns_servers() static void close_dns_servers() { - std::list::iterator serverI; + std::list::iterator serverI; for(serverI = servs.begin(); serverI != servs.end(); serverI++) { - if ((*serverI)->connected) { - nsi_delete((*serverI)->nsd, NSOCK_PENDING_SILENT); - (*serverI)->connected = 0; - (*serverI)->to_process.clear(); - (*serverI)->in_process.clear(); + if (serverI->connected) { + nsi_delete(serverI->nsd, NSOCK_PENDING_SILENT); + serverI->connected = 0; + serverI->to_process.clear(); + serverI->in_process.clear(); } } } @@ -355,27 +355,24 @@ static int add_integer_to_dns_packet(char *packet, int c) { // Puts as many packets on the line as capacity will allow static void do_possible_writes() { - std::list::iterator servI; - dns_server *tpserv; + std::list::iterator servI; request *tpreq; for(servI = servs.begin(); servI != servs.end(); servI++) { - tpserv = *servI; - - if (tpserv->write_busy == 0 && tpserv->reqs_on_wire < tpserv->capacity) { + if (servI->write_busy == 0 && servI->reqs_on_wire < servI->capacity) { tpreq = NULL; - if (!tpserv->to_process.empty()) { - tpreq = tpserv->to_process.front(); - tpserv->to_process.pop_front(); + if (!servI->to_process.empty()) { + tpreq = servI->to_process.front(); + servI->to_process.pop_front(); } else if (!new_reqs.empty()) { tpreq = new_reqs.front(); - tpreq->first_server = tpreq->curr_server = tpserv; + tpreq->first_server = tpreq->curr_server = &*servI; new_reqs.pop_front(); } if (tpreq) { if (o.debugging >= TRACE_DEBUG_LEVEL) - log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , tpserv->hostname); + log_write(LOG_STDOUT, "mass_rdns: TRANSMITTING for <%s> (server <%s>)\n", tpreq->targ->targetipstr() , servI->hostname.c_str()); stat_trans++; put_dns_packet_on_wire(tpreq); } @@ -433,11 +430,10 @@ static void put_dns_packet_on_wire(request *req) { // Processes DNS packets that have timed out // Returns time until next read timeout static int deal_with_timedout_reads() { - std::list::iterator servI; - std::list::iterator servItemp; + std::list::iterator servI; + std::list::iterator servItemp; std::list::iterator reqI; std::list::iterator nextI; - dns_server *tpserv; request *tpreq; struct timeval now; int tp, min_timeout = INT_MAX; @@ -448,10 +444,8 @@ static int deal_with_timedout_reads() { SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now); for(servI = servs.begin(); servI != servs.end(); servI++) { - tpserv = *servI; - - nextI = tpserv->in_process.begin(); - if (nextI == tpserv->in_process.end()) continue; + nextI = servI->in_process.begin(); + if (nextI == servI->in_process.end()) continue; do { reqI = nextI++; @@ -461,22 +455,22 @@ static int deal_with_timedout_reads() { if (tp > 0 && tp < min_timeout) min_timeout = tp; if (tp <= 0) { - tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MINOR_DOWN_SCALE); - check_capacities(tpserv); - tpserv->in_process.erase(reqI); - tpserv->reqs_on_wire--; + servI->capacity = (int) (servI->capacity * CAPACITY_MINOR_DOWN_SCALE); + check_capacities(&*servI); + servI->in_process.erase(reqI); + servI->reqs_on_wire--; // If we've tried this server enough times, move to the next one if (read_timeouts[read_timeout_index][tpreq->tries] == -1) { - tpserv->capacity = (int) (tpserv->capacity * CAPACITY_MAJOR_DOWN_SCALE); - check_capacities(tpserv); + servI->capacity = (int) (servI->capacity * CAPACITY_MAJOR_DOWN_SCALE); + check_capacities(&*servI); servItemp = servI; servItemp++; if (servItemp == servs.end()) servItemp = servs.begin(); - tpreq->curr_server = *servItemp; + tpreq->curr_server = &*servItemp; tpreq->tries = 0; tpreq->servers_tried++; @@ -495,17 +489,17 @@ static int deal_with_timedout_reads() { delete tpreq; // **** OR We start at the back of this server's queue - //(*servItemp)->to_process.push_back(tpreq); + //servItemp->to_process.push_back(tpreq); } else { - (*servItemp)->to_process.push_back(tpreq); + servItemp->to_process.push_back(tpreq); } } else { - tpserv->to_process.push_back(tpreq); + servI->to_process.push_back(tpreq); } } - } while (nextI != tpserv->in_process.end()); + } while (nextI != servI->in_process.end()); } @@ -518,15 +512,12 @@ static int deal_with_timedout_reads() { // looking for and update their results as necessary. // Returns non-zero if this matches a query we're looking for static int process_result(u32 ia, char *result, int action, u16 id) { - std::list::iterator servI; + std::list::iterator servI; std::list::iterator reqI; - dns_server *tpserv; request *tpreq; for(servI = servs.begin(); servI != servs.end(); servI++) { - tpserv = *servI; - - for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end(); reqI++) { + for(reqI = servI->in_process.begin(); reqI != servI->in_process.end(); reqI++) { tpreq = *reqI; if (id == tpreq->id) { @@ -535,16 +526,16 @@ static int process_result(u32 ia, char *result, int action, u16 id) { continue; if (action == ACTION_CNAME_LIST || action == ACTION_FINISHED) { - tpserv->capacity += CAPACITY_UP_STEP; - check_capacities(tpserv); + servI->capacity += CAPACITY_UP_STEP; + check_capacities(&*servI); if (result) { tpreq->targ->setHostName(result); addto_etchosts(tpreq->targ->v4hostip()->s_addr, result); } - tpserv->in_process.remove(tpreq); - tpserv->reqs_on_wire--; + servI->in_process.remove(tpreq); + servI->reqs_on_wire--; total_reqs--; @@ -811,8 +802,7 @@ static void connect_evt_handler(nsock_pool nsp, nsock_event evt, void *servers) // Adds DNS servers to the dns_server list. They can be separated by // commas or spaces - NOTE this doesn't actually do any connecting! static void add_dns_server(char *ipaddrs) { - std::list::iterator servI; - dns_server *tpserv; + std::list::iterator servI; char *hostname; struct sockaddr_storage addr; size_t addr_len = sizeof(addr); @@ -823,19 +813,17 @@ static void add_dns_server(char *ipaddrs) { continue; for(servI = servs.begin(); servI != servs.end(); servI++) { - tpserv = *servI; - // Already added! - if (memcmp(&addr, &tpserv->addr, sizeof(addr)) == 0) break; + if (memcmp(&addr, &servI->addr, sizeof(addr)) == 0) break; } // If it hasn't already been added, add it! if (servI == servs.end()) { - tpserv = new dns_server; + dns_server tpserv; - tpserv->hostname = strdup(hostname); - memcpy(&tpserv->addr, &addr, sizeof(addr)); - tpserv->addr_len = addr_len; + tpserv.hostname = hostname; + memcpy(&tpserv.addr, &addr, sizeof(addr)); + tpserv.addr_len = addr_len; servs.push_front(tpserv); @@ -846,46 +834,26 @@ static void add_dns_server(char *ipaddrs) { } -void free_dns_servers() { - std::list::iterator servI; - dns_server *tpserv; - - for(servI = servs.begin(); servI != servs.end();servI++){ - tpserv = *servI; - if(tpserv){ - if(tpserv->hostname) - free(tpserv->hostname); - delete tpserv; - } - } - servs.clear(); -} - - // Creates a new nsi for each DNS server static void connect_dns_servers() { - std::list::iterator serverI; - dns_server *s; - + std::list::iterator serverI; for(serverI = servs.begin(); serverI != servs.end(); serverI++) { - s = *serverI; - - s->nsd = nsi_new(dnspool, NULL); + serverI->nsd = nsi_new(dnspool, NULL); if (o.spoofsource) { struct sockaddr_storage ss; size_t sslen; o.SourceSockAddr(&ss, &sslen); - nsi_set_localaddr(s->nsd, &ss, sslen); + nsi_set_localaddr(serverI->nsd, &ss, sslen); } if (o.ipoptionslen) - nsi_set_ipoptions(s->nsd, o.ipoptions, o.ipoptionslen); - s->reqs_on_wire = 0; - s->capacity = CAPACITY_MIN; - s->write_busy = 0; + nsi_set_ipoptions(serverI->nsd, o.ipoptions, o.ipoptionslen); + serverI->reqs_on_wire = 0; + serverI->capacity = CAPACITY_MIN; + serverI->write_busy = 0; - nsock_connect_udp(dnspool, s->nsd, connect_evt_handler, NULL, (struct sockaddr *) &s->addr, s->addr_len, 53); - nsock_read(dnspool, s->nsd, read_evt_handler, -1, NULL); - s->connected = 1; + nsock_connect_udp(dnspool, serverI->nsd, connect_evt_handler, NULL, (struct sockaddr *) &serverI->addr, serverI->addr_len, 53); + nsock_read(dnspool, serverI->nsd, read_evt_handler, -1, NULL); + serverI->connected = 1; } } @@ -1016,28 +984,11 @@ static void parse_etchosts(const char *fname) { fclose(fp); } -void free_etchosts() { - host_elem *he; - std::list::iterator hi; - int i; - - for(i=0; i < HASH_TABLE_SIZE; i++){ - for(hi = etchosts[i].begin(); hi != etchosts[i].end(); hi++) { - he = *hi; - if(he) { - free(he->name); - delete he; - } - } - etchosts[i].clear(); - } -} - /* Executed when the DNS cache is full, ages entries * and removes any with a cache hit of 0 (the least used) */ -bool remove_and_age(host_elem *host) { - if(host->cache_hits) { - host->cache_hits /=2; +bool remove_and_age(host_elem &host) { + if(host.cache_hits) { + host.cache_hits /=2; return false; } else return true; @@ -1048,8 +999,8 @@ bool remove_and_age(host_elem *host) { * make more space. */ static void addto_etchosts(u32 ip, const char *hname) { static u16 total_size = 0; - std::list::iterator it; - host_elem *he; + std::list::iterator it; + host_elem he; int i; if(lookup_etchosts(ip) != NULL) @@ -1066,26 +1017,23 @@ static void addto_etchosts(u32 ip, const char *hname) { } } } - he = new host_elem; - he->name = strdup(hname); - he->addr = ip; - he->cache_hits = 0; + he.name = hname; + he.addr = ip; + he.cache_hits = 0; etchosts[IP_HASH(ip)].push_back(he); total_size++; } /* Search for a hostname in the cache and increment * its cache hit counter if found */ -static char *lookup_etchosts(u32 ip) { - std::list::iterator hostI; - host_elem *tpelem; +static const char *lookup_etchosts(u32 ip) { + std::list::iterator hostI; int localIP_Hash = IP_HASH(ip); for(hostI = etchosts[localIP_Hash].begin(); hostI != etchosts[localIP_Hash].end(); hostI++) { - tpelem = *hostI; - if (tpelem->addr == ip) { - if(tpelem->cache_hits < UCHAR_MAX) - tpelem->cache_hits++; - return tpelem->name; + if (hostI->addr == ip) { + if(hostI->cache_hits < UCHAR_MAX) + hostI->cache_hits++; + return hostI->name.c_str(); } } return NULL; @@ -1162,7 +1110,7 @@ static void nmap_mass_rdns_core(Target **targets, int num_targets) { std::list::iterator reqI; request *tpreq; int timeout; - char *tpname; + const char *tpname; int i; char spmobuf[1024]; @@ -1372,10 +1320,10 @@ std::list get_dns_servers() { // of servers. assert(o.mass_dns || servs.empty()); - std::list::iterator servI; + std::list::iterator servI; std::list serverList; for(servI = servs.begin(); servI != servs.end(); servI++) { - serverList.push_back(inet_socktop((struct sockaddr_storage *) &(*servI)->addr)); + serverList.push_back(inet_socktop((struct sockaddr_storage *) &servI->addr)); } return serverList; } diff --git a/nmap_dns.h b/nmap_dns.h index a401fd00d..068700b50 100644 --- a/nmap_dns.h +++ b/nmap_dns.h @@ -98,7 +98,4 @@ class Target; void nmap_mass_rdns(Target ** targets, int num_targets); const char *lookup_cached_host(u32 ip); -void free_dns_servers(); -void free_etchosts(); - std::list get_dns_servers();