diff --git a/CHANGELOG b/CHANGELOG
index 7b389160f..b45d02cf5 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -13,8 +13,23 @@ o Updated the Windows installer to give an option checkbox for
performing the Nmap performance registry changes. The default is to
do so. Thanks to Adam Vartanian (flooey(a)gmail.com) for the patch.
+o Nmap now provides progress statistics in the XML output in verbose
+ mode. Here are some examples of the format (etc is "estimated time
+ until completion) and times are in unix time_t (seconds since 1970) format:
+
+
+
+
+
+ Thanks to Adam Vartanian (flooey(a)gmail.com) for the patch.
+
o Applied several code cleanup patches from Marek Majkowski.
+o Added --release-memory option, which causes Nmap to release all
+ accessible memory buffers before quitting (rather than let the OS do
+ it). This is only useful for debugging memory leaks.
+
o Fixed a bug related to bogus completion time estimates when you
request an estimate (through runtime interaction) right when Nmap is
starting.a subsystem (such as a port scan or version detection).
diff --git a/NmapOps.h b/NmapOps.h
index 694ab0a9d..be969c275 100644
--- a/NmapOps.h
+++ b/NmapOps.h
@@ -300,6 +300,7 @@ class NmapOps {
stype current_scantype;
bool noninteractive;
+ bool release_memory; /* suggest to release memory before quitting. used to find memory leaks. */
private:
int max_rtt_timeout;
int min_rtt_timeout;
diff --git a/charpool.cc b/charpool.cc
index be470c98a..65b286ab4 100644
--- a/charpool.cc
+++ b/charpool.cc
@@ -122,6 +122,16 @@ static int cp_init(void) {
return 0;
}
+void cp_free(void) {
+ int ccp;
+ for(ccp=0; ccp <= currentcharpool; ccp++)
+ if(charpool[ccp]){
+ free(charpool[ccp]);
+ charpool[ccp] = NULL;
+ }
+ currentcharpool = 0;
+}
+
static inline void cp_grow(void) {
/* Doh! We've got to make room */
if (++currentcharpool > 15) {
diff --git a/charpool.h b/charpool.h
index 10344fb0b..910f1330b 100644
--- a/charpool.h
+++ b/charpool.h
@@ -107,4 +107,7 @@
void *cp_alloc(int sz);
char *cp_strdup(const char *src);
+
+void cp_free(void);
+
#endif
diff --git a/docs/nmap.dtd b/docs/nmap.dtd
index 42b4e51f4..91eb9d7e6 100644
--- a/docs/nmap.dtd
+++ b/docs/nmap.dtd
@@ -45,6 +45,7 @@
+
@@ -71,7 +72,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -202,6 +227,11 @@
fingerprint CDATA #REQUIRED
>
+
+
+
NameIP());
+ ScanProgressMeter SPM(scanname);
if (numports == 0) return; /* nothing to scan for */
if (!proxyName) fatal("Idlescan requires a proxy host");
@@ -988,9 +991,6 @@ void idle_scan(Target *target, u16 *portarray, int numports,
initialize_idleproxy(&proxy, proxyName, target->v4hostip());
}
- if (o.debugging || o.verbose) {
- log_write(LOG_STDOUT, "Initiating Idlescan against %s\n", target->NameIP());
- }
starttime = time(NULL);
/* If we don't have timing infoz for the new target, we'll use values
@@ -1019,11 +1019,9 @@ void idle_scan(Target *target, u16 *portarray, int numports,
}
- if (o.verbose) {
- long timediff = time(NULL) - starttime;
- log_write(LOG_STDOUT, "The Idlescan took %ld %s to scan %d ports.\n",
- timediff, (timediff == 1)? "second" : "seconds", numports);
- }
+ char additional_info[14];
+ snprintf(additional_info, sizeof(additional_info), "%d ports", numports);
+ SPM.endTask(NULL, additional_info);
/* Now we go through the ports which were not determined were scanned
but not determined to be open, and add them in the "closed" state */
diff --git a/nmap.cc b/nmap.cc
index f217989fc..c53ed36b1 100644
--- a/nmap.cc
+++ b/nmap.cc
@@ -109,6 +109,7 @@
#include "NmapOps.h"
#include "MACLookup.h"
#include "nmap_tty.h"
+#include "nmap_dns.h"
#ifdef WIN32
#include "winfix.h"
#endif
@@ -491,6 +492,8 @@ int nmap_main(int argc, char *argv[]) {
{"debug", optional_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{"iflist", no_argument, 0, 0},
+ {"release_memory", no_argument, 0, 0},
+ {"release-memory", no_argument, 0, 0},
{"max_parallelism", required_argument, 0, 'M'},
{"max-parallelism", required_argument, 0, 'M'},
{"min_parallelism", required_argument, 0, 0},
@@ -640,6 +643,8 @@ int nmap_main(int argc, char *argv[]) {
}
} else if (strcmp(long_options[option_index].name, "iflist") == 0 ) {
iflist = true;
+ } else if (strcmp(long_options[option_index].name, "release-memory") == 0 ) {
+ o.release_memory = true;
} else if (optcmp(long_options[option_index].name, "min-parallelism") == 0 ) {
o.min_parallelism = atoi(optarg);
if (o.min_parallelism < 1) fatal("Argument to --min-parallelism must be at least 1!");
@@ -1626,23 +1631,35 @@ int nmap_main(int argc, char *argv[]) {
printfinaloutput();
- if (ports) {
- free(ports->tcp_ports);
- free(ports->udp_ports);
- free(ports->prots);
- free(ports);
- }
+ free_scan_lists(ports);
eth_close_cached();
- /* Free fake argv */
- for(i=0; i < argc; i++)
- free(fakeargv[i]);
- free(fakeargv);
+ if(o.release_memory || o.interactivemode) {
+ /* Free fake argv */
+ for(i=0; i < argc; i++)
+ free(fakeargv[i]);
+ free(fakeargv);
+ nmap_free_mem();
+ }
return 0;
}
+// Free some global memory allocations.
+// This is used for detecting memory leaks.
+void nmap_free_mem() {
+ PortList::freePortMap();
+ cp_free();
+ free_dns_servers();
+ free_etchosts();
+ if(o.reference_FPs){
+ free_fingerprint_file(o.reference_FPs);
+ o.reference_FPs = NULL;
+ }
+ AllProbes::service_scan_free();
+
+}
/* Reads in a (normal or machine format) Nmap log file and gathers enough
state to allow Nmap to continue where it left off. The important things
@@ -1927,6 +1944,14 @@ struct scan_lists *getpts(char *origexpr) {
return ports;
}
+void free_scan_lists(struct scan_lists *ports) {
+ if (ports) {
+ free(ports->tcp_ports);
+ free(ports->udp_ports);
+ free(ports->prots);
+ free(ports);
+ }
+}
void printinteractiveusage() {
printf(
diff --git a/nmap.h b/nmap.h
index 75267cc7f..a11f874b8 100644
--- a/nmap.h
+++ b/nmap.h
@@ -452,6 +452,7 @@ int ftp_anon_connect(struct ftpinfo *ftp);
/* port manipulators */
void getprobepts(char *expr);
struct scan_lists *getpts(char *expr); /* someone stole the name getports()! */
+void free_scan_lists(struct scan_lists *ports);
int getidentinfoz(struct in_addr target, u16 localport, u16 remoteport,
char *owner, int ownersz);
@@ -467,6 +468,8 @@ int listen_icmp(int icmpsock, unsigned short outports[],
/* Renamed main so that interactive mode could preprocess when neccessary */
int nmap_main(int argc, char *argv[]);
+void nmap_free_mem();
+
/* general helper functions */
int parse_targets(struct targets *targets, char *h);
char *statenum2str(int state);
diff --git a/nmap_dns.cc b/nmap_dns.cc
index 49e72a7fb..70438f68e 100644
--- a/nmap_dns.cc
+++ b/nmap_dns.cc
@@ -816,6 +816,21 @@ 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
void connect_dns_servers() {
@@ -969,6 +984,23 @@ static void parse_etchosts(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();
+ }
+}
+
static char *lookup_etchosts(u32 ip) {
std::list::iterator hostI;
@@ -1058,6 +1090,7 @@ static void nmap_mass_rdns_core(Target **targets, int num_targets) {
}
}
+ SPM->endTask(NULL, NULL);
delete SPM;
return;
@@ -1137,6 +1170,8 @@ static void nmap_mass_rdns_core(Target **targets, int num_targets) {
nsock_loop(dnspool, timeout);
}
+ SPM->endTask(NULL, NULL);
+
delete SPM;
close_dns_servers();
@@ -1172,6 +1207,7 @@ static void nmap_mass_rdns_core(Target **targets, int num_targets) {
}
+ SPM->endTask(NULL, NULL);
delete SPM;
cname_reqs.clear();
diff --git a/nmap_dns.h b/nmap_dns.h
index 6b0bda397..3a5d351e8 100644
--- a/nmap_dns.h
+++ b/nmap_dns.h
@@ -98,3 +98,7 @@
#include "Target.h"
void nmap_mass_rdns(Target ** targets, int num_targets);
+void free_dns_servers();
+
+void free_etchosts();
+
diff --git a/osscan.cc b/osscan.cc
index 541f82fd5..92e4d761e 100644
--- a/osscan.cc
+++ b/osscan.cc
@@ -1925,6 +1925,33 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig) {
return FP;
}
+
+void free_fingerprint_file(FingerPrint **FPs) {
+ FingerPrint **current;
+ FingerPrint *c, *d;
+ struct AVal *avc;
+ struct AVal *avd;
+
+ for(current = FPs; *current != NULL; current++){
+ for(c = *current; c; c=d){
+ d = c->next;
+ if(c->name)
+ free((void*)c->name); //strdup
+ if(c->results){
+ for(avc = c->results; avc; avc = avd) {
+ avd = avc->next;
+ if(avc->attribute)
+ free(avc->attribute);
+ }
+ free(c->results);
+ }
+ free(c);
+ }
+ }
+ free(FPs);
+}
+
+
FingerPrint **parse_fingerprint_file(char *fname) {
FingerPrint **FPs;
FingerPrint *current;
diff --git a/osscan.h b/osscan.h
index 6c159a843..001b2d437 100644
--- a/osscan.h
+++ b/osscan.h
@@ -131,6 +131,8 @@ FingerPrint *parse_single_fingerprint(char *fprint_orig);
FingerPrint **parse_fingerprint_file(char *fname);
FingerPrint **parse_fingerprint_reference_file(char *dbname);
+void free_fingerprint_file(FingerPrint **FPs);
+
/* Compares 2 fingerprints -- a referenceFP (can have expression
attributes) with an observed fingerprint (no expressions). If
verbose is nonzero, differences will be printed. The comparison
diff --git a/portlist.cc b/portlist.cc
index cc1a5952c..ffdb0d705 100644
--- a/portlist.cc
+++ b/portlist.cc
@@ -582,6 +582,17 @@ void PortList::setPortEntry(u16 portno, u8 protocol, Port *port) {
port_list[proto][mapped_pno] = port;
}
+/* Just free memory used by PortList::port_map[]. Should be done somewhere
+ * before closing nmap. */
+void PortList::freePortMap(){
+ int proto;
+ for(proto=0; proto < PORTLIST_PROTO_MAX; proto++)
+ if(port_map[proto]){
+ free(port_map[proto]);
+ port_map[proto] = NULL;
+ }
+}
+
u16 *PortList::port_map[PORTLIST_PROTO_MAX];
int PortList::port_list_count[PORTLIST_PROTO_MAX];
diff --git a/portlist.h b/portlist.h
index b5425bc92..321d3ffba 100644
--- a/portlist.h
+++ b/portlist.h
@@ -268,6 +268,9 @@ class PortList {
/* Set ports that will be scanned for each protocol. This function
* must be called before any PortList object will be created. */
static void initializePortMap(int protocol, u16 *ports, int portcount);
+ /* Free memory used by port_map. It should be done somewhere before quitting*/
+ static void PortList::freePortMap();
+
/* Add a new port to this list. If the state has changed, it is
OK to call this function to effect the change */
int addPort(u16 portno, u8 protocol, char *owner, int state);
diff --git a/scan_engine.cc b/scan_engine.cc
index d588d1fe8..eb16c29fd 100644
--- a/scan_engine.cc
+++ b/scan_engine.cc
@@ -3358,7 +3358,6 @@ static void startTimeOutClocks(vector &Targets) {
void ultra_scan(vector &Targets, struct scan_lists *ports,
stype scantype) {
UltraScanInfo *USI = NULL;
- time_t starttime;
o.current_scantype = scantype;
if (Targets.size() == 0) {
@@ -3377,14 +3376,11 @@ void ultra_scan(vector &Targets, struct scan_lists *ports,
if (o.verbose) {
char targetstr[128];
- struct tm *tm;
bool plural = (Targets.size() != 1);
if (!plural) {
(*(Targets.begin()))->NameIP(targetstr, sizeof(targetstr));
} else snprintf(targetstr, sizeof(targetstr), "%d hosts", (int) Targets.size());
- starttime = USI->now.tv_sec;
- tm = localtime(&starttime);
- log_write(LOG_STDOUT, "Initiating %s against %s [%d port%s%s] at %02d:%02d\n", scantype2str(scantype), targetstr, USI->gstats->numprobes, (USI->gstats->numprobes != 1)? "s" : "", plural? "/host" : "", tm->tm_hour, tm->tm_min);
+ log_write(LOG_STDOUT, "Scanning %s [%d port%s%s]\n", targetstr, USI->gstats->numprobes, (USI->gstats->numprobes != 1)? "s" : "", plural? "/host" : "");
}
begin_sniffer(USI, Targets);
@@ -3433,17 +3429,15 @@ void ultra_scan(vector &Targets, struct scan_lists *ports,
}
if (o.verbose) {
+ char additional_info[128];
if (USI->gstats->num_hosts_timedout == 0)
- log_write(LOG_STDOUT, "The %s took %.2fs to scan %lu total %s.\n",
- scantype2str(scantype),
- TIMEVAL_MSEC_SUBTRACT(USI->now, USI->SPM->begin) / 1000.0,
+ snprintf(additional_info, sizeof(additional_info), "%lu total %s",
(unsigned long) USI->gstats->numprobes * Targets.size(),
(scantype == PING_SCAN_ARP)? "hosts" : "ports");
- else log_write(LOG_STDOUT, "Finished %s in %.2fs, but %d %s timed out.\n",
- scantype2str(scantype),
- TIMEVAL_MSEC_SUBTRACT(USI->now, USI->SPM->begin) / 1000.0,
+ else snprintf(additional_info, sizeof(additional_info), "%d %s timed out",
USI->gstats->num_hosts_timedout,
(USI->gstats->num_hosts_timedout == 1)? "host" : "hosts");
+ USI->SPM->endTask(NULL, additional_info);
}
delete USI;
USI = NULL;
@@ -3629,7 +3623,6 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) {
struct scanstats ss;
int senddelay = 0;
int rpcportsscanned = 0;
- bool printedinitialmsg = false;
int tries = 0;
time_t starttime;
struct timeval starttm;
@@ -3643,6 +3636,8 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) {
struct serviceDeductions sd;
bool doingOpenFiltered = false;
+ ScanProgressMeter *SPM = NULL;
+
if (target->timedOut(NULL))
return;
@@ -3759,11 +3754,10 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) {
// This initial message is way down here because we don't want to print it if
// no RPC ports need scanning.
- if (o.verbose && !printedinitialmsg) {
- struct tm *tm = localtime(&starttime);
- assert(tm);
- log_write(LOG_STDOUT, "Initiating %s against %s at %02d:%02d\n", scantype2str(scantype), target->NameIP(hostname, sizeof(hostname)), tm->tm_hour, tm->tm_min);
- printedinitialmsg = true;
+ if (!SPM) {
+ char scanname[32];
+ snprintf(scanname, sizeof(scanname), "%s against %s", scantype2str(scantype), target->NameIP());
+ SPM = new ScanProgressMeter(scanname);
}
while(pil.testinglist != NULL) /* While we have live queries or more ports to scan */
@@ -3919,13 +3913,18 @@ void pos_scan(Target *target, u16 *portarray, int numports, stype scantype) {
}
numports = rpcportsscanned;
- if (o.verbose && numports > 0) {
- gettimeofday(&now, NULL);
- log_write(LOG_STDOUT, "The %s took %.2fs to scan %d ports on %s.\n", scantype2str(scantype), TIMEVAL_MSEC_SUBTRACT(now, starttm) / 1000.0, numports, target->NameIP());
+ if (SPM && o.verbose && (numports > 0)) {
+ char scannedportsstr[14];
+ snprintf(scannedportsstr, sizeof(scannedportsstr), "%d %s", numports, (numports > 1)? "ports" : "port");
+ SPM->endTask(NULL, scannedportsstr);
}
posscan_timedout:
target->stopTimeOutClock(NULL);
free(scan);
close_rpc_query_sockets();
+ if (SPM) {
+ delete SPM;
+ SPM = NULL;
+ }
return;
}
diff --git a/service_scan.cc b/service_scan.cc
index c74f38679..8cef6a1ac 100644
--- a/service_scan.cc
+++ b/service_scan.cc
@@ -305,6 +305,7 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) {
const char *pcre_errptr = NULL;
int pcre_erroffset = 0;
unsigned int tmpbuflen = 0;
+ char **curr_tmp = NULL;
if (isInitialized) fatal("Sorry ... ServiceProbeMatch::InitMatch does not yet support reinitializion");
if (!matchtext || !*matchtext)
@@ -414,13 +415,27 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) {
tmptemplate[tmpbuflen] = '\0';
}
- if (modechar == 'p') product_template = tmptemplate;
- else if (modechar == 'v') version_template = tmptemplate;
- else if (modechar == 'i') info_template = tmptemplate;
- else if (modechar == 'h') hostname_template = tmptemplate;
- else if (modechar == 'o') ostype_template = tmptemplate;
- else if (modechar == 'd') devicetype_template = tmptemplate;
- else fatal("ServiceProbeMatch::InitMatch: Unknown template specifier '%c' on line %d of nmap-service-probes", modechar, lineno);
+ switch(modechar){
+ case 'p': curr_tmp = &product_template; break;
+ case 'v': curr_tmp = &version_template; break;
+ case 'i': curr_tmp = &info_template; break;
+ case 'h': curr_tmp = &hostname_template; break;
+ case 'o': curr_tmp = &ostype_template; break;
+ case 'd': curr_tmp = &devicetype_template; break;
+ default:
+ fatal("ServiceProbeMatch::InitMatch: Unknown template specifier '%c' on line %d of nmap-service-probes", modechar, lineno);
+ }
+ if(*curr_tmp){
+ if(o.debugging)
+ error("WARNING: Template \"%c/%s/\" replaced with \"%c/%s/\" on line %d of nmap-service-probes",
+ modechar,
+ *curr_tmp,
+ modechar,
+ tmptemplate,
+ lineno);
+ free(*curr_tmp);
+ }
+ *curr_tmp = tmptemplate;
matchtext = p + 1;
}
@@ -1133,17 +1148,26 @@ void parse_nmap_service_probes(AllProbes *AP) {
parse_nmap_service_probe_file(AP, filename);
}
-static AllProbes *service_scan_init(void)
+AllProbes *AllProbes::global_AP;
+AllProbes *AllProbes::service_scan_init(void)
{
- static AllProbes *AP;
+ if(global_AP)
+ return global_AP;
+ global_AP = new AllProbes();
+ parse_nmap_service_probes(global_AP);
- if (AP) return AP;
- AP = new AllProbes();
- parse_nmap_service_probes(AP);
-
- return AP;
+ return global_AP;
}
+void AllProbes::service_scan_free(void)
+{
+ if(global_AP){
+ delete global_AP;
+ global_AP = NULL;
+ }
+}
+
+
// If the buf (of length buflen) matches one of the regexes in this
// ServiceProbe, returns the details of the match (service name,
// version number if applicable, and whether this is a "soft" match.
@@ -1175,8 +1199,12 @@ AllProbes::~AllProbes() {
vector::iterator vi;
// Delete all the ServiceProbe's inside the probes vector
- for(vi = probes.begin(); vi != probes.end(); vi++)
+ for(vi = probes.begin(); vi != probes.end(); vi++) {
delete *vi;
+ }
+ if(nullProbe)
+ delete nullProbe;
+ free_scan_lists(excludedports);
}
// Tries to find the probe in this AllProbes class which have the
@@ -2338,7 +2366,7 @@ int service_scan(vector &Targets) {
if (Targets.size() == 0)
return 1;
- AP = service_scan_init();
+ AP = AllProbes::service_scan_init();
// Now I convert the targets into a new ServiceGroup
@@ -2361,16 +2389,15 @@ int service_scan(vector &Targets) {
starttime = time(NULL);
if (o.verbose) {
char targetstr[128];
- struct tm *tm = localtime(&starttime);
bool plural = (Targets.size() != 1);
if (!plural) {
(*(Targets.begin()))->NameIP(targetstr, sizeof(targetstr));
} else snprintf(targetstr, sizeof(targetstr), "%u hosts", (unsigned) Targets.size());
- log_write(LOG_STDOUT, "Initiating service scan against %u %s on %s at %02d:%02d\n",
+ log_write(LOG_STDOUT, "Scanning %u %s on %s\n",
(unsigned) SG->services_remaining.size(),
(SG->services_remaining.size() == 1)? "service" : "services",
- targetstr, tm->tm_hour, tm->tm_min);
+ targetstr);
}
// Lets create a nsock pool for managing all the concurrent probes
@@ -2399,18 +2426,16 @@ int service_scan(vector &Targets) {
nsp_delete(nsp);
if (o.verbose) {
- gettimeofday(&now, NULL);
+ char additional_info[128];
if (SG->num_hosts_timedout == 0)
- log_write(LOG_STDOUT, "The service scan took %.2fs to scan %u %s on %u %s.\n",
- TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
+ snprintf(additional_info, sizeof(additional_info), "%u %s on %u %s",
(unsigned) SG->services_finished.size(),
(SG->services_finished.size() == 1)? "service" : "services",
(unsigned) Targets.size(), (Targets.size() == 1)? "host" : "hosts");
- else log_write(LOG_STDOUT,
- "Finished service scan in %.2fs, but %d %s timed out.\n",
- TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0,
+ else snprintf(additional_info, sizeof(additional_info), "%u %s timed out",
SG->num_hosts_timedout,
(SG->num_hosts_timedout == 1)? "host" : "hosts");
+ SG->SPM->endTask(NULL, additional_info);
}
// Yeah - done with the service scan. Now I go through the results
diff --git a/service_scan.h b/service_scan.h
index c4db6d355..a186e143f 100644
--- a/service_scan.h
+++ b/service_scan.h
@@ -332,6 +332,11 @@ public:
int isExcluded(unsigned short port, int proto);
struct scan_lists *excludedports;
+
+ static AllProbes *service_scan_init(void);
+ static void service_scan_free(void);
+protected:
+ static AllProbes *global_AP;
};
/********************** PROTOTYPES ***********************************/
diff --git a/targets.cc b/targets.cc
index 8a285816f..ede469e91 100644
--- a/targets.cc
+++ b/targets.cc
@@ -794,7 +794,6 @@ static int get_ping_results(int sd, pcap_t *pd, Target *hostbatch[],
return 0;
}
-
static int sendconnecttcpquery(Target *hostbatch[], struct tcpqueryinfo *tqi,
Target *target, int probe_port_num, u16 seq,
struct timeval *time, struct pingtune *pt,
diff --git a/tcpip.cc b/tcpip.cc
index 08781d2ae..e68acb171 100644
--- a/tcpip.cc
+++ b/tcpip.cc
@@ -2118,6 +2118,7 @@ void set_pcap_filter(const char *device,
fatal("Error compiling our pcap filter: %s\n", pcap_geterr(pd));
if (pcap_setfilter(pd, &fcode) < 0 )
fatal("Failed to set the pcap filter: %s\n", pcap_geterr(pd));
+ pcap_freecode(&fcode);
}
/* The 'dev' passed in must be at least 32 bytes long */
diff --git a/timing.cc b/timing.cc
index 1c42cad91..01779212c 100644
--- a/timing.cc
+++ b/timing.cc
@@ -243,6 +243,7 @@ ScanProgressMeter::ScanProgressMeter(char *stypestr) {
last_print_test = begin;
memset(&last_print, 0, sizeof(last_print));
memset(&last_est, 0, sizeof(last_print));
+ beginOrEndTask(&begin, NULL, true);
}
ScanProgressMeter::~ScanProgressMeter() {
@@ -382,19 +383,57 @@ bool ScanProgressMeter::printStats(double perc_done,
// If we're less than 1% done we probably don't have enough
// data for decent timing estimates. Also with perc_done == 0
// these elements will be nonsensical.
- if (perc_done < 0.01)
+ if (perc_done < 0.01) {
log_write(LOG_STDOUT, "%s Timing: About %.2f%% done\n",
scantypestr, perc_done * 100);
- else
+ log_flush(LOG_STDOUT);
+ } else {
log_write(LOG_STDOUT, "%s Timing: About %.2f%% done; ETC: %02d:%02d (%li:%02li:%02li remaining)\n",
scantypestr, perc_done * 100, ltime->tm_hour, ltime->tm_min, sec_left / 3600,
(sec_left % 3600) / 60, sec_left % 60);
-
- log_flush(LOG_STDOUT);
+ log_write(LOG_XML, "\n",
+ scantypestr, (unsigned long) now->tv_sec,
+ perc_done * 100, sec_left, (unsigned long) last_est.tv_sec);
+ log_flush(LOG_STDOUT|LOG_XML);
+ }
return true;
}
+/* Indicates that the task is beginning or ending, and that a message should
+ be generated if appropriate. Returns whether a message was printed.
+ now may be NULL, if the caller doesn't have the current time handy.
+ additional_info may be NULL if no additional information is necessary. */
+bool ScanProgressMeter::beginOrEndTask(const struct timeval *now, const char *additional_info, bool beginning) {
+ struct timeval tvtmp;
+ struct tm *tm;
+ time_t tv_sec;
+ if (!o.verbose) {
+ return false;
+ }
+ if (!now) {
+ gettimeofday(&tvtmp, NULL);
+ now = (const struct timeval *) &tvtmp;
+ }
-
+ tv_sec = now->tv_sec;
+ tm = localtime(&tv_sec);
+ if (beginning) {
+ log_write(LOG_STDOUT, "Initiating %s at %02d:%02d", scantypestr, tm->tm_hour, tm->tm_min);
+ if (additional_info) {
+ log_write(LOG_STDOUT, " (%s)", additional_info);
+ }
+ log_write(LOG_STDOUT, "\n");
+ log_write(LOG_XML, "\n", scantypestr, (unsigned long) now->tv_sec);
+ } else {
+ log_write(LOG_STDOUT, "Completed %s at %02d:%02d, %.2fs elapsed", scantypestr, tm->tm_hour, tm->tm_min, TIMEVAL_MSEC_SUBTRACT(*now, begin) / 1000.0);
+ if (additional_info) {
+ log_write(LOG_STDOUT, " (%s)", additional_info);
+ }
+ log_write(LOG_STDOUT, "\n");
+ log_write(LOG_XML, "\n", scantypestr, (unsigned long) now->tv_sec);
+ }
+ log_flush(LOG_STDOUT|LOG_XML);
+ return true;
+}
diff --git a/timing.h b/timing.h
index 58cf0abd2..4ec7421e9 100644
--- a/timing.h
+++ b/timing.h
@@ -154,12 +154,17 @@ class ScanProgressMeter {
/* Prints an estimate of when this scan will complete. */
bool printStats(double perc_done, const struct timeval *now);
+ /* Prints that this task is complete. */
+ bool endTask(const struct timeval *now, const char *additional_info) { return beginOrEndTask(now, additional_info, false); }
+
struct timeval begin; /* When this ScanProgressMeter was instantiated */
private:
struct timeval last_print_test; /* Last time printStatsIfNeccessary was called */
struct timeval last_print; /* The most recent time the ETC was printed */
char *scantypestr;
struct timeval last_est; /* The latest PRINTED estimate */
+
+ bool beginOrEndTask(const struct timeval *now, const char *additional_info, bool beginning);
};
#endif /* NMAP_TIMING_H */