1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-10 16:39:04 +00:00

Merge the minimum-rate scanning feature (--min-rate) from

/nmap-exp/david/nmap-fixed-rate.
This commit is contained in:
david
2008-03-26 02:41:32 +00:00
parent dd220398b1
commit feab94ebd3
8 changed files with 351 additions and 14 deletions

View File

@@ -195,6 +195,7 @@ void NmapOps::Initialize() {
#endif
debugging = 0;
verbose = 0;
min_packet_send_rate = 0.0; /* Unset. */
randomize_hosts = 0;
sendpref = PACKET_SEND_NOPREF;
spoofsource = 0;

View File

@@ -178,6 +178,8 @@ class NmapOps {
bool openOnly() { return open_only; }
void setOpenOnly(bool oo) { open_only = oo; }
int verbose;
/* The requested minimum packet sending rate, or 0.0 if unset. */
float min_packet_send_rate;
int randomize_hosts;
int spoofsource; /* -S used */
int fastscan;

View File

@@ -2300,6 +2300,44 @@ threshold based intrusion detection and prevention systems (IDS/IPS).</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--min-rate &lt;number&gt;</option>
(Specify a minimum scanning rate)
<indexterm><primary>--min-rate</primary></indexterm>
</term>
<listitem>
<para>Nmap's dynamic timing does a good job of finding an appropriate
speed at which to scan. Sometimes, however, you may happen to know an
appropriate speed for a network, or you may have to guarantee that a
scan will be finished by a certain time. When the
<option>--min-rate</option> is given Nmap will do its best to send
packets as fast or faster than the given rate. The argument is a
positive real number representing a packet rate in packets per second.
For example, using <command>--min-rate 300</command> will ensure that
the packet sending rate doesn't fall below 300 packets per second.
Specifying a minimum rate does not keep Nmap from going faster if
conditions warrant.</para>
<para>There are two conditions when the actual scanning rate may fall
below the specified minimum. The first is if the minimum is faster than
the fastest rate at which Nmap can send, which is dependent on hardware.
In this case Nmap will send packets as fast a possible, but be aware
that such high rates are likely to cause a loss of accuracy. The second
case is when Nmap has nothing to send, for example at the end of a scan
when the last probes have been sent and Nmap is waiting for them to time
out or be responded to. It's normal to see the scanning rate drop at the
end of a scan or in between groups of hosts.</para>
<para>The <option>--min-rate</option> option is global, affecting an
entire scan, not individual hosts. It only affects port and host
discovery scans. Other features like OS detection implement their own
timing.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--defeat-rst-ratelimit</option>
<indexterm><primary>--defeat-rst-ratelimit</primary></indexterm></term>

View File

@@ -278,6 +278,7 @@ printf("%s %s ( %s )\n"
" --max-retries <tries>: Caps number of port scan probe retransmissions.\n"
" --host-timeout <time>: Give up on target after this long\n"
" --scan-delay/--max-scan-delay <time>: Adjust delay between probes\n"
" --min-rate <number>: Send packets no slower than <number> per second\n"
"FIREWALL/IDS EVASION AND SPOOFING:\n"
" -f; --mtu <val>: fragment packets (optionally w/given MTU)\n"
" -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys\n"
@@ -634,6 +635,7 @@ int nmap_main(int argc, char *argv[]) {
#endif
{"ip_options", required_argument, 0, 0},
{"ip-options", required_argument, 0, 0},
{"min-rate", required_argument, 0, 0},
{0, 0, 0, 0}
};
@@ -888,6 +890,9 @@ int nmap_main(int argc, char *argv[]) {
o.traceroute = true;
} else if(strcmp(long_options[option_index].name, "reason") == 0) {
o.reason = true;
} else if(optcmp(long_options[option_index].name, "min-rate") == 0) {
if (sscanf(optarg, "%f", &o.min_packet_send_rate) != 1 || o.min_packet_send_rate <= 0.0)
fatal("Argument to --min-rate must be a positive floating-point number");
} else {
fatal("Unknown long option (%s) given@#!$#$", long_options[option_index].name);
}
@@ -1483,6 +1488,7 @@ int nmap_main(int argc, char *argv[]) {
log_write(LOG_PLAIN, " max-scan-delay: TCP %d, UDP %d\n", o.maxTCPScanDelay(), o.maxUDPScanDelay());
log_write(LOG_PLAIN, " parallelism: min %d, max %d\n", o.min_parallelism, o.max_parallelism);
log_write(LOG_PLAIN, " max-retries: %d, host-timeout: %ld\n", o.getMaxRetransmissions(), o.host_timeout);
log_write(LOG_PLAIN, " min-rate: %g\n", o.min_packet_send_rate);
log_write(LOG_PLAIN, "---------------------------------------------\n");
}

View File

@@ -346,8 +346,9 @@ public:
struct sockaddr_storage latestip;
GroupScanStats(UltraScanInfo *UltraSI);
~GroupScanStats();
void probeSent();
/* Returns true if the GLOBAL system says that sending is OK. */
bool sendOK();
bool sendOK(struct timeval *when);
/* Total # of probes outstanding (active) for all Hosts */
int num_probes_active;
UltraScanInfo *USI; /* The USI which contains this GSS. Use for at least
@@ -373,6 +374,9 @@ public:
/* Value of numprobes_sent at lastping_sent time -- to ensure that we don't
send too many pings when probes are going slowly. */
int lastping_sent_numprobes;
/* When to send the next probe, to keep the minimum up. Used only when a
minimum sending rate (o.min_packet_send_rate) is set. */
struct timeval send_no_later_than;
/* The host to which global pings are sent. This is kept updated to be the
most recent host that was found up. */
@@ -653,6 +657,7 @@ public:
list<HostScanStats *> completedHosts;
ScanProgressMeter *SPM;
RateMeter send_rate_meter;
struct scan_lists *ports;
int rawsd; /* raw socket descriptor */
pcap_t *pd;
@@ -874,6 +879,7 @@ GroupScanStats::GroupScanStats(UltraScanInfo *UltraSI) {
probes_sent = probes_sent_at_last_wait = 0;
probes_replied_to = 0;
lastping_sent = lastrcvd = USI->now;
send_no_later_than = USI->now;
lastping_sent_numprobes = 0;
pinghost = NULL;
gettimeofday(&last_wait, NULL);
@@ -884,10 +890,27 @@ GroupScanStats::~GroupScanStats() {
delete CSI;
}
void GroupScanStats::probeSent() {
/* Find the next scheduled send time for minimum-rate scanning. */
if (TIMEVAL_SUBTRACT(send_no_later_than, USI->now) > 0) {
/* The next scheduled send is in the future. That means we're ahead of
schedule, but it also means there's slack time during which the sending
rate could drop. Reschedule the send to keep that from happening. */
send_no_later_than = USI->now;
}
TIMEVAL_ADD(send_no_later_than, send_no_later_than,
(time_t) (1000000.0 / o.min_packet_send_rate));
}
/* Returns true if the GLOBAL system says that sending is OK.*/
bool GroupScanStats::sendOK() {
bool GroupScanStats::sendOK(struct timeval *when) {
int recentsends;
/* In case it's not okay to send, arbitrarily say to check back in one
second. */
if (when)
TIMEVAL_MSEC_ADD(*when, USI->now, 1000);
if ((USI->scantype == CONNECT_SCAN || USI->ptech.connecttcpscan)
&& CSI->numSDs >= CSI->maxSocketsAllowed)
return false;
@@ -914,13 +937,34 @@ bool GroupScanStats::sendOK() {
if (recentsends >= 50)
return false;
/* Enforce a minimum scanning rate, if necessary. If we're ahead of schedule,
record the time of the next scheduled send. If we're behind schedule,
return true to indicate that we need to send now, regardless of any
congestion control. */
if (o.min_packet_send_rate != 0.0) {
if (TIMEVAL_SUBTRACT(send_no_later_than, USI->now) > 0) {
if (when)
*when = send_no_later_than;
} else {
if (when)
*when = USI->now;
return true;
}
}
/* When there is only one target left, let the host congestion
stuff deal with it. */
if (USI->numIncompleteHostsLessThan(2))
if (USI->numIncompleteHostsLessThan(2)) {
if (when)
*when = USI->now;
return true;
}
if (timing.cwnd >= num_probes_active + 0.5)
if (timing.cwnd >= num_probes_active + 0.5) {
if (when)
*when = USI->now;
return true;
}
return false;
}
@@ -1053,6 +1097,16 @@ bool HostScanStats::sendOK(struct timeval *when) {
struct timeval probe_to, earliest_to, sendTime;
long tdiff;
/* If the group stats say we need to send a probe to enforce a minimum
scanning rate, then we need to step up and send a probe. */
if (o.min_packet_send_rate != 0.0) {
if (TIMEVAL_SUBTRACT(USI->gstats->send_no_later_than, USI->now) <= 0) {
if (when)
*when = USI->now;
return true;
}
}
if (target->timedOut(&USI->now) || completed()) {
if (when) *when = USI->now;
return false;
@@ -1293,6 +1347,7 @@ void UltraScanInfo::Init(vector<Target *> &Targets, struct scan_lists *pts, styp
seqmask = get_random_u32();
scantype = scantp;
SPM = new ScanProgressMeter(scantype2str(scantype));
send_rate_meter.start(&now);
tcp_scan = udp_scan = prot_scan = ping_scan = noresp_open_scan = false;
ping_scan_arp = false;
memset((char *) &ptech, 0, sizeof(ptech));
@@ -1447,11 +1502,12 @@ bool UltraScanInfo::sendOK(struct timeval *when) {
bool hgood = false;
bool thisHostGood = false;
bool foundgood = false;
ggood = gstats->sendOK();
ggood = gstats->sendOK(when);
if (!ggood) {
if (when) {
TIMEVAL_MSEC_ADD(lowhtime, now, 1000);
lowhtime = *when;
// Can't do anything until global is OK - means packet receipt
// or probe timeout.
for(host = incompleteHosts.begin(); host != incompleteHosts.end();
@@ -1482,6 +1538,13 @@ bool UltraScanInfo::sendOK(struct timeval *when) {
assert(foundgood);
}
/* Defer to the group stats if they need a shorter delay to enforce a minimum
packet sending rate. */
if (o.min_packet_send_rate != 0.0) {
if (TIMEVAL_MSEC_SUBTRACT(gstats->send_no_later_than, lowhtime) < 0)
lowhtime = gstats->send_no_later_than;
}
if (TIMEVAL_MSEC_SUBTRACT(lowhtime, now) < 0)
lowhtime = now;
@@ -2483,11 +2546,14 @@ static UltraProbe *sendConnectScanProbe(UltraScanInfo *USI, HostScanStats *hss,
else sin6->sin6_port = htons(probe->pspec()->pd.tcp.dport);
#endif
hss->lastprobe_sent = probe->sent = USI->now;
USI->gstats->probeSent();
rc = connect(CP->sd, (struct sockaddr *)&sock, socklen);
gettimeofday(&USI->now, NULL);
if (rc == -1) connect_errno = socket_errno();
PacketTrace::traceConnect(IPPROTO_TCP, (sockaddr *) &sock, socklen, rc,
connect_errno, &USI->now);
/* We don't record a byte count for connect probes. */
USI->send_rate_meter.record(0, &USI->now);
/* This counts as probe being sent, so update structures */
hss->probes_outstanding.push_back(probe);
probeI = hss->probes_outstanding.end();
@@ -2579,11 +2645,13 @@ static UltraProbe *sendArpScanProbe(UltraScanInfo *USI, HostScanStats *hss,
ETH_ADDR_BROADCAST, *hss->target->v4hostip());
gettimeofday(&USI->now, NULL);
hss->lastprobe_sent = probe->sent = USI->now;
USI->gstats->probeSent();
if ((rc = eth_send(USI->ethsd, frame, sizeof(frame))) != sizeof(frame)) {
int err = socket_errno();
error("WARNING: eth_send of ARP packet returned %i rather than expected %d (errno=%i: %s)", rc, (int) sizeof(frame), err, strerror(err));
}
PacketTrace::traceArp(PacketTrace::SENT, (u8 *) frame, sizeof(frame), &USI->now);
USI->send_rate_meter.record(sizeof(frame), &USI->now);
probe->tryno = tryno;
probe->pingseq = pingseq;
/* First build the probe */
@@ -2656,6 +2724,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
USI->gstats->probeSent();
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
@@ -2671,6 +2740,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
USI->gstats->probeSent();
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
@@ -2726,6 +2796,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
USI->gstats->probeSent();
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
@@ -2748,10 +2819,12 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
probe->setIP(packet, packetlen, pspec);
hss->lastprobe_sent = probe->sent = USI->now;
}
USI->gstats->probeSent();
send_ip_packet(USI->rawsd, ethptr, packet, packetlen);
free(packet);
}
} else assert(0); /* TODO: Maybe RPC scan and the like */
USI->send_rate_meter.record(packetlen, &USI->now);
/* Now that the probe has been sent, add it to the Queue for this host */
hss->probes_outstanding.push_back(probe);
USI->gstats->num_probes_active++;
@@ -2811,7 +2884,7 @@ static void doAnyNewProbes(UltraScanInfo *USI) {
sending a probe. */
unableToSend = NULL;
hss = USI->nextIncompleteHost();
while (hss != NULL && hss != unableToSend && USI->gstats->sendOK()) {
while (hss != NULL && hss != unableToSend && USI->gstats->sendOK(NULL)) {
if (hss->freshPortsLeft() && hss->sendOK(NULL)) {
sendNextScanProbe(USI, hss);
unableToSend = NULL;
@@ -2834,7 +2907,7 @@ static void doAnyRetryStackRetransmits(UltraScanInfo *USI) {
sending a probe. */
unableToSend = NULL;
hss = USI->nextIncompleteHost();
while (hss != NULL && hss != unableToSend && USI->gstats->sendOK()) {
while (hss != NULL && hss != unableToSend && USI->gstats->sendOK(NULL)) {
if (!hss->retry_stack.empty() && hss->sendOK(NULL)) {
sendNextRetryStackProbe(USI, hss);
unableToSend = NULL;
@@ -2901,7 +2974,7 @@ static void doAnyPings(UltraScanInfo *USI) {
hss->numprobes_sent >= hss->lastping_sent_numprobes + 10 &&
TIMEVAL_SUBTRACT(USI->now, hss->lastrcvd) > USI->perf.pingtime &&
TIMEVAL_SUBTRACT(USI->now, hss->lastping_sent) > USI->perf.pingtime &&
USI->gstats->sendOK() && hss->sendOK(NULL)) {
USI->gstats->sendOK(NULL) && hss->sendOK(NULL)) {
sendPingProbe(USI, hss);
hss->lastping_sent = USI->now;
hss->lastping_sent_numprobes = hss->numprobes_sent;
@@ -2914,7 +2987,7 @@ static void doAnyPings(UltraScanInfo *USI) {
USI->gstats->probes_sent >= USI->gstats->lastping_sent_numprobes + 20 &&
TIMEVAL_SUBTRACT(USI->now, USI->gstats->lastrcvd) > USI->perf.pingtime &&
TIMEVAL_SUBTRACT(USI->now, USI->gstats->lastping_sent) > USI->perf.pingtime &&
USI->gstats->sendOK()) {
USI->gstats->sendOK(NULL)) {
sendGlobalPingProbe(USI);
USI->gstats->lastping_sent = USI->now;
USI->gstats->lastping_sent_numprobes = USI->gstats->probes_sent;
@@ -2966,6 +3039,12 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
int retrans = 0; /* Number of retransmissions during a loop */
unsigned int maxtries;
struct timeval tv_start = {0};
if (o.debugging) {
gettimeofday(&USI->now, NULL);
tv_start = USI->now;
}
gettimeofday(&USI->now, NULL);
/* Loop until we get through all the hosts without a retransmit or we're not
@@ -2973,7 +3052,7 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
do {
retrans = 0;
for (hostI = USI->incompleteHosts.begin();
hostI != USI->incompleteHosts.end() && USI->gstats->sendOK();
hostI != USI->incompleteHosts.end() && USI->gstats->sendOK(NULL);
hostI++) {
host = *hostI;
/* Skip this host if it has nothing to send. */
@@ -3006,7 +3085,14 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
}
} while (probeI != host->probes_outstanding.begin());
}
} while (USI->gstats->sendOK() && retrans != 0);
} while (USI->gstats->sendOK(NULL) && retrans != 0);
if (o.debugging) {
long tv_diff;
gettimeofday(&USI->now, NULL);
tv_diff = TIMEVAL_MSEC_SUBTRACT(USI->now, tv_start);
if (tv_diff > 30) log_write(LOG_PLAIN, "%s took %lims\n", __func__, tv_diff);
}
}
/* Print occasional remaining time estimates, as well as
@@ -3041,6 +3127,13 @@ static void printAnyStats(UltraScanInfo *USI) {
hss->target->to.rttvar);
}
}
log_write(LOG_PLAIN, "Current sending rates: %.2f packets / s, %.2f bytes / s.\n",
USI->send_rate_meter.getCurrentPacketRate(),
USI->send_rate_meter.getCurrentByteRate());
log_write(LOG_PLAIN, "Overall sending rates: %.2f packets / s, %.2f bytes / s.\n",
USI->send_rate_meter.getOverallPacketRate(),
USI->send_rate_meter.getOverallByteRate());
}
/* Now time to figure out how close we are to completion ... */
@@ -4694,12 +4787,20 @@ void ultra_scan(vector<Target *> &Targets, struct scan_lists *ports,
avgdone /= USI->gstats->numtargets;
USI->SPM->printStats(avgdone, NULL); // This prints something like SYN Stealth Scan Timing: About 1.14% done; ETC: 15:01 (0:43:23 remaining);
/* Don't update when getting the current rates, otherwise we can get
anomalies (rates are too low) from having just done a potentially long
waitForResponses without sending any packets. */
log_write(LOG_STDOUT, "Current sending rates: %.2f packets / s, %.2f bytes / s.\n",
USI->send_rate_meter.getCurrentPacketRate(&USI->now, false),
USI->send_rate_meter.getCurrentByteRate(&USI->now, false));
log_flush(LOG_STDOUT);
}
}
USI->send_rate_meter.stop(&USI->now);
/* Save the computed timeouts. */
if (to != NULL)
*to = USI->gstats->to;
@@ -4718,6 +4819,9 @@ void ultra_scan(vector<Target *> &Targets, struct scan_lists *ports,
USI->gstats->num_hosts_timedout,
(USI->gstats->num_hosts_timedout == 1)? "host" : "hosts");
USI->SPM->endTask(NULL, additional_info);
log_write(LOG_STDOUT, "Overall sending rates: %.2f packets / s, %.2f bytes / s.\n",
USI->send_rate_meter.getOverallPacketRate(),
USI->send_rate_meter.getOverallByteRate());
}
if (o.debugging > 2 && USI->pd != NULL)

150
timing.cc
View File

@@ -238,6 +238,156 @@ void enforce_scan_delay(struct timeval *tv) {
return;
}
/* Initialize the constant CURRENT_RATE_HISTORY that defines how far back we
look when calculating the current rates. */
RateMeter::RateMeter() : CURRENT_RATE_HISTORY(5.0) {
start_tv.tv_sec = 0;
start_tv.tv_usec = 0;
stop_tv.tv_sec = 0;
stop_tv.tv_usec = 0;
last_update_tv.tv_sec = 0;
last_update_tv.tv_usec = 0;
num_packets = 0;
num_bytes = 0;
current_packet_rate = 0.0;
current_byte_rate = 0.0;
assert(!isSet(&start_tv));
assert(!isSet(&stop_tv));
}
void RateMeter::start(const struct timeval *now) {
assert(!isSet(&start_tv));
assert(!isSet(&stop_tv));
if (now == NULL)
gettimeofday(&start_tv, NULL);
else
start_tv = *now;
}
void RateMeter::stop(const struct timeval *now) {
assert(isSet(&start_tv));
assert(!isSet(&stop_tv));
if (now == NULL)
gettimeofday(&stop_tv, NULL);
else
stop_tv = *now;
}
/* Record a packet of length len. If now is not NULL, use it as the time the
packet was received rather than calling gettimeofday. */
void RateMeter::record(u32 len, const struct timeval *now) {
update(1, len, now);
}
double RateMeter::getOverallPacketRate(const struct timeval *now) const {
return num_packets / elapsedTime(now);
}
/* Get the "current" packet rate (actually a moving average of the last few
seconds). If update is true (its default value), lower the rate to account
for the time since the last packet was received. */
double RateMeter::getCurrentPacketRate(const struct timeval *now, bool update) {
if (update)
this->update(0, 0, now);
return current_packet_rate;
}
double RateMeter::getOverallByteRate(const struct timeval *now) const {
return num_bytes / elapsedTime(now);
}
/* Get the "current" byte rate (actually a moving average of the last few
seconds). If update is true (its default value), lower the rate to account
for the time since the last bytes were received. */
double RateMeter::getCurrentByteRate(const struct timeval *now, bool update) {
if (update)
this->update(0, 0, now);
return current_byte_rate;
}
/* Update the rates to include packets additional packets and bytes additional
bytes. If now is not NULL, use it as the time the packets and bytes were
received rather than calling gettimeofday. */
void RateMeter::update(u32 packets, u32 bytes, const struct timeval *now) {
struct timeval tv;
double diff;
double d;
double count;
assert(isSet(&start_tv));
assert(!isSet(&stop_tv));
/* Update the overall counters. */
num_packets += packets;
num_bytes += bytes;
if (now == NULL) {
gettimeofday(&tv, NULL);
now = &tv;
}
if (!isSet(&last_update_tv))
last_update_tv = start_tv;
/* Calculate approximate moving averages of how many packets and bytes were
recorded in the last CURRENT_RATE_HISTORY seconds. These averages are what
are returned as the "current" rates. */
/* How long since the last update? */
diff = TIMEVAL_SUBTRACT(*now, last_update_tv) / 1000000.0;
/* Look back CURRENT_RATE_HISTORY seconds, or to when the last sample was
recorded, whichever is longer, but don't look back past the start. */
d = MAX(CURRENT_RATE_HISTORY, diff);
d = MIN(d, TIMEVAL_SUBTRACT(*now, start_tv) / 1000000.0);
assert(d >= 0);
/* If we get packets in the very same instant that the timer is started,
there's no way to calculate meaningful rates. Ignore it. */
if (d == 0.0)
return;
/* To calculate the approximate average of the packet rate over the last d
seconds, we assume that the rate was constant over that interval. We
calculate how many packets would have been received in that interval,
ignoring the first diff seconds' worth, (d - diff) * current_packet_rate.
Then we add how many packets were received in the most recent diff seconds.
Divide by the width of the interval to get the average. */
count = (d - diff) * current_packet_rate + packets;
current_packet_rate = count / d;
assert(current_packet_rate >= 0.0);
/* Likewise with the byte rate. */
count = (d - diff) * current_byte_rate + bytes;
current_byte_rate = count / d;
assert(current_byte_rate >= 0.0);
last_update_tv = *now;
}
/* Get the number of seconds the meter has been running: if it has been stopped,
the amount of time between start and stop, or if it is still running, the
amount of time between start and now. */
double RateMeter::elapsedTime(const struct timeval *now) const {
struct timeval tv;
const struct timeval *end_tv;
assert(isSet(&start_tv));
if (isSet(&stop_tv)) {
end_tv = &stop_tv;
} else if (now == NULL) {
gettimeofday(&tv, NULL);
end_tv = &tv;
} else {
end_tv = now;
}
return TIMEVAL_SUBTRACT(*end_tv, start_tv) / 1000000.0;
}
/* Returns true if tv has been initialized; i.e., its members are not all
zero. */
bool RateMeter::isSet(const struct timeval *tv) {
return tv->tv_sec != 0 || tv->tv_usec != 0;
}
ScanProgressMeter::ScanProgressMeter(char *stypestr) {
scantypestr = strdup(stypestr);
gettimeofday(&begin, NULL);

View File

@@ -129,6 +129,42 @@ void adjust_timeouts(struct timeval sent, struct timeout_info *to);
time is recorded in it */
void enforce_scan_delay(struct timeval *tv);
/* This class implements current and lifetime average data rates for packets and
bytes. */
class RateMeter {
public:
RateMeter();
void start(const struct timeval *now = NULL);
void stop(const struct timeval *now = NULL);
void record(u32 len, const struct timeval *now = NULL);
double getOverallPacketRate(const struct timeval *now = NULL) const;
double getCurrentPacketRate(const struct timeval *now = NULL, bool update =true);
double getOverallByteRate(const struct timeval *now = NULL) const;
double getCurrentByteRate(const struct timeval *now = NULL, bool update =true);
private:
/* How many seconds to look back when calculating the "current" rates. */
const double CURRENT_RATE_HISTORY;
/* When this meter started recording. */
struct timeval start_tv;
/* When this meter stopped recording. */
struct timeval stop_tv;
/* The last time the current sample rates were updated. */
struct timeval last_update_tv;
unsigned long long num_packets;
unsigned long long num_bytes;
double current_packet_rate;
double current_byte_rate;
void update(u32 packets, u32 bytes, const struct timeval *now);
double elapsedTime(const struct timeval *now = NULL) const;
static bool isSet(const struct timeval *tv);
};
class ScanProgressMeter {
public:
/* A COPY of stypestr is made and saved for when stats are printed */

View File

@@ -175,8 +175,8 @@
#define TIMEVAL_SEC_SUBTRACT(a,b) ((a).tv_sec - (b).tv_sec + (((a).tv_usec < (b).tv_usec) ? - 1 : 0))
/* assign one timeval to another timeval plus some msecs: a = b + msecs */
#define TIMEVAL_MSEC_ADD(a, b, msecs) (a).tv_sec = (b).tv_sec + ((msecs) / 1000); (a).tv_usec = (b).tv_usec + ((msecs) % 1000) * 1000; (a).tv_sec += (a).tv_usec / 1000000; (a).tv_usec %= 1000000
#define TIMEVAL_ADD(a, b, usecs) (a).tv_sec = (b).tv_sec + ((usecs) / 1000000); (a).tv_usec = (b).tv_usec + ((usecs) % 1000000); (a).tv_sec += (a).tv_usec / 1000000; (a).tv_usec %= 1000000
#define TIMEVAL_MSEC_ADD(a, b, msecs) { (a).tv_sec = (b).tv_sec + ((msecs) / 1000); (a).tv_usec = (b).tv_usec + ((msecs) % 1000) * 1000; (a).tv_sec += (a).tv_usec / 1000000; (a).tv_usec %= 1000000; }
#define TIMEVAL_ADD(a, b, usecs) { (a).tv_sec = (b).tv_sec + ((usecs) / 1000000); (a).tv_usec = (b).tv_usec + ((usecs) % 1000000); (a).tv_sec += (a).tv_usec / 1000000; (a).tv_usec %= 1000000; }
/* Return num if it is between min and max. Otherwise return min or
max (whichever is closest to num), */