1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

memory releasing patch from Marek

This commit is contained in:
fyodor
2006-07-04 23:04:56 +00:00
parent 41aad8638a
commit 9c0af0a95b
21 changed files with 312 additions and 71 deletions

View File

@@ -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:
<taskbegin task="SYN Stealth Scan" time="1151384685" />
<taskprogress task="SYN Stealth Scan" time="1151384715"
percent="13.85" remaining="187" etc="1151384902" />
<taskend task="SYN Stealth Scan" time="1151384776" />
<taskbegin task="Service scan" time="1151384776" />
<taskend task="Service scan" time="1151384788" />
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).

View File

@@ -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;

View File

@@ -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) {

View File

@@ -107,4 +107,7 @@
void *cp_alloc(int sz);
char *cp_strdup(const char *src);
void cp_free(void);
#endif

View File

@@ -45,6 +45,7 @@
<!ENTITY % attr_numeric "CDATA" >
<!ENTITY % attr_ipaddr "CDATA" >
<!ENTITY % attr_numeric "CDATA" >
<!ENTITY % attr_percent "CDATA" >
<!ENTITY % attr_type "(ipv4 | ipv6 | mac)" >
<!ENTITY % host_states "(up|down|unknown|skipped)" >
@@ -71,7 +72,7 @@
<!-- This element was started in nmap.c:nmap_main().
It represents to the topmost element of the output document.
-->
<!ELEMENT nmaprun (scaninfo*, verbose, debugging, host*, runstats) >
<!ELEMENT nmaprun (scaninfo*, verbose, debugging, ((taskbegin, taskprogress*, taskend) | host)*, runstats) >
<!ATTLIST nmaprun
scanner (nmap) #REQUIRED
args CDATA #IMPLIED
@@ -98,13 +99,37 @@
<!ELEMENT debugging EMPTY >
<!ATTLIST debugging level %attr_numeric; #IMPLIED >
<!-- this element is written in timing.c:beginOrEndTask() -->
<!ELEMENT taskbegin EMPTY >
<!ATTLIST taskbegin
task CDATA #REQUIRED
time %attr_numeric; #REQUIRED
>
<!-- this element is written in timing.c:printStats() -->
<!ELEMENT taskprogress EMPTY >
<!ATTLIST taskprogress
task CDATA #REQUIRED
time %attr_numeric; #REQUIRED
percent %attr_percent; #REQUIRED
remaining %attr_numeric; #REQUIRED
etc %attr_numeric; #REQUIRED
>
<!-- this element is written in timing.c:beginOrEndTask() -->
<!ELEMENT taskend EMPTY >
<!ATTLIST taskend
task CDATA #REQUIRED
time %attr_numeric; #REQUIRED
>
<!--
this element is started in nmap.c:nmap_main() and filled by
output.c:write_host_status(), output.c:printportoutput(), and
output.c:printosscanoutput()
-->
<!ELEMENT host ( status, address , (address | hostnames |
smurf | ports | os | uptime |
smurf | ports | os | distance | uptime |
tcpsequence | ipidsequence | tcptssequence )* ) >
@@ -202,6 +227,11 @@
fingerprint CDATA #REQUIRED
>
<!ELEMENT distance EMPTY >
<!ATTLIST distance
value %attr_numeric; #REQUIRED
>
<!ELEMENT uptime EMPTY >
<!ATTLIST uptime
seconds %attr_numeric; #REQUIRED

View File

@@ -965,6 +965,9 @@ void idle_scan(Target *target, u16 *portarray, int numports,
int portidx = 0; /* Used for splitting the port array into chunks */
int portsleft;
time_t starttime;
char scanname[32];
snprintf(scanname, sizeof(scanname), "Idlescan against %s", target->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 */

37
nmap.cc
View File

@@ -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();
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(

3
nmap.h
View File

@@ -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);

View File

@@ -816,6 +816,21 @@ static void add_dns_server(char *ipaddrs) {
}
void free_dns_servers() {
std::list<dns_server *>::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<host_elem *>::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<host_elem *>::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();

View File

@@ -98,3 +98,7 @@
#include "Target.h"
void nmap_mass_rdns(Target ** targets, int num_targets);
void free_dns_servers();
void free_etchosts();

View File

@@ -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;

View File

@@ -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

View File

@@ -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];

View File

@@ -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);

View File

@@ -3358,7 +3358,6 @@ static void startTimeOutClocks(vector<Target *> &Targets) {
void ultra_scan(vector<Target *> &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<Target *> &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<Target *> &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;
}

View File

@@ -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<ServiceProbe *>::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<Target *> &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<Target *> &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<Target *> &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

View File

@@ -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 ***********************************/

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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, "<taskprogress task=\"%s\" time=\"%lu\" percent=\"%.2f\" remaining=\"%li\" etc=\"%lu\" />\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, "<taskbegin task=\"%s\" time=\"%lu\" />\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, "<taskend task=\"%s\" time=\"%lu\" />\n", scantypestr, (unsigned long) now->tv_sec);
}
log_flush(LOG_STDOUT|LOG_XML);
return true;
}

View File

@@ -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 */