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