1
2 /***************************************************************************
3 * PacketStats.cc -- The PacketStats class handles packet statistics. It *
4 * is intended to keep track of the number of packets and bytes sent and *
5 * received, keep track of start and finish times, etc. *
6 * *
7 ***********************IMPORTANT NMAP LICENSE TERMS************************
8 * *
9 * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap *
10 * Project"). Nmap is also a registered trademark of the Nmap Project. *
11 * *
12 * This program is distributed under the terms of the Nmap Public Source *
13 * License (NPSL). The exact license text applying to a particular Nmap *
14 * release or source code control revision is contained in the LICENSE *
15 * file distributed with that version of Nmap or source code control *
16 * revision. More Nmap copyright/legal information is available from *
17 * https://nmap.org/book/man-legal.html, and further information on the *
18 * NPSL license itself can be found at https://nmap.org/npsl. This header *
19 * summarizes some key points from the Nmap license, but is no substitute *
20 * for the actual license text. *
21 * *
22 * Nmap is generally free for end users to download and use themselves, *
23 * including commercial use. It is available from https://nmap.org. *
24 * *
25 * The Nmap license generally prohibits companies from using and *
26 * redistributing Nmap in commercial products, but we sell a special Nmap *
27 * OEM Edition with a more permissive license and special features for *
28 * this purpose. See https://nmap.org/oem *
29 * *
30 * If you have received a written Nmap license agreement or contract *
31 * stating terms other than these (such as an Nmap OEM license), you may *
32 * choose to use and redistribute Nmap under those terms instead. *
33 * *
34 * The official Nmap Windows builds include the Npcap software *
35 * (https://npcap.org) for packet capture and transmission. It is under *
36 * separate license terms which forbid redistribution without special *
37 * permission. So the official Nmap Windows builds may not be *
38 * redistributed without special permission (such as an Nmap OEM *
39 * license). *
40 * *
41 * Source is provided to this software because we believe users have a *
42 * right to know exactly what a program is going to do before they run it. *
43 * This also allows you to audit the software for security holes. *
44 * *
45 * Source code also allows you to port Nmap to new platforms, fix bugs, *
46 * and add new features. You are highly encouraged to submit your *
47 * changes as a Github PR or by email to the dev@nmap.org mailing list *
48 * for possible incorporation into the main distribution. Unless you *
49 * specify otherwise, it is understood that you are offering us very *
50 * broad rights to use your submissions as described in the Nmap Public *
51 * Source License Contributor Agreement. This is important because we *
52 * fund the project by selling licenses with various terms, and also *
53 * because the inability to relicense code has caused devastating *
54 * problems for other Free Software projects (such as KDE and NASM). *
55 * *
56 * The free version of Nmap is distributed in the hope that it will be *
57 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
58 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties, *
59 * indemnification and commercial support are all available through the *
60 * Npcap OEM program--see https://nmap.org/oem. *
61 * *
62 ***************************************************************************/
63
64 #include "nping.h"
65 #include "stats.h"
66 #include "NpingOps.h"
67 #include "output.h"
68
69
70
71 /*****************************************************************************/
72 /* Implementation of NpingTimer class. */
73 /*****************************************************************************/
74
NpingTimer()75 NpingTimer::NpingTimer(){
76 this->reset();
77 }
78
~NpingTimer()79 NpingTimer::~NpingTimer(){
80
81 }
82
reset()83 void NpingTimer::reset(){
84 this->start_tv.tv_sec=0;
85 this->start_tv.tv_usec=0;
86 this->stop_tv.tv_sec=0;
87 this->stop_tv.tv_usec=0;
88 }
89
90
start()91 int NpingTimer::start(){
92 if( timeval_set(&start_tv) || timeval_set(&stop_tv) )
93 return OP_FAILURE;
94 gettimeofday(&start_tv, NULL);
95 return OP_SUCCESS;
96 }
97
98
stop()99 int NpingTimer::stop(){
100 if( !timeval_set(&start_tv) || timeval_set(&stop_tv) )
101 return OP_FAILURE;
102 gettimeofday(&stop_tv, NULL);
103 return OP_SUCCESS;
104 }
105
106
elapsed(struct timeval * now)107 double NpingTimer::elapsed(struct timeval *now){
108 struct timeval tv;
109 const struct timeval *end_tv=NULL;
110 /* If for some reason the clock has not been started,
111 * just return 0 seconds elapsed. */
112 if(!timeval_set(&start_tv)){
113 return 0.0;
114 }
115 /* If the caller supplied a time, use it */
116 if(now!=NULL){
117 end_tv=now;
118 /* If the clock has been stopped already, use the stop time */
119 }else if(timeval_set(&stop_tv)){
120 end_tv = &stop_tv;
121 }else{
122 gettimeofday(&tv, NULL);
123 end_tv = &tv;
124 }
125 return TIMEVAL_FSEC_SUBTRACT(*end_tv, start_tv);
126 }
127
128
is_started()129 bool NpingTimer::is_started(){
130 return timeval_set(&this->start_tv);
131 }
132
133
is_stopped()134 bool NpingTimer::is_stopped(){
135 return timeval_set(&this->stop_tv);
136 }
137
138
139 /* Returns true if tv has been initialized; i.e., its members are not all zero. */
timeval_set(const struct timeval * tv)140 bool NpingTimer::timeval_set(const struct timeval *tv) {
141 return (tv->tv_sec != 0 || tv->tv_usec != 0);
142 }
143
144
145
146 /*****************************************************************************/
147 /* Implementation of NpingStats class. */
148 /*****************************************************************************/
149
NpingStats()150 NpingStats::NpingStats(){
151 this->reset();
152 }
153
154
~NpingStats()155 NpingStats::~NpingStats(){
156
157 }
158
159
reset()160 void NpingStats::reset(){
161 this->packets_sent=0;
162 this->packets_received=0;
163 this->packets_echoed=0;
164
165 this->bytes_sent=0;
166 this->bytes_received=0;
167 this->bytes_echoed=0;
168
169 this->echo_clients_served=0;
170
171 this->tx_timer.reset();
172 this->rx_timer.reset();
173 this->run_timer.reset();
174
175 } /* End of reset() */
176
177
178 /** Updates packet and byte count for transmitted packets. */
addSentPacket(u32 len)179 int NpingStats::addSentPacket(u32 len){
180 this->packets_sent++;
181 this->bytes_sent+=len;
182 return OP_SUCCESS;
183 } /* End of addSentPacket() */
184
185
186 /** Updates packet and byte count for received packets. */
addRecvPacket(u32 len)187 int NpingStats::addRecvPacket(u32 len){
188 this->packets_received++;
189 this->bytes_received+=len;
190 return OP_SUCCESS;
191 } /* End of addRecvPacket() */
192
193
194 /** Updates packet and byte count for echoed packets. */
addEchoedPacket(u32 len)195 int NpingStats::addEchoedPacket(u32 len){
196 this->packets_echoed++;
197 this->bytes_echoed+=len;
198 return OP_SUCCESS;
199 } /* End of addEchoedPacket() */
200
201
202 /** Updates count for echo clients served by the echo server. */
addEchoClientServed()203 int NpingStats::addEchoClientServed(){
204 this->echo_clients_served++;
205 return OP_SUCCESS;
206 } /* End of addEchoClientServed() */
207
208
startClocks()209 int NpingStats::startClocks(){
210 this->startTxClock();
211 this->startRxClock();
212 return OP_SUCCESS;
213 }
214
215
stopClocks()216 int NpingStats::stopClocks(){
217 this->stopTxClock();
218 this->stopRxClock();
219 return OP_SUCCESS;
220 }
221
222
startTxClock()223 int NpingStats::startTxClock(){
224 this->tx_timer.start();
225 return OP_SUCCESS;
226 }
227
228
stopTxClock()229 int NpingStats::stopTxClock(){
230 this->tx_timer.stop();
231 return OP_SUCCESS;
232 }
233
startRxClock()234 int NpingStats::startRxClock(){
235 this->rx_timer.start();
236 return OP_SUCCESS;
237 }
238
239
stopRxClock()240 int NpingStats::stopRxClock(){
241 this->rx_timer.stop();
242 return OP_SUCCESS;
243 }
244
245
startRuntime()246 int NpingStats::startRuntime(){
247 this->run_timer.start();
248 return OP_SUCCESS;
249 }
250
251
stopRuntime()252 int NpingStats::stopRuntime(){
253 this->run_timer.start();
254 return OP_SUCCESS;
255 }
256
257
elapsedTx()258 double NpingStats::elapsedTx(){
259 return this->tx_timer.elapsed();
260 }
261
262
elapsedRx()263 double NpingStats::elapsedRx(){
264 return this->rx_timer.elapsed();
265 }
266
267
elapsedRuntime(struct timeval * now)268 double NpingStats::elapsedRuntime(struct timeval *now){
269 return this->run_timer.elapsed(now);
270 }
271
272
getSentPackets()273 u64_t NpingStats::getSentPackets(){
274 return this->packets_sent;
275 } /* End of getSentPackets() */
276
277
getSentBytes()278 u64_t NpingStats::getSentBytes(){
279 return this->bytes_sent;
280 } /* End of getSentBytes() */
281
282
getRecvPackets()283 u64_t NpingStats::getRecvPackets(){
284 return this->packets_received;
285 } /* End of getRecvPackets() */
286
287
getRecvBytes()288 u64_t NpingStats::getRecvBytes(){
289 return this->bytes_received;
290 } /* End of getRecvBytes() */
291
292
getEchoedPackets()293 u64_t NpingStats::getEchoedPackets(){
294 return this->packets_echoed;
295 } /* End of getEchoedPackets() */
296
297
getEchoedBytes()298 u64_t NpingStats::getEchoedBytes(){
299 return this->bytes_echoed;
300 } /* End of getEchoedBytes() */
301
getEchoClientsServed()302 u32 NpingStats::getEchoClientsServed(){
303 return this->echo_clients_served;
304 } /* End of getEchoClientsServed() */
305
306
getLostPackets()307 u64_t NpingStats::getLostPackets(){
308 if(this->packets_sent <= this->packets_received)
309 return 0;
310 else
311 return this->packets_sent - this->packets_received;
312 } /* End of getLostPackets() */
313
314
getLostPacketPercentage()315 double NpingStats::getLostPacketPercentage(){
316 u32 pkt_rcvd=this->packets_received;
317 u32 pkt_sent=this->packets_sent;
318 u32 pkt_lost=(pkt_rcvd>=pkt_sent) ? 0 : (u32)(pkt_sent-pkt_rcvd);
319 /* Only compute percentage if we actually sent packets, don't do divisions
320 * by zero! (this could happen when user presses CTRL-C and we print the
321 * stats */
322 double percentlost=0.0;
323 if( pkt_lost!=0 && pkt_sent!=0)
324 percentlost=((double)pkt_lost)/((double)pkt_sent);
325 return percentlost;
326 } /* End of getLostPacketPercentage() */
327
328
getLostPacketPercentage100()329 double NpingStats::getLostPacketPercentage100(){
330 return this->getLostPacketPercentage()*100;
331 } /* End of getLostPacketPercentage100() */
332
333
getUnmatchedPackets()334 u64_t NpingStats::getUnmatchedPackets(){
335 if(this->packets_received <= this->packets_echoed)
336 return 0;
337 else
338 return this->packets_received - this->packets_echoed;
339 } /* End of getUnmatchedPackets() */
340
341
getUnmatchedPacketPercentage()342 double NpingStats::getUnmatchedPacketPercentage(){
343 u32 pkt_captured=this->packets_received;
344 u32 pkt_echoed=this->packets_echoed;
345 u32 pkt_unmatched=(pkt_captured<=pkt_echoed) ? 0 : (u32)(pkt_captured-pkt_echoed);
346 double percentunmatched=0.0;
347 if( pkt_unmatched!=0 && pkt_captured!=0)
348 percentunmatched=((double)pkt_unmatched)/((double)pkt_captured);
349 return percentunmatched;
350 } /* End of getUnmatchedPacketPercentage() */
351
352
getUnmatchedPacketPercentage100()353 double NpingStats::getUnmatchedPacketPercentage100(){
354 return this->getUnmatchedPacketPercentage()*100;
355 } /* End of getUnmatchedPacketPercentage100() */
356
357
getOverallTxPacketRate()358 double NpingStats::getOverallTxPacketRate(){
359 double elapsed = this->tx_timer.elapsed();
360 if(elapsed <= 0.0)
361 return 0.0;
362 else
363 return this->packets_sent / elapsed;
364 }
365
366
getOverallTxByteRate()367 double NpingStats::getOverallTxByteRate(){
368 double elapsed = this->tx_timer.elapsed();
369 if(elapsed <= 0.0)
370 return 0.0;
371 else
372 return this->bytes_sent / elapsed;
373 }
374
375
getOverallRxPacketRate()376 double NpingStats::getOverallRxPacketRate(){
377 double elapsed = this->rx_timer.elapsed();
378 if(elapsed <= 0.0)
379 return 0.0;
380 else
381 return this->packets_received / elapsed;
382 }
383
384
getOverallRxByteRate()385 double NpingStats::getOverallRxByteRate(){
386 double elapsed = this->rx_timer.elapsed();
387 if(elapsed <= 0.0)
388 return 0.0;
389 else
390 return this->bytes_received / elapsed;
391 }
392
393