1 
2 /***************************************************************************
3  * NpingOps.cc -- The NpingOps class contains global options, mostly based *
4  * on user-provided command-line settings.                                 *
5  *                                                                         *
6  ***********************IMPORTANT NMAP LICENSE TERMS************************
7  *                                                                         *
8  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
9  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
10  *                                                                         *
11  * This program is distributed under the terms of the Nmap Public Source   *
12  * License (NPSL). The exact license text applying to a particular Nmap    *
13  * release or source code control revision is contained in the LICENSE     *
14  * file distributed with that version of Nmap or source code control       *
15  * revision. More Nmap copyright/legal information is available from       *
16  * https://nmap.org/book/man-legal.html, and further information on the    *
17  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
18  * summarizes some key points from the Nmap license, but is no substitute  *
19  * for the actual license text.                                            *
20  *                                                                         *
21  * Nmap is generally free for end users to download and use themselves,    *
22  * including commercial use. It is available from https://nmap.org.        *
23  *                                                                         *
24  * The Nmap license generally prohibits companies from using and           *
25  * redistributing Nmap in commercial products, but we sell a special Nmap  *
26  * OEM Edition with a more permissive license and special features for     *
27  * this purpose. See https://nmap.org/oem                                  *
28  *                                                                         *
29  * If you have received a written Nmap license agreement or contract       *
30  * stating terms other than these (such as an Nmap OEM license), you may   *
31  * choose to use and redistribute Nmap under those terms instead.          *
32  *                                                                         *
33  * The official Nmap Windows builds include the Npcap software             *
34  * (https://npcap.org) for packet capture and transmission. It is under    *
35  * separate license terms which forbid redistribution without special      *
36  * permission. So the official Nmap Windows builds may not be              *
37  * redistributed without special permission (such as an Nmap OEM           *
38  * license).                                                               *
39  *                                                                         *
40  * Source is provided to this software because we believe users have a     *
41  * right to know exactly what a program is going to do before they run it. *
42  * This also allows you to audit the software for security holes.          *
43  *                                                                         *
44  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
45  * and add new features.  You are highly encouraged to submit your         *
46  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
47  * for possible incorporation into the main distribution. Unless you       *
48  * specify otherwise, it is understood that you are offering us very       *
49  * broad rights to use your submissions as described in the Nmap Public    *
50  * Source License Contributor Agreement. This is important because we      *
51  * fund the project by selling licenses with various terms, and also       *
52  * because the inability to relicense code has caused devastating          *
53  * problems for other Free Software projects (such as KDE and NASM).       *
54  *                                                                         *
55  * The free version of Nmap is distributed in the hope that it will be     *
56  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
57  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
58  * indemnification and commercial support are all available through the    *
59  * Npcap OEM program--see https://nmap.org/oem.                            *
60  *                                                                         *
61  ***************************************************************************/
62 
63 #ifdef WIN32
64 #include "winfix.h"
65 #endif
66 
67 #include "nping.h"
68 #include "nbase.h"
69 #include "NpingOps.h"
70 #include "utils.h"
71 #include "utils_net.h"
72 #include "ArgParser.h"
73 #include "output.h"
74 #include "common.h"
75 
76 
77 /******************************************************************************
78  *  Constructors and destructors                                              *
79  ******************************************************************************/
80 
81 /* Constructor */
NpingOps()82 NpingOps::NpingOps() {
83 
84     /* Probe modes */
85     mode=0;
86     mode_set=false;
87 
88     traceroute=false;
89     traceroute_set=false;
90 
91     /* Output */
92     vb=DEFAULT_VERBOSITY;
93     vb_set=false;
94 
95     dbg=DEFAULT_DEBUGGING;
96     dbg_set=false;
97 
98     show_sent_pkts=true;
99     show_sent_pkts_set=false;
100 
101     /* Operation and Performance */
102     pcount=0;
103     pcount_set=false;
104 
105     sendpref=0;
106     sendpref_set=false;
107 
108     send_eth=false;
109     send_eth_set=false;
110 
111     delay=0;
112     delay_set=false;
113 
114     memset(device, 0, MAX_DEV_LEN);
115     device_set=false;
116 
117     spoofsource=false;
118     spoofsource_set=false;
119 
120     bpf_filter_spec=NULL;
121     bpf_filter_spec_set=false;
122 
123     current_round=0;
124 
125     have_pcap=true;
126 
127     disable_packet_capture=false;
128     disable_packet_capture_set=false;
129 
130     /* Privileges */
131 /* If user did not specify --privileged or --unprivileged explicitly, try to
132  * determine if has root privileges. */
133 #if defined WIN32 || defined __amigaos__
134     /* TODO: Check this because although nmap does exactly the same, it has a this->have_pcap that may affect to this */
135     isr00t=true;
136 #else
137   if (getenv("NMAP_PRIVILEGED") || getenv("NPING_PRIVILEGED"))
138     isr00t=true;
139   else if (getenv("NMAP_UNPRIVILEGED") || getenv("NPING_UNPRIVILEGED"))
140     isr00t=false;
141   else
142     isr00t = !(geteuid());
143 #endif
144 
145     /* Payloads */
146     payload_type=PL_NONE;
147     payload_type_set=false;
148 
149     payload_buff=NULL;
150     payload_buff_set=false;
151 
152     payload_len=0;
153     payload_len_set=false;
154 
155     /* Roles */
156     role=0;
157     role_set=false;
158 
159     /* IP */
160     ttl=0;
161     ttl_set=false;
162 
163     tos=0;
164     tos_set=false;
165 
166     identification=0;
167     identification_set=false;
168 
169     mf=false;
170     mf_set=false;
171 
172     df=false;
173     df_set=false;
174 
175     mtu=0;
176     mtu_set=false;
177 
178     badsum_ip=false;
179     badsum_ip_set=false;
180 
181     ipversion=0;
182     ipversion_set=false;
183 
184     memset(&ipv4_src_address, 0, sizeof(struct in_addr));
185     ipv4_src_address_set=false;
186 
187     ip_options=NULL;
188     ip_options_set=false;
189 
190     /* IPv6 */
191     ipv6_tclass=0;
192     ipv6_tclass_set=false;
193 
194     ipv6_flowlabel=0;
195     ipv6_flowlabel_set=false;
196 
197     memset(&ipv6_src_address, 0, sizeof(struct in6_addr));
198     ipv6_src_address_set=false;
199 
200     /* TCP / UDP */
201     target_ports=NULL;
202     tportcount=0;
203     target_ports_set=false;
204 
205     source_port=0;
206     source_port_set=false;
207 
208     tcpseq=0;
209     tcpseq_set=false;
210 
211     memset(tcpflags, 0, 8);
212     tcpflags_set=false;
213 
214     tcpack=0;
215     tcpack_set=false;
216 
217     tcpwin=0;
218     tcpwin_set=false;
219 
220     badsum=false;
221     badsum_set=false;
222 
223     /* ICMP */
224     icmp_type=0;
225     icmp_type_set=false;
226 
227     icmp_code=0;
228     icmp_code_set=false;
229 
230     badsum_icmp=false;
231     badsum_icmp_set=false;
232 
233     icmp_redir_addr.s_addr=0;
234     icmp_redir_addr_set=false;
235 
236     icmp_paramprob_pnt=0;
237     icmp_paramprob_pnt_set=false;
238 
239     icmp_routeadv_ltime=0;
240     icmp_routeadv_ltime_set=false;
241 
242     icmp_id=0;
243     icmp_id_set=false;
244 
245     icmp_seq=0;
246     icmp_seq_set=false;
247 
248     icmp_orig_time=0;
249     icmp_orig_time_set=false;
250 
251     icmp_recv_time=0;
252     icmp_recv_time_set=false;
253 
254     icmp_trans_time=0;
255     icmp_trans_time_set=false;
256 
257     memset( icmp_advert_entry_addr, 0, sizeof(u32)*MAX_ICMP_ADVERT_ENTRIES );
258     memset( icmp_advert_entry_pref, 0, sizeof(u32)*MAX_ICMP_ADVERT_ENTRIES );
259     icmp_advert_entry_count=0;
260     icmp_advert_entry_set=false;
261 
262     /* Ethernet */
263     memset(src_mac, 0, 6);
264     src_mac_set=false;
265 
266     memset(dst_mac, 0, 6);
267     dst_mac_set=false;
268 
269     eth_type=0;
270     eth_type_set=false;
271 
272     arp_htype=0;
273     arp_htype_set=false;
274 
275     /* ARP/RARP */
276     arp_ptype=0;
277     arp_ptype_set=false;
278 
279     arp_hlen=0;
280     arp_hlen_set=false;
281 
282     arp_plen=0;
283     arp_plen_set=false;
284 
285     arp_opcode=0;
286     arp_opcode_set=false;
287 
288     memset(arp_sha, 0, 6);
289     arp_sha_set=false;
290 
291     memset(arp_tha, 0, 6);
292     arp_tha_set=false;
293 
294     arp_spa.s_addr=0;
295     arp_spa_set=false;
296 
297     arp_tpa.s_addr=0;
298     arp_tpa_set=false;
299 
300     /* Echo mode */
301     echo_port=DEFAULT_ECHO_PORT;
302     echo_port_set=false;
303 
304     do_crypto=true;
305 
306     echo_payload=false;
307 
308     echo_server_once=false;
309     echo_server_once_set=false;
310 
311     memset(echo_passphrase, 0, sizeof(echo_passphrase));
312     echo_passphrase_set=false;
313 
314     memset(&last_sent_pkt_time, 0, sizeof(struct timeval));
315 
316     delayed_rcvd_str=NULL;
317     delayed_rcvd_str_set=false;
318 
319 } /* End of NpingOps() */
320 
321 
322 /* Destructor */
~NpingOps()323 NpingOps::~NpingOps() {
324  if (payload_buff!=NULL)
325     free(payload_buff);
326  if ( ip_options!=NULL )
327     free(ip_options);
328  if ( target_ports!=NULL )
329     free(target_ports);
330  if (delayed_rcvd_str_set)
331    free(delayed_rcvd_str);
332  return;
333 } /* End of ~NpingOps() */
334 
335 
336 /******************************************************************************
337  *  Nping probe modes                                                         *
338  ******************************************************************************/
339 
340 /** Sets attribute "mode". Mode must be one of: TCP_CONNECT TCP, UDP, ICMP,
341  *  ARP
342  *  @return OP_SUCCESS on success.
343  *  @return OP_FAILURE in case of error. */
setMode(int md)344 int NpingOps::setMode(int md) {
345   if ( md!=TCP_CONNECT && md!=TCP && md!=UDP && md!=UDP_UNPRIV && md!=ICMP && md!=ARP )
346     return OP_FAILURE;
347   else{
348     this->mode=md;
349     this->mode_set=true;
350   }
351   return OP_SUCCESS;
352 } /* End of setMode() */
353 
354 
355 /** Returns value of attribute "mode". The value returned is supposed to be
356  *  one of : TCP_CONNECT, TCP, UDP, UDP_UNPRIV, ICMP, ARP */
getMode()357 int NpingOps::getMode() {
358   return mode;
359 } /* End of getMode() */
360 
361 
362 /* Returns true if option has been set */
issetMode()363 bool NpingOps::issetMode(){
364   return this->mode_set;
365 } /* End of isset() */
366 
367 
368 /** Takes a probe mode and returns an ASCII string with the name of the mode.
369  *  @warning Returned pointer is a static buffer that subsequent calls
370  *            will overwrite.
371  *  @return Pointer to the appropriate string on success and pointer to a
372  *          string containing "Unknown probe" in case of failure.
373  * */
mode2Ascii(int md)374 char * NpingOps::mode2Ascii(int md) {
375   static char buff[24];
376 
377   switch( md ){
378     case TCP_CONNECT:
379         sprintf(buff, "TCP-Connect");
380     break;
381 
382     case TCP:
383         sprintf(buff, "TCP");
384     break;
385 
386     case UDP:
387         sprintf(buff, "UDP");
388     break;
389 
390     case UDP_UNPRIV:
391         sprintf(buff, "UDP-Unprivileged");
392     break;
393 
394     case ICMP:
395         sprintf(buff, "ICMP");
396     break;
397 
398     case ARP:
399         sprintf(buff, "ARP");
400     break;
401 
402     default:
403         sprintf(buff, "Unknown mode");
404     break;
405  }
406  return buff;
407 } /* End of mode2Ascii() */
408 
409 
410 /** Returns value of attribute "traceroute" */
getTraceroute()411 bool NpingOps::getTraceroute() {
412   return traceroute;
413 } /* End of getTraceroute() */
414 
415 
416 /** Sets attribute traceroute to "true".
417  *  @return previous value of the attribute. */
enableTraceroute()418 bool NpingOps::enableTraceroute() {
419   bool prev = traceroute;
420   this->traceroute=true;
421   this->traceroute_set=true;
422   return prev;
423 } /* End of enableTraceroute() */
424 
425 
426 /** Sets attribute traceroute to "false".
427  *  @return previous value of the attribute. */
disableTraceroute()428 bool NpingOps::disableTraceroute() {
429   bool prev = traceroute;
430   this->traceroute=false;
431   this->traceroute_set=true;
432   return prev;
433 } /* End of disableTraceroute() */
434 
435 
436 /* Returns true if option has been set */
issetTraceroute()437 bool NpingOps::issetTraceroute(){
438   return this->traceroute_set;
439 } /* End of issetTraceroute() */
440 
441 
442 /******************************************************************************
443  * Output                                                                     *
444  ******************************************************************************/
445 
446 /** Sets verbosity level. Supplied level must be an integer between -4 and
447  *  4. Check man pages for details.
448  *
449  *  The thing here is that what the argument parser gets from the user is
450  *  number in the range [-4, 4]. However, in NpingOps we don't store negative
451  *  verbosity values, we just convert the supplied level into our internal
452  *  levels (QT_4, QT_3, ... , VB_0, VB_1, ..., VB_4)
453  *  So the rest of the code in Nping should check for these defines, rather
454  *  than checking for numbers. Check nping.h for more information on how to
455  *  handle verbosity levels.
456  *
457  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setVerbosity(int level)458 int NpingOps::setVerbosity(int level){
459    if( level < -4 || level > 4 ){
460         nping_fatal(QT_3,"setVerbosity(): Invalid verbosity level supplied\n");
461         return OP_FAILURE;
462    }else{
463         switch(level){
464             case -4:  vb=QT_4;  break;
465             case -3:  vb=QT_3;  break;
466             case -2:  vb=QT_2;  break;
467             case -1:  vb=QT_1;  break;
468             case  0:  vb=VB_0;  break;
469             case  1:  vb=VB_1;  break;
470             case  2:  vb=VB_2;  break;
471             case  3:  vb=VB_3;  break;
472             case  4:  vb=VB_4;  break;
473             default:
474                 nping_fatal(QT_3,"setVerbosity():2: Invalid verbosity level supplied\n");
475             break;
476         }
477     }
478     this->vb_set=true;
479     return OP_SUCCESS;
480 } /* End of setVerbosity() */
481 
482 
483 /** Returns value of attribute vb (current verbosity level) */
getVerbosity()484 int NpingOps::getVerbosity(){
485   return vb;
486 } /* End of getVerbosity() */
487 
488 
489 
490 /* Returns true if option has been set */
issetVerbosity()491 bool NpingOps::issetVerbosity(){
492   return this->vb_set;
493 } /* End of issetVerbosity() */
494 
495 
496 /** Increments verbosity level by one. (When it reaches VB_4 it stops
497   * getting incremented)
498   * @return previous verbosity level */
increaseVerbosity()499 int NpingOps::increaseVerbosity(){
500   this->vb_set=true;
501   if (vb < VB_4){
502     vb++;
503     return vb-1;
504   }else{
505     return vb;
506   }
507 } /* End of increaseVerbosity() */
508 
509 
510 /** Decreases verbosity level by one. (When it reaches QT_4 it stops
511   * getting incremented)
512   * @return previous verbosity level */
decreaseVerbosity()513 int NpingOps::decreaseVerbosity(){
514   this->vb_set=true;
515   if (vb > QT_4){
516     vb--;
517     return vb+1;
518   }else{
519     return vb;
520   }
521 } /* End of decreaseVerbosity() */
522 
523 
524 /** Sets debugging level. Supplied level must be an integer between DBG_0 and
525  *  DBG_9. Check file nping.h for details
526  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setDebugging(int level)527 int NpingOps::setDebugging(int level){
528   if( level < 0 || level > 9){
529     nping_fatal(QT_3,"setDebugging(): Invalid debugging level supplied\n");
530     return OP_FAILURE;
531   }else{
532     this->dbg= DBG_0  + level;
533   }
534   this->dbg_set=true;
535   return OP_SUCCESS;
536 } /* End of setDebugging() */
537 
538 
539 /** Returns value of attribute dbg (current debugging level) */
getDebugging()540 int NpingOps::getDebugging(){
541   return dbg;
542 } /* End of getDebugging() */
543 
544 
545 /** Increments debugging level by one. (When it reaches DBG_9 it stops
546   * getting incremented)
547   *   * @return previous verbosity level */
increaseDebugging()548 int NpingOps::increaseDebugging(){
549   this->dbg_set=true;
550   if (dbg < DBG_9){
551     dbg++;
552     return dbg-1;
553   }else{
554     return dbg;
555   }
556 } /* End of increaseDebugging() */
557 
558 
559 /* Returns true if option has been set */
issetDebugging()560 bool NpingOps::issetDebugging(){
561     return this->dbg_set;
562 } /* End of issetDebugging() */
563 
564 
565 /** Sets ShowSentPackets.
566  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setShowSentPackets(bool val)567 int NpingOps::setShowSentPackets(bool val){
568   this->show_sent_pkts=val;
569   this->show_sent_pkts_set=true;
570   return OP_SUCCESS;
571 } /* End of setShowSentPackets() */
572 
573 
574 /** Returns value of attribute show_sent_pkts */
showSentPackets()575 bool NpingOps::showSentPackets(){
576   return this->show_sent_pkts;
577 } /* End of showSentPackets() */
578 
579 
580 /* Returns true if option has been set */
issetShowSentPackets()581 bool NpingOps::issetShowSentPackets(){
582   return this->show_sent_pkts_set;
583 } /* End of issetShowSentPackets() */
584 
585 
586 
587 /******************************************************************************
588  *  Operation and Performance                                                 *
589  ******************************************************************************/
590 
591 /** Sets packet count (number of packets that should be sent to each target)
592  *  Supplied parameter must be a non-negative integer.
593  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setPacketCount(u32 val)594 int NpingOps::setPacketCount(u32 val){
595   /* If zero is supplied, use the highest possible value */
596   if( val==0 )
597     this->pcount=0xFFFFFFFF;
598   else
599     pcount=val;
600   this->pcount_set=true;
601   return OP_SUCCESS;
602 } /* End of setPacketCount() */
603 
604 
605 /** Returns value of attribute pcount (number of packets that should be sent
606  *  to each target)  */
getPacketCount()607 u32 NpingOps::getPacketCount(){
608   return this->pcount;
609 } /* End of getPacketCount() */
610 
611 
612 /* Returns true if option has been set */
issetPacketCount()613 bool NpingOps::issetPacketCount(){
614   return this->pcount_set;
615 } /* End of issetPacketCount() */
616 
617 
618 /** Sets attribute sendpref which defines user's preference for packet
619  *  sending. Supplied parameter must be an integer with one of these values:
620  *  PACKET_SEND_NOPREF, PACKET_SEND_ETH_WEAK, PACKET_SEND_ETH_STRONG,
621  *  PACKET_SEND_ETH, PACKET_SEND_IP_WEAK, PACKET_SEND_IP_STRONG, PACKET_SEND_IP
622  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setSendPreference(int v)623 int NpingOps::setSendPreference(int v){
624    if( v!=PACKET_SEND_NOPREF && v!=PACKET_SEND_ETH_WEAK &&
625        v!=PACKET_SEND_ETH_STRONG && v!=PACKET_SEND_ETH &&
626        v!=PACKET_SEND_IP_WEAK && v!=PACKET_SEND_IP_STRONG &&
627        v!=PACKET_SEND_IP ){
628         nping_fatal(QT_3,"setSendPreference(): Invalid value supplied\n");
629         return OP_FAILURE;
630     }else{
631         sendpref=v;
632     }
633     this->sendpref_set=true;
634     return OP_SUCCESS;
635 } /* End of setSendPreference() */
636 
637 
638 /** Returns value of attribute sendpref */
getSendPreference()639 int NpingOps::getSendPreference(){
640   return this->sendpref;
641 } /* End of getSendPreference() */
642 
643 
644 /* Returns true if option has been set */
issetSendPreference()645 bool NpingOps::issetSendPreference(){
646   return this->sendpref_set;
647 } /* End of issetSendPreference() */
648 
649 
650 /* Returns true if send preference is Ethernet */
sendPreferenceEthernet()651 bool NpingOps::sendPreferenceEthernet(){
652   if ( this->getSendPreference()==PACKET_SEND_ETH_WEAK )
653     return true;
654   else if (this->getSendPreference()==PACKET_SEND_ETH_STRONG)
655     return true;
656   else if (this->getSendPreference()==PACKET_SEND_ETH )
657     return true;
658   else
659     return false;
660 } /* End of sendPreferenceEthernet() */
661 
662 
663 /* Returns true if send preference is Ethernet */
sendPreferenceIP()664 bool NpingOps::sendPreferenceIP(){
665   if ( this->getSendPreference()==PACKET_SEND_IP_WEAK )
666     return true;
667   else if (this->getSendPreference()==PACKET_SEND_IP_STRONG)
668     return true;
669   else if (this->getSendPreference()==PACKET_SEND_IP )
670     return true;
671   else
672     return false;
673 } /* End of sendPreferenceIP() */
674 
675 
676 /** Sets SendEth.
677  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setSendEth(bool val)678 int NpingOps::setSendEth(bool val){
679   this->send_eth=val;
680   this->send_eth_set=true;
681   return OP_SUCCESS;
682 } /* End of setSendEth() */
683 
684 
685 /** Returns value of attribute send_eth */
sendEth()686 bool NpingOps::sendEth(){
687   return this->send_eth;
688 } /* End of getSendEth() */
689 
690 
691 /* Returns true if option has been set */
issetSendEth()692 bool NpingOps::issetSendEth(){
693   return this->send_eth_set;
694 } /* End of issetSendEth() */
695 
696 
697 /** Sets inter-probe delay. Supplied parameter is assumed to be in milliseconds
698  *  and must be a long integer greater than zero.
699  *  @warning timeout is assumed to be in milliseconds. Use tval2msecs() from
700  *           nbase to obtain a proper value.
701  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setDelay(long t)702 int NpingOps::setDelay(long t){
703   if( t < 0 )
704     nping_fatal(QT_3,"setDelay(): Invalid time supplied\n");
705   this->delay=t;
706   this->delay_set=true;
707   return OP_SUCCESS;
708 } /* End of setDelay() */
709 
710 
711 /** Returns value of attribute delay */
getDelay()712 long NpingOps::getDelay(){
713   return delay;
714 } /* End of getDelay() */
715 
716 
717 /* Returns true if option has been set */
issetDelay()718 bool NpingOps::issetDelay(){
719   return this->delay_set;
720 } /* End of issetDelay() */
721 
722 
723 /** Sets network device. Supplied parameter must be a valid network interface
724  *  name.
725  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setDevice(char * n)726 int NpingOps::setDevice(char *n){
727   if( n==NULL ){
728     nping_fatal(QT_3,"setDevice(): Invalid value supplied\n");
729   }else{
730     Strncpy(this->device, n, MAX_DEV_LEN-1);
731   }
732   this->device_set=true;
733   return OP_SUCCESS;
734 } /* End of setDevice() */
735 
736 
getDevice()737 char *NpingOps::getDevice(){
738   return this->device;
739 } /* End of getDevice() */
740 
741 
742 /* Returns true if option has been set */
issetDevice()743 bool NpingOps::issetDevice(){
744   return this->device_set;
745 } /* End of issetDevice() */
746 
747 
748 /** Returns true if user requested explicitly that he wants IP source
749  *  spoofing */
spoofSource()750 bool NpingOps::spoofSource(){
751   return this->spoofsource;
752 } /* End of spoofSource() */
753 
754 
getSpoofSource()755 bool NpingOps::getSpoofSource(){
756   return this->spoofsource;
757 } /* End of getSpoofSource() */
758 
759 
setSpoofSource()760 int NpingOps::setSpoofSource(){
761   this->spoofsource=true;
762   this->spoofsource_set=true;
763   return OP_SUCCESS;
764 } /* End of spoofSource() */
765 
766 
767 /* Returns true if option has been set */
issetSpoofSource()768 bool NpingOps::issetSpoofSource(){
769   return this->spoofsource_set;
770 } /* End of issetSpoofSource() */
771 
772 
773 /** Sets BPFFilterSpec.
774  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setBPFFilterSpec(char * val)775 int NpingOps::setBPFFilterSpec(char *val){
776   this->bpf_filter_spec=val;
777   this->bpf_filter_spec_set=true;
778   return OP_SUCCESS;
779 } /* End of setBPFFilterSpec() */
780 
781 
782 /** Returns value of attribute bpf_filter_spec */
getBPFFilterSpec()783 char *NpingOps::getBPFFilterSpec(){
784   return this->bpf_filter_spec;
785 } /* End of getBPFFilterSpec() */
786 
787 
788 /* Returns true if option has been set */
issetBPFFilterSpec()789 bool NpingOps::issetBPFFilterSpec(){
790   return this->bpf_filter_spec_set;
791 } /* End of issetBPFFilterSpec() */
792 
793 
794 /** Sets CurrentRound.
795  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setCurrentRound(int val)796 int NpingOps::setCurrentRound(int val){
797   this->current_round=val;
798   return OP_SUCCESS;
799 } /* End of setCurrentRound() */
800 
801 
802 /** Returns value of attribute current_round */
getCurrentRound()803 int NpingOps::getCurrentRound(){
804   return this->current_round;
805 } /* End of getCurrentRound() */
806 
807 
havePcap()808 bool NpingOps::havePcap(){
809   return this->have_pcap;
810 } /* End of havePcap() */
811 
812 
setHavePcap(bool val)813 int NpingOps::setHavePcap(bool val){
814   this->have_pcap=val;
815   return OP_SUCCESS;
816 } /* End of setHavePcap() */
817 
818 
819 /** Sets DisablePacketCapture.
820  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setDisablePacketCapture(bool val)821 int NpingOps::setDisablePacketCapture(bool val){
822   this->disable_packet_capture=val;
823   this->disable_packet_capture_set=true;
824   return OP_SUCCESS;
825 } /* End of setDisablePacketCapture() */
826 
827 
828 /** Returns value of attribute disable_packet_capture */
disablePacketCapture()829 bool NpingOps::disablePacketCapture(){
830   return this->disable_packet_capture;
831 } /* End of disablePacketCapture() */
832 
833 
834 /* Returns true if option has been set */
issetDisablePacketCapture()835 bool NpingOps::issetDisablePacketCapture(){
836   return this->disable_packet_capture_set;
837 } /* End of issetDisablePacketCapture() */
838 
839 /** Sets the IP version that will be used in all packets. Supplied parameter
840  *  must be either IP_VERSION_4 or IP_VERSION_&.
841  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setIPVersion(u8 val)842 int NpingOps::setIPVersion(u8 val){
843   if( val!=IP_VERSION_4 && val!=IP_VERSION_6 ){
844     nping_fatal(QT_3,"setIPVersion(): Invalid value supplied\n");
845     return OP_FAILURE;
846   }else{
847     this-> ipversion=val;
848   }
849   this->ipversion_set=true;
850   return OP_SUCCESS;
851 } /* End of setIPVersion() */
852 
853 
854 /** Returns value of attribute ipversion. */
getIPVersion()855 int NpingOps::getIPVersion(){
856   return ipversion;
857 } /* End of getIPVersion() */
858 
859 
860 /* Returns true if option has been set */
issetIPVersion()861 bool NpingOps::issetIPVersion(){
862   return this->ipversion_set;
863 } /* End of issetIPversion() */
864 
865 
866 /* Returns true if we are using IPv4 */
ipv4()867 bool NpingOps::ipv4(){
868   if( this->getIPVersion() == IP_VERSION_4 )
869     return true;
870   else
871     return false;
872 } /* End of ipv4() */
873 
874 
875 /* Returns true if we are using IPv6 */
ipv6()876 bool NpingOps::ipv6(){
877   if( this->getIPVersion() == IP_VERSION_6 )
878     return true;
879   else
880     return false;
881 } /* End of ipv6() */
882 
883 
884 /* Returns true if we are sending IPv6 packets at raw TCP level (using a
885  * useless and boring IPv6 socket that doesn't let us include our own IPv6
886  * header)*/
ipv6UsingSocket()887 bool NpingOps::ipv6UsingSocket(){
888   if( this->getIPVersion() == IP_VERSION_6 && this->sendEth()==false)
889     return true;
890   else
891     return false;
892 } /* End of ipv6UsingSocket() */
893 
894 
895 /* Returns AF_INET or AF_INET6, depending on current configuration */
af()896 int NpingOps::af(){
897   if( this->getIPVersion() == IP_VERSION_6 )
898     return AF_INET6;
899   else
900     return AF_INET;
901 } /* End of af() */
902 
903 
904 /******************************************************************************
905  *  User types and Privileges                                                 *
906  ******************************************************************************/
907 
908 /** Sets value of attribute isr00t.
909  *  @returns previous isr00t value */
setIsRoot(int v)910 int NpingOps::setIsRoot(int v) {
911   int prev=this->isr00t;
912   this->isr00t = (v==0) ? 0 : 1;
913   return prev;
914 } /* End of setIsRoot() */
915 
916 
917 /** Sets attribute isr00t to value 1.
918  *  @returns previous isr00t value */
setIsRoot()919 int NpingOps::setIsRoot() {
920   int prev=this->isr00t;
921   this->isr00t=1;
922  return prev;
923 } /* End of setIsRoot() */
924 
925 
926 /* Returns the state of attribute isr00t */
isRoot()927 bool NpingOps::isRoot() {
928   return (this->isr00t);
929 } /* End of isRoot() */
930 
931 
932 /******************************************************************************
933  *  Payloads                                                                  *
934  ******************************************************************************/
935 
936 /** Sets payload type. Supplied parameter must be one of: PL_RAND, PL_HEX or
937  *  PL_FILE;
938  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setPayloadType(int t)939 int NpingOps::setPayloadType(int t){
940   if( t!=PL_RAND && t!=PL_HEX && t!=PL_FILE && t!=PL_STRING){
941     nping_fatal(QT_3,"setPayloadType(): Invalid value supplied\n");
942     return OP_FAILURE;
943   }else{
944     payload_type=t;
945   }
946   this->payload_type_set=true;
947   return OP_SUCCESS;
948 } /* End of setPayloadType() */
949 
950 
951 /** Returns value of attribute payload_type */
getPayloadType()952 int NpingOps::getPayloadType(){
953   return payload_type;
954 } /* End of getPayloadType() */
955 
956 
957 /* Returns true if option has been set */
issetPayloadType()958 bool NpingOps::issetPayloadType(){
959   return this->payload_type_set;
960 } /* End of issetPayloadType() */
961 
962 
963 /** Sets payload buffer pointer. Supplied pointer must be a free()able
964  *  non-NULL pointer; Supplied length must be a positive integer.
965  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setPayloadBuffer(u8 * p,int len)966 int NpingOps::setPayloadBuffer(u8 *p, int len){
967   if( p==NULL || len < 0 ){
968     nping_fatal(QT_3,"setPayloadBuffer(): Invalid value supplied\n");
969     return OP_FAILURE;
970   }else{
971     this->payload_buff=p;
972     this->payload_len=len;
973   }
974   this->payload_buff_set=true;
975   this->payload_len_set=true;
976   return OP_SUCCESS;
977 } /* End of setPayloadBuffer() */
978 
979 
980 /** Returns value of attribute payload_type */
getPayloadBuffer()981 u8 *NpingOps::getPayloadBuffer(){
982   return this->payload_buff;
983 } /* End of getPayloadBuffer() */
984 
985 
986 /* Returns true if option has been set */
issetPayloadBuffer()987 bool NpingOps::issetPayloadBuffer(){
988   return this->payload_buff_set;
989 } /* End of issetPayloadBuffer() */
990 
991 
992 /** Returns value of attribute payload_len */
getPayloadLen()993 int NpingOps::getPayloadLen(){
994   return this->payload_len;
995 } /* End of getPayloadLen() */
996 
997 
998 /* Returns true if option has been set */
issetPayloadLen()999 bool NpingOps::issetPayloadLen(){
1000   return this->payload_len_set;
1001 } /* End of issetPayloadLen() */
1002 
1003 
1004 /******************************************************************************
1005  *  Roles (normal, client, server... )                                        *
1006  ******************************************************************************/
1007 
1008 /** Sets nping's role. Supplied argument must be one of: ROLE_NORMAL,
1009  *  ROLE_CLIENT or ROLE_SERVER.
1010  *  @return previous value of attribute "role" or OP_FAILURE in case of error.
1011  *  */
setRole(int r)1012 int NpingOps::setRole(int r){
1013   int prev = this->role;
1014   if (r!=ROLE_NORMAL && r!=ROLE_CLIENT && r!=ROLE_SERVER){
1015     nping_warning(QT_2,"setRoleClient(): Invalid role supplied");
1016     return OP_FAILURE;
1017   }
1018   else
1019     this->role=r;
1020   this->role_set=true;
1021   return prev;
1022 } /* End of setRole() */
1023 
1024 
1025 /** Sets nping's role to ROLE_CLIENT.
1026  *  @return previous value of attribute "role".  */
setRoleClient()1027 int NpingOps::setRoleClient(){
1028   int prev = this->role;
1029   this->role=ROLE_CLIENT;
1030   this->role_set=true;
1031   return prev;
1032 } /* End of setRoleClient() */
1033 
1034 
1035 /** Sets nping's role to ROLE_SERVER.
1036  *  @return previous value of attribute "role". */
setRoleServer()1037 int NpingOps::setRoleServer(){
1038   int prev = this->role;
1039   this->role=ROLE_SERVER;
1040   this->role_set=true;
1041   return prev;
1042 } /* End of setRoleServer() */
1043 
1044 
1045 /** Sets nping's role to ROLE_NORMAL.
1046  *  @return previous value of attribute "role". */
setRoleNormal()1047 int NpingOps::setRoleNormal(){
1048   int prev = this->role;
1049   this->role=ROLE_NORMAL;
1050   this->role_set=true;
1051   return prev;
1052 } /* End of setRoleNormal() */
1053 
1054 /* Returns nping role. */
getRole()1055 int NpingOps::getRole(){
1056   return this->role;
1057 } /* End of getRole() */
1058 
1059 
1060 /* Returns true if option has been set */
issetRole()1061 bool NpingOps::issetRole(){
1062   return this->role_set;
1063 } /* End of issetRole() */
1064 
1065 
1066 
1067 /******************************************************************************
1068  * Internet Protocol  Version 4                                               *
1069  ******************************************************************************/
1070 
1071 /** Sets IPv4 TTL / IPv6 hop limit. Supplied parameter must be an integer
1072  *  between 0 and 255 (included).
1073  *  @return OP_SUCCESS                                                       */
setTTL(u8 t)1074 int NpingOps::setTTL(u8 t){
1075   this->ttl=t;
1076   this->ttl_set=true;
1077   return OP_SUCCESS;
1078 } /* End of setTTL() */
1079 
1080 
1081 /** Sets IPv4 TTL / IPv6 hop limit. This a wrapper for setTTL(). It is provided
1082  *  for consistency with IPv6 option setters.
1083  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setHopLimit(u8 t)1084 int NpingOps::setHopLimit(u8 t){
1085   return setTTL(t);
1086 } /* End of setHopLimit() */
1087 
1088 
1089 /** Returns value of attribute ttl */
getTTL()1090 u8 NpingOps::getTTL(){
1091   return ttl;
1092 } /* End of getTTL() */
1093 
1094 
1095 /** Returns value of attribute ttl */
getHopLimit()1096 u8 NpingOps::getHopLimit(){
1097   return getTTL();
1098 } /* End of getHopLimit() */
1099 
1100 
1101 /* Returns true if option has been set */
issetTTL()1102 bool NpingOps::issetTTL(){
1103   return this->ttl_set;
1104 } /* End of issetTTL() */
1105 
1106 
1107 /* Returns true if option has been set */
issetHopLimit()1108 bool NpingOps::issetHopLimit(){
1109   return issetTTL();
1110 } /* End of issetHopLimit() */
1111 
1112 
1113 /** Sets IP TOS. Supplied parameter must be 0<=n<=255
1114  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setTOS(u8 val)1115 int NpingOps::setTOS(u8 val){
1116   this->tos=val;
1117   this->tos_set=true;
1118   return OP_SUCCESS;
1119 } /* End of setTOS() */
1120 
1121 
1122 /** Returns value of attribute TOS */
getTOS()1123 u8 NpingOps::getTOS(){
1124   return this->tos;
1125 } /* End of getTOS() */
1126 
1127 
1128 /* Returns true if option has been set */
issetTOS()1129 bool NpingOps::issetTOS(){
1130   return this->tos_set;
1131 } /* End of isset() */
1132 
1133 
1134 /** Sets IP Identification. Supplied parameter must be 0<=n<=255
1135  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setIdentification(u16 val)1136 int NpingOps::setIdentification(u16 val){
1137   this->identification=val;
1138   this->identification_set=true;
1139   return OP_SUCCESS;
1140 } /* End of setIdentification() */
1141 
1142 
1143 /** Returns value of attribute Identification */
getIdentification()1144 u16 NpingOps::getIdentification(){
1145   return this->identification;
1146 } /* End of getIdentification() */
1147 
1148 
1149 /* Returns true if option has been set */
issetIdentification()1150 bool NpingOps::issetIdentification(){
1151   return this->identification_set;
1152 } /* End of issetIdentification() */
1153 
1154 
setMF()1155 int NpingOps::setMF(){
1156   this->mf = true;
1157   this->mf_set=true;
1158   return OP_SUCCESS;
1159 } /* End of setMF() */
1160 
1161 
1162 /* Get MF flag */
getMF()1163 bool NpingOps::getMF(){
1164   return this->mf;
1165 } /* End of getMF() */
1166 
1167 
1168 /** Set DF flag */
setDF()1169 int NpingOps::setDF(){
1170   this->df = true;
1171   this->df_set=true;
1172   return OP_SUCCESS;
1173 } /* End of setDF() */
1174 
1175 
1176 /** Get DF flag */
getDF()1177 bool NpingOps::getDF(){
1178   return this->df;
1179 } /* End of getDF() */
1180 
1181 
1182 /* Returns true if option has been set */
issetMF()1183 bool NpingOps::issetMF(){
1184   return this->mf_set;
1185 } /* End of isset() */
1186 
1187 
1188 /* Returns true if option has been set */
issetDF()1189 bool NpingOps::issetDF(){
1190   return this->df_set;
1191 } /* End of isset() */
1192 
1193 
1194 /** Sets Maximum Transmission Unit length. Supplied parameter must be a positive
1195  *  integer and must be a multiple of 8.
1196  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setMTU(u32 t)1197 int NpingOps::setMTU(u32 t){
1198   if(t==0 || (t%8)!=0){
1199     nping_fatal(QT_3,"setMTU(): Invalid mtu supplied\n");
1200   }else{
1201     this->mtu=t;
1202     this->mtu_set=true;
1203   }
1204   return OP_SUCCESS;
1205 } /* End of setMTU() */
1206 
1207 
1208 /** Returns value of attribute mtu */
getMTU()1209 u32 NpingOps::getMTU(){
1210   return this->mtu;
1211 } /* End of getMTU() */
1212 
1213 
1214 /* Returns true if option has been set */
issetMTU()1215 bool NpingOps::issetMTU(){
1216   return this->mtu_set;
1217 } /* End of issetMTU() */
1218 
1219 
1220 /** Sets attribute badsum_ip to "true". (Generate invalid checksums in IP
1221  *  packets)
1222  *  @return previous value of the attribute. */
enableBadsumIP()1223 bool NpingOps::enableBadsumIP() {
1224   bool prev = this->badsum_ip;
1225   this->badsum_ip=true;
1226   this->badsum_ip_set=true;
1227   return prev;
1228 } /* End of enableBadsumIP() */
1229 
1230 
1231 /** Sets attribute badsum_ip to "false". (Do NOT Generate invalid checksums
1232  *  in IP packets)
1233  *  @return previous value of the attribute. */
disableBadsumIP()1234 bool NpingOps::disableBadsumIP() {
1235    bool prev = badsum_ip;
1236    badsum_ip=false;
1237    this->badsum_ip_set=true;
1238    return prev;
1239 } /* End of disableBadsumIP() */
1240 
1241 
1242 /** Returns value of attribute badsum_ip */
getBadsumIP()1243 bool NpingOps::getBadsumIP() {
1244    return this->badsum_ip;
1245 } /* End of getBadsumIP() */
1246 
1247 
1248 /* Returns true if option has been set */
issetBadsumIP()1249 bool NpingOps::issetBadsumIP(){
1250   return this->badsum_ip_set;
1251 } /* End of issetBadsumIP() */
1252 
1253 
1254 /** @warning Supplied parameter must be in NETWORK byte order */
setIPv4SourceAddress(struct in_addr i)1255 int NpingOps::setIPv4SourceAddress(struct in_addr i){
1256   this->ipv4_src_address=i;
1257   this->ipv4_src_address_set=true;
1258   return OP_SUCCESS;
1259 } /* End of setIPv4SourceAddress() */
1260 
1261 
getIPv4SourceAddress()1262 struct in_addr NpingOps::getIPv4SourceAddress(){
1263   return ipv4_src_address;
1264 } /* End of getIPv4SourceAddress() */
1265 
1266 
1267 /* Returns true if option has been set */
issetIPv4SourceAddress()1268 bool NpingOps::issetIPv4SourceAddress(){
1269   return this->ipv4_src_address_set;
1270 } /* End of issetIPv4SourceAddress() */
1271 
1272 
1273 /** @warning  This method makes a copy of the supplied buffer. That copy will
1274  *  be free()ed by the NpingOps destructor.                                  */
setIPOptions(char * txt)1275 int NpingOps::setIPOptions(char *txt){
1276   if (txt==NULL)
1277     nping_fatal(QT_3,"setIPOptions(): NULL pointer supplied\n");
1278   this->ip_options=strdup(txt) ;
1279   this->ip_options_set=true;
1280   return OP_SUCCESS;
1281 } /* End of setIPOptions() */
1282 
1283 
getIPOptions()1284 char *NpingOps::getIPOptions(){
1285   return this->ip_options;
1286 } /* End of getIPOptions() */
1287 
1288 
issetIPOptions()1289 bool NpingOps::issetIPOptions(){
1290   return this->ip_options_set;
1291 } /* End of issetIPOptions() */
1292 
1293 
1294 /******************************************************************************
1295  * Internet Protocol  Version 6                                               *
1296  ******************************************************************************/
1297 /** Sets TrafficClass.
1298  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setTrafficClass(u8 val)1299 int NpingOps::setTrafficClass(u8 val){
1300   this->ipv6_tclass=val;
1301   this->ipv6_tclass_set=true;
1302   return OP_SUCCESS;
1303 } /* End of setTrafficClass() */
1304 
1305 
1306 /** Returns value of attribute ipv6_tclass */
getTrafficClass()1307 u8 NpingOps::getTrafficClass(){
1308   return this->ipv6_tclass;
1309 } /* End of getTrafficClass() */
1310 
1311 
1312 /* Returns true if option has been set */
issetTrafficClass()1313 bool NpingOps::issetTrafficClass(){
1314   return this->ipv6_tclass_set;
1315 } /* End of issetTrafficClass() */
1316 
1317 
1318 /** Sets FlowLabel.
1319  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setFlowLabel(u32 val)1320 int NpingOps::setFlowLabel(u32 val){
1321   this->ipv6_flowlabel=val;
1322   this->ipv6_flowlabel_set=true;
1323   return OP_SUCCESS;
1324 } /* End of setFlowLabel() */
1325 
1326 
1327 /** Returns value of attribute ipv6_flowlabel */
getFlowLabel()1328 u32 NpingOps::getFlowLabel(){
1329   return this->ipv6_flowlabel;
1330 } /* End of getFlowLabel() */
1331 
1332 
1333 /* Returns true if option has been set */
issetFlowLabel()1334 bool NpingOps::issetFlowLabel(){
1335   return this->ipv6_flowlabel_set;
1336 } /* End of issetFlowLabel() */
1337 
1338 
1339 
setIPv6SourceAddress(u8 * val)1340 int NpingOps::setIPv6SourceAddress(u8 *val){
1341   if(val==NULL)
1342     nping_fatal(QT_3,"setIPv6SourceAddress(): NULL pointer supplied\n");
1343   memcpy(this->ipv6_src_address.s6_addr, val, 16);
1344   this->ipv6_src_address_set=true;
1345   return OP_SUCCESS;
1346 } /* End of setIPv6SourceAddress() */
1347 
1348 
setIPv6SourceAddress(struct in6_addr val)1349 int NpingOps::setIPv6SourceAddress(struct in6_addr val){
1350   this->ipv6_src_address = val;
1351   this->ipv6_src_address_set=true;
1352   return OP_SUCCESS;
1353 } /* End of setIPv6SourceAddress() */
1354 
1355 
getIPv6SourceAddress()1356 struct in6_addr NpingOps::getIPv6SourceAddress(){
1357   return ipv6_src_address;
1358 } /* End of getIPv6SourceAddress() */
1359 
1360 
1361 /* Returns true if option has been set */
issetIPv6SourceAddress()1362 bool NpingOps::issetIPv6SourceAddress(){
1363   return this->ipv6_src_address_set;
1364 } /* End of issetIPv6SourceAddress() */
1365 
1366 
1367 /* Returns a pointer to a sockaddr_storage structure that contains the
1368  * source IP address. This function takes into account this->getIPVersion()
1369  * an returns an IPv4 sockaddr_in or an IPv6 sockaddr_in6 struct.  */
getSourceSockAddr()1370 struct sockaddr_storage *NpingOps::getSourceSockAddr(){
1371   static struct sockaddr_storage ss;
1372   return getSourceSockAddr(&ss);
1373 } /* End of getSourceSockAddr() */
1374 
1375 
1376 /* Returns a pointer to the supplied sockaddr_storage structure that now
1377  * contains the source IP address. This function takes into account
1378  * this->getIPVersion() an returns an IPv4 sockaddr_in or an IPv6
1379  * sockaddr_in6 struct.  */
getSourceSockAddr(struct sockaddr_storage * ss)1380 struct sockaddr_storage *NpingOps::getSourceSockAddr(struct sockaddr_storage *ss){
1381   struct sockaddr_in *s4 = (struct sockaddr_in*)ss;
1382   struct sockaddr_in6 *s6 = (struct sockaddr_in6*)ss;
1383   memset(ss, 0, sizeof(struct sockaddr_storage));
1384   if( this->getIPVersion() == IP_VERSION_4){
1385     if(this->spoofSource())
1386         s4->sin_addr=getIPv4SourceAddress();
1387     else
1388         s4->sin_addr.s_addr=INADDR_ANY;
1389     s4->sin_family=AF_INET;
1390     if(this->issetSourcePort())
1391         s4->sin_port=htons(this->getSourcePort());
1392     else
1393         s4->sin_port=0;
1394   }
1395   else if (this->getIPVersion() == IP_VERSION_6){
1396     if(this->spoofSource())
1397         s6->sin6_addr=this->getIPv6SourceAddress();
1398     else
1399         s6->sin6_addr=in6addr_any;
1400     s6->sin6_addr=this->getIPv6SourceAddress();
1401     s6->sin6_family=AF_INET6;
1402     if(this->issetSourcePort())
1403         s6->sin6_port=htons(this->getSourcePort());
1404     else
1405         s6->sin6_port=0;
1406   }else{
1407     nping_fatal(QT_3, "NpingOps::getSourceSockAddr(): IP version unset.");
1408   }
1409   return ss;
1410 } /* End of getSourceSockAddr() */
1411 
1412 
1413 
1414 /******************************************************************************
1415  * Transmission Control Protocol and User Datagram Protocol                   *
1416  ******************************************************************************/
1417 
1418 /** @warning Returned ports are in HOST byte order */
getTargetPorts(int * len)1419 u16 *NpingOps::getTargetPorts( int *len ){
1420   if( this->tportcount <= 0)
1421     return NULL;
1422   if(len!=NULL)
1423     *len=this->tportcount;
1424   return this->target_ports;
1425 } /* End of getTargetPorts() */
1426 
1427 
1428 /** @warning ports in the supplied array must be in HOST byte order */
setTargetPorts(u16 * pnt,int n)1429 int NpingOps::setTargetPorts( u16 *pnt, int n ){
1430   if(this->tportcount>65536 || this->tportcount<0)
1431     nping_fatal(QT_3, "setTargetPorts():: Invalid number of ports supplied.");
1432   this->target_ports=pnt;
1433   this->tportcount=n;
1434   this->target_ports_set=true;
1435   return OP_SUCCESS;
1436 } /* End of setTargetPorts() */
1437 
1438 
1439 /* Returns true if option has been set */
issetTargetPorts()1440 bool NpingOps::issetTargetPorts(){
1441   return this->target_ports_set;
1442 } /* End of issetTargetPorts() */
1443 
1444 /*Returns true if the scan type can use the -p option*/
scan_mode_uses_target_ports(int mode)1445 bool NpingOps::scan_mode_uses_target_ports(int mode){
1446     return (mode==TCP_CONNECT || mode==TCP || mode == UDP || mode == UDP_UNPRIV);
1447 } /*End of scan_mode_uses_target_ports*/
1448 
1449 /** Sets TCP/UPD source port. Supplied parameter must be an integer >=0 &&
1450  * <=65535
1451  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setSourcePort(u16 val)1452 int NpingOps::setSourcePort(u16 val){
1453   this->source_port=val;
1454   this->source_port_set=true;
1455   return OP_SUCCESS;
1456 } /* End of setSourcePort() */
1457 
1458 
1459 /** Returns value of attribute source_port */
getSourcePort()1460 u16 NpingOps::getSourcePort(){
1461   return this->source_port;
1462 } /* End of getSourcePort() */
1463 
1464 
1465 /* Returns true if option has been set */
issetSourcePort()1466 bool NpingOps::issetSourcePort(){
1467   return this->source_port_set;
1468 } /* End of issetSourcePort() */
1469 
1470 
1471 /** Sets TCP Seq number. Supplied parameter must be a positive integer between
1472  *  0 and 2^32 -1
1473  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setTCPSequence(u32 val)1474 int NpingOps::setTCPSequence(u32 val){
1475   this->tcpseq=val;
1476   this->tcpseq_set=true;
1477   return OP_SUCCESS;
1478 } /* End of setTCPSequence() */
1479 
1480 
1481 /** Returns value of attribute tcpseq */
getTCPSequence()1482 u32 NpingOps::getTCPSequence(){
1483   return this->tcpseq;
1484 } /* End of getTCPSequence() */
1485 
1486 
1487 /** Returns true if option has been set */
issetTCPSequence()1488 bool NpingOps::issetTCPSequence(){
1489   return this->tcpseq_set;
1490 } /* End of issetTCPSequence() */
1491 
1492 
1493 /** Sets TCP Ack. Supplied parameter must be a positive integer between 0 and
1494  *  2^32 -1
1495  *  @return OP_SUCCESS                                                       */
setTCPAck(u32 val)1496 int NpingOps::setTCPAck(u32 val){
1497   this->tcpack=val;
1498   this->tcpack_set=true;
1499   return OP_SUCCESS;
1500 } /* End of setTCPAck() */
1501 
1502 
1503 /** Returns value of attribute tcpack */
getTCPAck()1504 u32 NpingOps::getTCPAck(){
1505   return this->tcpack;
1506 } /* End of getTCPAck() */
1507 
1508 
1509 /** Returns true if option has been set */
issetTCPAck()1510 bool NpingOps::issetTCPAck(){
1511   return this->tcpack_set;
1512 } /* End of issetTCPAck() */
1513 
1514 
setFlagTCP(int flag)1515 int NpingOps::setFlagTCP(int flag){
1516   if (flag < FLAG_CWR || flag > FLAG_FIN)
1517     nping_fatal(QT_3,"setFlagTCP(): Invalid flag supplied\n");
1518   else
1519     this->tcpflags[flag]=1;
1520   this->tcpflags_set=true;
1521   return OP_SUCCESS;
1522 } /* End of setFlagTCP() */
1523 
1524 
setAllFlagsTCP()1525 int NpingOps::setAllFlagsTCP(){
1526   for(int i=FLAG_CWR; i<=FLAG_FIN; i++)
1527     this->tcpflags[i]=1;
1528   this->tcpflags_set=true;
1529   return OP_SUCCESS;
1530 } /* End of setFlagTCP() */
1531 
1532 
unsetAllFlagsTCP()1533 int NpingOps::unsetAllFlagsTCP(){
1534   for(int i=FLAG_CWR; i<=FLAG_FIN; i++)
1535     this->tcpflags[i]=0;
1536   this->tcpflags_set=true;
1537   return OP_SUCCESS;
1538 } /* End of setFlagTCP() */
1539 
1540 
getFlagTCP(int flag)1541 int NpingOps::getFlagTCP(int flag){
1542   if (flag < FLAG_CWR || flag > FLAG_FIN)
1543     nping_fatal(QT_3,"setFlagTCP(): Invalid flag supplied\n");
1544   return this->tcpflags[flag];
1545 } /* End of getFlagTCP() */
1546 
1547 
getTCPFlags()1548 u8 NpingOps::getTCPFlags(){
1549  u8 octet=0x00;
1550   if(this->getFlagTCP(FLAG_CWR))
1551     octet |= TH_CWR;
1552   if(this->getFlagTCP(FLAG_ECN))
1553     octet |= TH_ECN;
1554   if(this->getFlagTCP(FLAG_URG))
1555     octet |= TH_URG;
1556   if(this->getFlagTCP(FLAG_ACK))
1557     octet |= TH_ACK;
1558   if(this->getFlagTCP(FLAG_PSH))
1559     octet |= TH_PSH;
1560   if(this->getFlagTCP(FLAG_RST))
1561     octet |= TH_RST;
1562   if(this->getFlagTCP(FLAG_SYN))
1563     octet |= TH_SYN;
1564   if(this->getFlagTCP(FLAG_FIN))
1565     octet |= TH_FIN;
1566  return octet;
1567 } /* End of getTCPFlags() */
1568 
1569 
1570 /* Returns true if option has been set */
issetTCPFlags()1571 bool NpingOps::issetTCPFlags(){
1572   return this->tcpflags_set;
1573 } /* End of isset() */
1574 
1575 
1576 /** Sets TCP Window. Supplied parameter must be a positive integer between 0 and
1577  *  2^32 -1
1578  *  @return OP_SUCCESS                                                       */
setTCPWindow(u16 val)1579 int NpingOps::setTCPWindow(u16 val){
1580   this->tcpwin=val;
1581   this->tcpwin_set=true;
1582   return OP_SUCCESS;
1583 } /* End of setTCPWindow() */
1584 
1585 
1586 /** Returns value of attribute tcpwin */
getTCPWindow()1587 u16 NpingOps::getTCPWindow(){
1588   return this->tcpwin;
1589 } /* End of getTCPWindow() */
1590 
1591 
1592 /** Returns true if option has been set */
issetTCPWindow()1593 bool NpingOps::issetTCPWindow(){
1594   return this->tcpwin_set;
1595 } /* End of issetTCPWindow() */
1596 
1597 
1598 /** Sets attribute badsum to "true". (Generate invalid checksums in UDP / TCP
1599  *  packets)
1600  *  @return previous value of the attribute. */
enableBadsum()1601 bool NpingOps::enableBadsum() {
1602   bool prev = this->badsum;
1603   this->badsum=true;
1604   this->badsum_set=true;
1605   return prev;
1606 } /* End of enableBadsumTCP() */
1607 
1608 
1609 /** Sets attribute traceroute to "false". (Do NOT Generate invalid checksums
1610  *  in UDP / TCP packets)
1611  *  @return previous value of the attribute. */
disableBadsum()1612 bool NpingOps::disableBadsum() {
1613   bool prev = this->badsum;
1614   this->badsum=false;
1615   this->badsum_set=true;
1616   return prev;
1617 } /* End of disableBadsum() */
1618 
1619 
1620 /** Returns value of attribute badsum */
getBadsum()1621 bool NpingOps::getBadsum() {
1622   return this->badsum;
1623 } /* End of getBadsum() */
1624 
1625 
1626 /* Returns true if option has been set */
issetBadsum()1627 bool NpingOps::issetBadsum(){
1628   return this->badsum_set;
1629 } /* End of issetBadsum() */
1630 
1631 
1632 
1633 /******************************************************************************
1634  *  Internet Control Message Protocol                                         *
1635  ******************************************************************************/
1636 /** Sets ICMPType.
1637  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPType(u8 val)1638 int NpingOps::setICMPType(u8 val){
1639   this->icmp_type=val;
1640   this->icmp_type_set=true;
1641   return OP_SUCCESS;
1642 } /* End of setICMPType() */
1643 
1644 
1645 /** Returns value of attribute icmp_type */
getICMPType()1646 u8 NpingOps::getICMPType(){
1647   return this->icmp_type;
1648 } /* End of getICMPType() */
1649 
1650 
1651 /* Returns true if option has been set */
issetICMPType()1652 bool NpingOps::issetICMPType(){
1653   return this->icmp_type_set;
1654 } /* End of issetICMPType() */
1655 
1656 
1657 /** Sets ICMPCode.
1658  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPCode(u8 val)1659 int NpingOps::setICMPCode(u8 val){
1660   this->icmp_code=val;
1661   this->icmp_code_set=true;
1662   return OP_SUCCESS;
1663 } /* End of setICMPCode() */
1664 
1665 
1666 /** Returns value of attribute icmp_code */
getICMPCode()1667 u8 NpingOps::getICMPCode(){
1668   return this->icmp_code;
1669 } /* End of getICMPCode() */
1670 
1671 
1672 /* Returns true if option has been set */
issetICMPCode()1673 bool NpingOps::issetICMPCode(){
1674   return this->icmp_code_set;
1675 } /* End of issetICMPCode() */
1676 
1677 
1678 /** Sets attribute badsum_icmp to "true". (Generate invalid checksums in ICMP
1679  *  packets)
1680  *  @return previous value of the attribute. */
enableBadsumICMP()1681 bool NpingOps::enableBadsumICMP() {
1682   bool prev = this->badsum_icmp;
1683   this->badsum_icmp=true;
1684   this->badsum_icmp_set=true;
1685   return prev;
1686 } /* End of enableBadsumICMPTCP() */
1687 
1688 
1689 /** Sets attribute traceroute to "false". (Do NOT Generate invalid checksums
1690  *  in UDP / TCP packets)
1691  *  @return previous value of the attribute. */
disableBadsumICMP()1692 bool NpingOps::disableBadsumICMP() {
1693   bool prev = this->badsum_icmp;
1694   this->badsum_icmp=false;
1695   this->badsum_icmp_set=true;
1696   return prev;
1697 } /* End of disableBadsumICMP() */
1698 
1699 
1700 /** Returns value of attribute badsum_icmp */
getBadsumICMP()1701 bool NpingOps::getBadsumICMP() {
1702   return this->badsum_icmp;
1703 } /* End of getBadsumICMP() */
1704 
1705 
1706 /* Returns true if option has been set */
issetBadsumICMP()1707 bool NpingOps::issetBadsumICMP(){
1708   return this->badsum_icmp_set;
1709 } /* End of issetBadsumICMP() */
1710 
1711 
1712 /** Sets ICMPRedirectAddress.
1713  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPRedirectAddress(struct in_addr val)1714 int NpingOps::setICMPRedirectAddress(struct in_addr val){
1715   this->icmp_redir_addr=val;
1716   this->icmp_redir_addr_set=true;
1717   return OP_SUCCESS;
1718 } /* End of setICMPRedirectAddress() */
1719 
1720 
1721 /** Returns value of attribute icmp_redir_addr */
getICMPRedirectAddress()1722 struct in_addr NpingOps::getICMPRedirectAddress(){
1723   return this->icmp_redir_addr;
1724 } /* End of getICMPRedirectAddress() */
1725 
1726 
1727 /* Returns true if option has been set */
issetICMPRedirectAddress()1728 bool NpingOps::issetICMPRedirectAddress(){
1729   return this->icmp_redir_addr_set;
1730 } /* End of issetICMPRedirectAddress() */
1731 
1732 
1733 /** Sets ICMPParamProblemPointer.
1734  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPParamProblemPointer(u8 val)1735 int NpingOps::setICMPParamProblemPointer(u8 val){
1736   this->icmp_paramprob_pnt=val;
1737   this->icmp_paramprob_pnt_set=true;
1738   return OP_SUCCESS;
1739 } /* End of setICMPParamProblemPointer() */
1740 
1741 
1742 /** Returns value of attribute icmp_paramprob_pnt */
getICMPParamProblemPointer()1743 u8 NpingOps::getICMPParamProblemPointer(){
1744   return this->icmp_paramprob_pnt;
1745 } /* End of getICMPParamProblemPointer() */
1746 
1747 
1748 /* Returns true if option has been set */
issetICMPParamProblemPointer()1749 bool NpingOps::issetICMPParamProblemPointer(){
1750   return this->icmp_paramprob_pnt_set;
1751 } /* End of issetICMPParamProblemPointer() */
1752 
1753 
1754 /** Sets ICMPRouterAdvLifetime.
1755  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPRouterAdvLifetime(u16 val)1756 int NpingOps::setICMPRouterAdvLifetime(u16 val){
1757   this->icmp_routeadv_ltime=val;
1758   this->icmp_routeadv_ltime_set=true;
1759   return OP_SUCCESS;
1760 } /* End of setICMPRouterAdvLifetime() */
1761 
1762 
1763 /** Returns value of attribute icmp_routeadv_ltime */
getICMPRouterAdvLifetime()1764 u16 NpingOps::getICMPRouterAdvLifetime(){
1765   return this->icmp_routeadv_ltime;
1766 } /* End of getICMPRouterAdvLifetime() */
1767 
1768 
1769 /* Returns true if option has been set */
issetICMPRouterAdvLifetime()1770 bool NpingOps::issetICMPRouterAdvLifetime(){
1771   return this->icmp_routeadv_ltime_set;
1772 } /* End of issetICMPRouterAdvLifetime() */
1773 
1774 
1775 /** Sets ICMPIdentifier.
1776  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPIdentifier(u16 val)1777 int NpingOps::setICMPIdentifier(u16 val){
1778   this->icmp_id=val;
1779   this->icmp_id_set=true;
1780   return OP_SUCCESS;
1781 } /* End of setICMPIdentifier() */
1782 
1783 /** Returns value of attribute icmp_id */
getICMPIdentifier()1784 u16 NpingOps::getICMPIdentifier(){
1785   return this->icmp_id;
1786 } /* End of getICMPIdentifier() */
1787 
1788 
1789 /* Returns true if option has been set */
issetICMPIdentifier()1790 bool NpingOps::issetICMPIdentifier(){
1791   return this->icmp_id_set;
1792 } /* End of issetICMPIdentifier() */
1793 
1794 
1795 /** Sets ICMPSequence.
1796  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPSequence(u16 val)1797 int NpingOps::setICMPSequence(u16 val){
1798   this->icmp_seq=val;
1799   this->icmp_seq_set=true;
1800   return OP_SUCCESS;
1801 } /* End of setICMPSequence() */
1802 
1803 
1804 /** Returns value of attribute icmp_seq */
getICMPSequence()1805 u16 NpingOps::getICMPSequence(){
1806   return this->icmp_seq;
1807 } /* End of getICMPSequence() */
1808 
1809 
1810 /* Returns true if option has been set */
issetICMPSequence()1811 bool NpingOps::issetICMPSequence(){
1812   return this->icmp_seq_set;
1813 } /* End of issetICMPSequence() */
1814 
1815 
1816 /** Sets ICMPOriginateTimestamp.
1817  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPOriginateTimestamp(u32 val)1818 int NpingOps::setICMPOriginateTimestamp(u32 val){
1819   this->icmp_orig_time=val;
1820   this->icmp_orig_time_set=true;
1821   return OP_SUCCESS;
1822 } /* End of setICMPOriginateTimestamp() */
1823 
1824 
1825 /** Returns value of attribute icmp_orig_time */
getICMPOriginateTimestamp()1826 u32 NpingOps::getICMPOriginateTimestamp(){
1827   return this->icmp_orig_time;
1828 } /* End of getICMPOriginateTimestamp() */
1829 
1830 
1831 /* Returns true if option has been set */
issetICMPOriginateTimestamp()1832 bool NpingOps::issetICMPOriginateTimestamp(){
1833   return this->icmp_orig_time_set;
1834 } /* End of issetICMPOriginateTimestamp() */
1835 
1836 
1837 /** Sets ICMPReceiveTimestamp.
1838  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPReceiveTimestamp(u32 val)1839 int NpingOps::setICMPReceiveTimestamp(u32 val){
1840   this->icmp_recv_time=val;
1841   this->icmp_recv_time_set=true;
1842   return OP_SUCCESS;
1843 } /* End of setICMPReceiveTimestamp() */
1844 
1845 
1846 /** Returns value of attribute icmp_recv_time */
getICMPReceiveTimestamp()1847 u32 NpingOps::getICMPReceiveTimestamp(){
1848   return this->icmp_recv_time;
1849 } /* End of getICMPReceiveTimestamp() */
1850 
1851 
1852 /* Returns true if option has been set */
issetICMPReceiveTimestamp()1853 bool NpingOps::issetICMPReceiveTimestamp(){
1854   return this->icmp_recv_time_set;
1855 } /* End of issetICMPReceiveTimestamp() */
1856 
1857 
1858 /** Sets ICMPTransmitTimestamp.
1859  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setICMPTransmitTimestamp(u32 val)1860 int NpingOps::setICMPTransmitTimestamp(u32 val){
1861   this->icmp_trans_time=val;
1862   this->icmp_trans_time_set=true;
1863   return OP_SUCCESS;
1864 } /* End of setICMPTransmitTimestamp() */
1865 
1866 
1867 /** Returns value of attribute icmp_trans_time */
getICMPTransmitTimestamp()1868 u32 NpingOps::getICMPTransmitTimestamp(){
1869   return this->icmp_trans_time;
1870 } /* End of getICMPTransmitTimestamp() */
1871 
1872 
1873 /* Returns true if option has been set */
issetICMPTransmitTimestamp()1874 bool NpingOps::issetICMPTransmitTimestamp(){
1875   return this->icmp_trans_time_set;
1876 } /* End of issetICMPTransmitTimestamp() */
1877 
1878 
addICMPAdvertEntry(struct in_addr addr,u32 pref)1879 int NpingOps::addICMPAdvertEntry(struct in_addr addr, u32 pref ){
1880   if( this->icmp_advert_entry_count > MAX_ICMP_ADVERT_ENTRIES )
1881     return OP_FAILURE;
1882   this->icmp_advert_entry_addr[this->icmp_advert_entry_count] = addr;
1883   this->icmp_advert_entry_pref[this->icmp_advert_entry_count] = pref;
1884   this->icmp_advert_entry_count++;
1885   this->icmp_advert_entry_set=true;
1886   return OP_SUCCESS;
1887 } /* End of addICMPAdvertEntry() */
1888 
1889 
1890 /** @param num means that the caller wants to obtain the num-th entry.
1891  *  Count starts in 0 so the supplied value must be
1892  *  0 <= num < getICMPAdvertEntryCount() */
getICMPAdvertEntry(int num,struct in_addr * addr,u32 * pref)1893 int NpingOps::getICMPAdvertEntry(int num, struct in_addr *addr, u32 *pref){
1894   if( num<0 || num>=icmp_advert_entry_count )
1895     nping_fatal(QT_3,"getICMPAdvertEntry(): Supplied index is out of bounds.\n");
1896   if( addr==NULL || pref==NULL)
1897     nping_fatal(QT_3,"getICMPAdvertEntry(): NULL pointer supplied\n");
1898   *addr =  this->icmp_advert_entry_addr[num];
1899   *pref =  this->icmp_advert_entry_pref[num];
1900   return OP_SUCCESS;
1901 } /* End of getICMPAdvertEntry() */
1902 
1903 
getICMPAdvertEntryCount()1904 int NpingOps::getICMPAdvertEntryCount(){
1905   return this->icmp_advert_entry_count;
1906 } /* End of getICMPAdvertEntryCount()*/
1907 
issetICMPAdvertEntry()1908 bool NpingOps::issetICMPAdvertEntry(){
1909   return this->icmp_advert_entry_set;
1910 } /* End of issetICMPAdvertEntry()*/
1911 
1912 
1913 
1914 /******************************************************************************
1915  *  Ethernet                                                                  *
1916  ******************************************************************************/
1917 /** Sets SourceMAC.
1918  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setSourceMAC(u8 * val)1919 int NpingOps::setSourceMAC(u8 * val){
1920   memcpy(this->src_mac, val, 6);
1921   this->src_mac_set=true;
1922   return OP_SUCCESS;
1923 } /* End of setSourceMAC() */
1924 
1925 
1926 /** Returns value of attribute src_mac */
getSourceMAC()1927 u8 * NpingOps::getSourceMAC(){
1928   return this->src_mac;
1929 } /* End of getSourceMAC() */
1930 
1931 
1932 /* Returns true if option has been set */
issetSourceMAC()1933 bool NpingOps::issetSourceMAC(){
1934   return this->src_mac_set;
1935 } /* End of issetSourceMAC() */
1936 
1937 
1938 /** Sets DestMAC.
1939  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setDestMAC(u8 * val)1940 int NpingOps::setDestMAC(u8 * val){
1941   memcpy(this->dst_mac, val, 6);
1942   this->dst_mac_set=true;
1943   return OP_SUCCESS;
1944 } /* End of setDestMAC() */
1945 
1946 
1947 /** Returns value of attribute dst_mac */
getDestMAC()1948 u8 * NpingOps::getDestMAC(){
1949   return this->dst_mac;
1950 } /* End of getDestMAC() */
1951 
1952 
1953 /* Returns true if option has been set */
issetDestMAC()1954 bool NpingOps::issetDestMAC(){
1955   return this->dst_mac_set;
1956 } /* End of issetDestMAC() */
1957 
1958 /** Sets EtherType.
1959  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setEtherType(u16 val)1960 int NpingOps::setEtherType(u16 val){
1961   this->eth_type=val;
1962   this->eth_type_set=true;
1963   return OP_SUCCESS;
1964 } /* End of setEtherType() */
1965 
1966 
1967 /** Returns value of attribute eth_type */
getEtherType()1968 u16 NpingOps::getEtherType(){
1969   return this->eth_type;
1970 } /* End of getEtherType() */
1971 
1972 
1973 /* Returns true if option has been set */
issetEtherType()1974 bool NpingOps::issetEtherType(){
1975   return this->eth_type_set;
1976 } /* End of issetEtherType() */
1977 
1978 
1979 
1980 /******************************************************************************
1981  *  Address Resolution Protocol / Reverse Address Resolution Protocol         *
1982  ******************************************************************************/
1983 /** Sets ARPHardwareType.
1984  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPHardwareType(u16 val)1985 int NpingOps::setARPHardwareType(u16 val){
1986   this->arp_htype=val;
1987   this->arp_htype_set=true;
1988   return OP_SUCCESS;
1989 } /* End of setARPHardwareType() */
1990 
1991 
1992 /** Returns value of attribute arp_htype */
getARPHardwareType()1993 u16 NpingOps::getARPHardwareType(){
1994   return this->arp_htype;
1995 } /* End of getARPHardwareType() */
1996 
1997 
1998 /* Returns true if option has been set */
issetARPHardwareType()1999 bool NpingOps::issetARPHardwareType(){
2000   return this->arp_htype_set;
2001 } /* End of issetARPHardwareType() */
2002 
2003 
2004 /** Sets ARPProtocolType.
2005  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPProtocolType(u16 val)2006 int NpingOps::setARPProtocolType(u16 val){
2007   this->arp_ptype=val;
2008   this->arp_ptype_set=true;
2009   return OP_SUCCESS;
2010 } /* End of setARPProtocolType() */
2011 
2012 
2013 /** Returns value of attribute arp_ptype */
getARPProtocolType()2014 u16 NpingOps::getARPProtocolType(){
2015   return this->arp_ptype;
2016 } /* End of getARPProtocolType() */
2017 
2018 
2019 /* Returns true if option has been set */
issetARPProtocolType()2020 bool NpingOps::issetARPProtocolType(){
2021   return this->arp_ptype_set;
2022 } /* End of issetARPProtocolType() */
2023 
2024 
2025 /** Sets ARPHwAddrLen.
2026  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPHwAddrLen(u8 val)2027 int NpingOps::setARPHwAddrLen(u8 val){
2028   this->arp_hlen=val;
2029   this->arp_hlen_set=true;
2030   return OP_SUCCESS;
2031 } /* End of setARPHwAddrLen() */
2032 
2033 
2034 /** Returns value of attribute arp_hlen */
getARPHwAddrLen()2035 u8 NpingOps::getARPHwAddrLen(){
2036   return this->arp_hlen;
2037 } /* End of getARPHwAddrLen() */
2038 
2039 
2040 /* Returns true if option has been set */
issetARPHwAddrLen()2041 bool NpingOps::issetARPHwAddrLen(){
2042   return this->arp_hlen_set;
2043 } /* End of issetARPHwAddrLen() */
2044 
2045 
2046 /** Sets ARPProtoAddrLen.
2047  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPProtoAddrLen(u8 val)2048 int NpingOps::setARPProtoAddrLen(u8 val){
2049   this->arp_plen=val;
2050   this->arp_plen_set=true;
2051   return OP_SUCCESS;
2052 } /* End of setARPProtoAddrLen() */
2053 
2054 
2055 /** Returns value of attribute arp_plen */
getARPProtoAddrLen()2056 u8 NpingOps::getARPProtoAddrLen(){
2057   return this->arp_plen;
2058 } /* End of getARPProtoAddrLen() */
2059 
2060 
2061 /* Returns true if option has been set */
issetARPProtoAddrLen()2062 bool NpingOps::issetARPProtoAddrLen(){
2063   return this->arp_plen_set;
2064 } /* End of issetARPProtoAddrLen() */
2065 
2066 
2067 /** Sets ARPOpCode.
2068  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPOpCode(u16 val)2069 int NpingOps::setARPOpCode(u16 val){
2070   this->arp_opcode=val;
2071   this->arp_opcode_set=true;
2072   return OP_SUCCESS;
2073 } /* End of setARPOpCode() */
2074 
2075 
2076 /** Returns value of attribute arp_opcode */
getARPOpCode()2077 u16 NpingOps::getARPOpCode(){
2078   return this->arp_opcode;
2079 } /* End of getARPOpCode() */
2080 
2081 
2082 /* Returns true if option has been set */
issetARPOpCode()2083 bool NpingOps::issetARPOpCode(){
2084   return this->arp_opcode_set;
2085 } /* End of issetARPOpCode() */
2086 
2087 
2088 /** Sets ARPSenderHwAddr.
2089  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPSenderHwAddr(u8 * val)2090 int NpingOps::setARPSenderHwAddr(u8 * val){
2091   memcpy(this->arp_sha, val, 6); /* MAC Address (6 bytes) */
2092   this->arp_sha_set=true;
2093   return OP_SUCCESS;
2094 } /* End of setARPSenderHwAddr() */
2095 
2096 
2097 /** Returns value of attribute arp_sha */
getARPSenderHwAddr()2098 u8 * NpingOps::getARPSenderHwAddr(){
2099   return this->arp_sha;
2100 } /* End of getARPSenderHwAddr() */
2101 
2102 
2103 /* Returns true if option has been set */
issetARPSenderHwAddr()2104 bool NpingOps::issetARPSenderHwAddr(){
2105   return this->arp_sha_set;
2106 } /* End of issetARPSenderHwAddr() */
2107 
2108 
2109 /** Sets ARPTargetHwAddr.
2110  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPTargetHwAddr(u8 * val)2111 int NpingOps::setARPTargetHwAddr(u8 * val){
2112   memcpy(this->arp_tha, val, 6); /* MAC Address (6 bytes) */
2113   this->arp_tha_set=true;
2114   return OP_SUCCESS;
2115 } /* End of setARPTargetHwAddr() */
2116 
2117 
2118 /** Returns value of attribute arp_tha */
getARPTargetHwAddr()2119 u8 * NpingOps::getARPTargetHwAddr(){
2120   return this->arp_tha;
2121 } /* End of getARPTargetHwAddr() */
2122 
2123 
2124 /* Returns true if option has been set */
issetARPTargetHwAddr()2125 bool NpingOps::issetARPTargetHwAddr(){
2126   return this->arp_tha_set;
2127 } /* End of issetARPTargetHwAddr() */
2128 
2129 
2130 /** Sets ARPSenderProtoAddr.
2131  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPSenderProtoAddr(struct in_addr val)2132 int NpingOps::setARPSenderProtoAddr(struct in_addr val){
2133   this->arp_spa=val;
2134   this->arp_spa_set=true;
2135   return OP_SUCCESS;
2136 } /* End of setARPSenderProtoAddr() */
2137 
2138 
2139 /** Returns value of attribute arp_spa */
getARPSenderProtoAddr()2140 struct in_addr NpingOps::getARPSenderProtoAddr(){
2141   return this->arp_spa;
2142 } /* End of getARPSenderProtoAddr() */
2143 
2144 
2145 /* Returns true if option has been set */
issetARPSenderProtoAddr()2146 bool NpingOps::issetARPSenderProtoAddr(){
2147   return this->arp_spa_set;
2148 } /* End of issetARPSenderProtoAddr() */
2149 
2150 
2151 /** Sets ARPTargetProtoAddr.
2152  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setARPTargetProtoAddr(struct in_addr val)2153 int NpingOps::setARPTargetProtoAddr(struct in_addr val){
2154   this->arp_tpa=val;
2155   this->arp_tpa_set=true;
2156   return OP_SUCCESS;
2157 } /* End of setARPTargetProtoAddr() */
2158 
2159 
2160 /** Returns value of attribute arp_tpa */
getARPTargetProtoAddr()2161 struct in_addr NpingOps::getARPTargetProtoAddr(){
2162   return this->arp_tpa;
2163 } /* End of getARPTargetProtoAddr() */
2164 
2165 
2166 /* Returns true if option has been set */
issetARPTargetProtoAddr()2167 bool NpingOps::issetARPTargetProtoAddr(){
2168   return this->arp_tpa_set;
2169 } /* End of issetARPTargetProtoAddr() */
2170 
2171 
2172 /** Sets EchoPort.
2173  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
setEchoPort(u16 val)2174 int NpingOps::setEchoPort(u16 val){
2175   this->echo_port=val;
2176   this->echo_port_set=true;
2177   return OP_SUCCESS;
2178 } /* End of setEchoPort() */
2179 
2180 
2181 /** Returns value of attribute echo_port */
getEchoPort()2182 u16 NpingOps::getEchoPort(){
2183   return this->echo_port;
2184 } /* End of getEchoPort() */
2185 
2186 
2187 /* Returns true if option has been set */
issetEchoPort()2188 bool NpingOps::issetEchoPort(){
2189   return this->echo_port_set;
2190 } /* End of issetEchoPort() */
2191 
2192 
setEchoPassphrase(const char * str)2193 int NpingOps::setEchoPassphrase(const char *str){
2194   strncpy(this->echo_passphrase, str, sizeof(echo_passphrase)-1);
2195   this->echo_passphrase_set=true;
2196   return OP_SUCCESS;
2197 } /* End of setEchoPassphrase() */
2198 
2199 
getEchoPassphrase()2200 char *NpingOps::getEchoPassphrase(){
2201   return this->echo_passphrase;
2202 } /* End of getEchoPassphrase() */
2203 
2204 
issetEchoPassphrase()2205 bool NpingOps::issetEchoPassphrase(){
2206   return this->echo_passphrase_set;
2207 } /* End of issetEchoPassphrase() */
2208 
2209 /** Sets value of this->echo_server_once. When true, the echo server
2210   * will exit after attending one client. */
setOnce(bool val)2211 int NpingOps::setOnce(bool val){
2212   this->echo_server_once=val;
2213   this->echo_server_once_set=true;
2214   return OP_SUCCESS;
2215 } /* End of once() */
2216 
2217 
2218 /** Returns value of attribute echo_port */
once()2219 bool NpingOps::once(){
2220   return this->echo_server_once;
2221 } /* End of once() */
2222 
2223 
2224 /******************************************************************************
2225  *  Option Validation                                                         *
2226  ******************************************************************************/
2227 
validateOptions()2228 void NpingOps::validateOptions() {
2229 
2230 /** DETERMINE ROOT PRIVILEGES ************************************************/
2231 const char *privreq = "root privileges";
2232 #ifdef WIN32
2233     //if (!this->have_pcap)
2234         privreq = "that WinPcap version 3.1 or higher and iphlpapi.dll be installed. You seem to be missing one or both of these.  Winpcap is available from http://www.winpcap.org.  iphlpapi.dll comes with Win98 and later operating systems and NT 4.0 with SP4 or greater.  For previous Windows versions, you may be able to take iphlpapi.dll from another system and place it in your system32 dir (e.g. c:\\windows\\system32)";
2235 #endif
2236 
2237 if (this->havePcap()==false){
2238     #ifdef WIN32
2239         nping_fatal(QT_3, "Nping requires %s", privreq);
2240     #else
2241         nping_fatal(QT_3, "Nping requires libpcap to be installed on your system.");
2242     #endif
2243 }
2244 
2245 
2246 /** ROLE SELECTION ***********************************************************/
2247   /* Ensure that at least one role is selected */
2248   if ( !this->issetRole() ) {
2249       this->setRoleNormal();
2250   }
2251 
2252 /** TARGET SPECIFICATION *****************************************************/
2253   /* Check if user entered at least one target spec */
2254   if( this->getRole() == ROLE_NORMAL ){
2255     if ( this->targets.getTargetSpecCount() <= 0 )
2256         nping_fatal(QT_3,"WARNING: No targets were specified, so 0 hosts pinged.");
2257   }else if( this->getRole() == ROLE_CLIENT ){
2258     if ( this->targets.getTargetSpecCount() <= 0 )
2259         nping_fatal(QT_3,"No echo server was specified.");
2260   }
2261 
2262 /** IP VERSION ***************************************************************/
2263   /* Default to IP version 4 */
2264   if( !this->issetIPVersion() )
2265     this->setIPVersion( IP_VERSION_4 );
2266 
2267 
2268 /** PROBE MODE SELECTION *****************************************************/
2269   /* Ensure that one probe mode is selected */
2270   if( !this->issetMode() ){
2271       if ( this->isRoot() ){
2272         if( !this->ipv6() )
2273             this->setMode(ICMP);
2274         else
2275             this->setMode(TCP);
2276       }
2277       else
2278         this->setMode(TCP_CONNECT);
2279   }
2280 
2281 /** PACKET COUNT / ROUNDS ****************************************************/
2282   if( !this->issetPacketCount() ){
2283       /* If --traceroute is set, the packet count is higher */
2284       if(this->issetTraceroute() )
2285           this->setPacketCount( TRACEROUTE_PACKET_COUNT );
2286       else
2287           this->setPacketCount( DEFAULT_PACKET_COUNT );
2288   }
2289 
2290 
2291   if( !this->issetDelay() )
2292     this->setDelay( DEFAULT_DELAY );
2293 
2294 /** UDP UNPRIVILEGED MODE? ***************************************************/
2295   /* If user is NOT root and specified UDP mode, check if he did not specify
2296    * any option that requires privileges. In that case, we enter
2297    * UDP-Unprivileged mode, where users can send UDP packets and read responses
2298    * trough a normal UDP socket.  */
2299   if( !this->isRoot() && this->getMode()==UDP && canRunUDPWithoutPrivileges() )
2300     this->setMode( UDP_UNPRIV );
2301 
2302 /** CHECK PRIVILEGES FOR CURRENT ROLE ****************************************/
2303   if( !this->isRoot() && (this->getRole()==ROLE_SERVER || this->getRole()==ROLE_CLIENT) )
2304     nping_fatal(QT_3,"Echo mode requires %s.", privreq);
2305 
2306 /** CHECK PRIVILEGES FOR CURRENT MODE ****************************************/
2307   if( !this->isRoot() && this->getMode()!=UDP_UNPRIV && this->getMode()!=TCP_CONNECT )
2308     nping_fatal(QT_3,"Mode %s requires %s.", this->mode2Ascii( this->getMode() ), privreq);
2309 
2310 
2311 /** DEFAULT HEADER PARAMETERS *************************************************/
2312   this->setDefaultHeaderValues();
2313 
2314 /** ARP MODE RELATED PARAMETERS *********************************************/
2315   if(this->getMode()==ARP && this->ipv6()) {
2316     nping_fatal(QT_3, "Sorry, ARP does not support IPv6 and Nping does not yet support NDP.");
2317   }
2318 
2319 /** TCP CONNECT RELATED PARAMETERS *********************************************/
2320   if(this->getMode()==TCP_CONNECT) {
2321       if(this->issetPayloadBuffer())
2322         nping_print(VB_0, "Warning: Payload supplied in TCP Connect mode. Payload will be ignored.");
2323   }
2324 
2325 /** SOURCE IP, SOURCE MAC and NETWORK DEVICE *********************************/
2326 /* If we are in a mode where we need to craft IP packets, then we need to
2327  * obtain a network interface name and a source IP address. There are three
2328  * different possibilities:
2329  *  1. User did NOT specify both network interface and source IP address.
2330  *  2. User did specify a network interface but not a source IP address.
2331  *  3. User did actually supply a source IP but not a network interface name
2332  *
2333  * I know the following code is ugly but the thing is that we want to determine
2334  * interface and source IP without user intervention, so we try in many ways
2335  * until either we succeed or we run out of possibilities and fatal().
2336  */
2337 if( this->getMode()!=TCP_CONNECT && this->getMode()!=UDP_UNPRIV && this->getRole()!=ROLE_SERVER){
2338 
2339     char devbuff[32];
2340     char *dev;
2341     struct sockaddr_storage ss, ifaddr;
2342     struct sockaddr_in *s4=(struct sockaddr_in *)&ifaddr;
2343     struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ifaddr;
2344     size_t ss_len;
2345     char hostname[128];
2346     memset(&ss, 0, sizeof(struct sockaddr_storage));
2347     memset(&ifaddr, 0, sizeof(struct sockaddr_storage));
2348 
2349 
2350    /* CASE 1: User did not specify a device so we have to select one. */
2351     if( !this->issetDevice() ){
2352         if( this->ipv4() ){
2353             /* Ugly hack. Get the first resolvable target and determine net interface. Let's
2354              * hope user did not specify something that mixes localhost with
2355              * other targets, like "nping localhost google.com playboy.com" */
2356              for(int z=0; z<this->targets.getTargetSpecCount(); z++){
2357                 if( this->targets.getNextTargetAddressAndName(&ss, &ss_len, hostname, sizeof(hostname)) == OP_SUCCESS )
2358                     break;
2359                 else if( z>=(this->targets.getTargetSpecCount()-1) )
2360                     nping_fatal(QT_3,"Cannot find a valid target. Please make sure the specified hosts are either IP addresses in standard notation or hostnames that can be resolved with DNS");
2361              }
2362              this->targets.rewind();
2363 
2364              /* Try to obtain a device name from the target IP */
2365              if ( getNetworkInterfaceName( &ss , devbuff) != OP_SUCCESS ) {
2366                 /* If that didn't work, ask libpcap */
2367                 char errbuf[PCAP_ERRBUF_SIZE];
2368                 if ( (dev = pcap_lookupdev(errbuf)) == NULL)
2369                     nping_fatal(QT_3, "Cannot obtain device for packet capture --> %s", errbuf);
2370                 else
2371                     this->setDevice( dev );
2372                 /* Libpcap gave us a device name, try to obtain it's IP */
2373                 if ( devname2ipaddr_alt(this->getDevice(), &ifaddr) != 0 ){
2374                     if( this->isRoot() )
2375                         nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, does it even exist?", this->getDevice());
2376                     else
2377                         nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, are you root?", this->getDevice());
2378                 }
2379                 else{
2380                     if( s4->sin_family==AF_INET )
2381                         this->setIPv4SourceAddress(s4->sin_addr);
2382                     else if ( s6->sin6_family==AF_INET6 )
2383                         this->setIPv6SourceAddress(s6->sin6_addr.s6_addr);
2384                 }
2385             }else{
2386                 this->setDevice(devbuff);
2387             }
2388         }else{ /* In IPv6 we just select one in libpcap and hope is the right one */
2389             char *selected_iface=this->select_network_iface();
2390             if(selected_iface==NULL)
2391                 nping_fatal(QT_3, "Error trying to find a suitable network interface ");
2392             else
2393                 this->setDevice( selected_iface );
2394         }
2395     } /* CASE 2: User did actually supply a device name */
2396     else{
2397         nping_print(DBG_2, "Using network interface \"%s\"", this->getDevice() );
2398     }
2399 
2400 /* The echo server needs to find out a network interface*/
2401 }else if (this->getRole()==ROLE_SERVER && this->issetDevice()==false){
2402   char *selected_iface=this->select_network_iface();
2403   if(selected_iface==NULL)
2404     nping_fatal(QT_3, "Error trying to find a suitable network interface ");
2405   else
2406     this->setDevice( selected_iface );
2407   nping_print(DBG_2, "Using network interface \"%s\"", this->getDevice() );
2408 }
2409 
2410 /** RAW IP AND RAW ETHERNET TRANSMISSION MODES *******************************/
2411 /* Determine if we need to send at raw ip level or at raw ethernet level */
2412 if(this->getRole()!=ROLE_SERVER){
2413  if (!this->issetSendPreference()) {
2414 
2415 
2416     /* CASE 1: ARP requested. We have to do raw ethernet transmission */
2417     if(this->getMode()==ARP ){
2418         this->setSendEth(true);
2419         this->setSendPreference( PACKET_SEND_ETH_STRONG );
2420     }
2421 
2422     /* CASE 2: If we are dealing with IPv6 we have two options: send at raw
2423      * eth level or sent at raw transport layer level. So here, we check if the
2424      * user has specified some IPv6 header specific options. If he has, we then
2425      * have to use raw ethernet (since we cannot include our own IPv6 header in
2426      * raw IPv6 sockets). If he hasn't, the best way is to send at raw TCP/UDP
2427      * level so we disable sendEth() */
2428     else if (this->ipv6() ){
2429 
2430         /* CASE 2.A: If user did not specify custom IPv6 header or Ethernet
2431          * field values go for raw transport layer level transmission */
2432         if( this->canDoIPv6ThroughSocket() ){
2433             this->setSendEth(false);
2434             this->setSendPreference( PACKET_SEND_IP_STRONG );
2435         }
2436         /* CASE 2.B: User wants to set some IPv6 or Ethernet values. So here we
2437          * check if enough parameters were supplied. */
2438         else if (this->canDoIPv6Ethernet() ){
2439             this->setSendEth(true);
2440             this->setSendPreference( PACKET_SEND_ETH_STRONG );
2441         }else{
2442             nping_fatal(QT_3, "If you want to control some of the fields"
2443                          " in the IPv6 header you also have to supply source and"
2444                          " destination MAC address. However, you can always"
2445                          " choose to let the kernel create the IPv6  header"
2446                          " choosing not to pass --source-IP, --traffic-class"
2447                          " or --flow options. That should simplify things a bit");
2448         }
2449     }
2450     /* CASE 3: We are dealing with regular, IPv4-based modes. In this case
2451      * we just select transmission mode based on current OS. For Windows
2452      * we choose raw eth level because MS has disable raw sockets support.
2453      * For the rest of systems, we chose raw IP because it's easier for us
2454      * as we don't have to deal with all the source MAC and next-hop MAC address
2455      * determination process. */
2456     else{
2457          #ifdef WIN32
2458             this->setSendPreference( PACKET_SEND_ETH_STRONG );
2459             this->setSendEth(true);
2460          #else
2461             this->setSendPreference( PACKET_SEND_IP_WEAK );
2462             this->setSendEth(false);
2463          #endif
2464     }
2465 
2466  /* User did actually supplied his own sending preference. Let's check if we
2467   * can actually send probes the way he wants. */
2468  }else{
2469 
2470     if( this->getMode()==ARP && !this->sendPreferenceEthernet() ){
2471         this->setSendEth(true);
2472         nping_warning(QT_2, "Warning: ARP mode requires raw ethernet frame transmission. Specified preference will be ignored.");
2473     }
2474     else if( this->ipv6() ){
2475 
2476         /* CASE 1: User requested ethernet explicitly and supplied all
2477          * necessary options. */
2478         if( this->sendPreferenceEthernet() && this->canDoIPv6Ethernet() ){
2479             this->setSendEth(true);
2480 
2481         /* CASE 2: User requested Ethernet but did not really supplied all
2482          * the information we need */
2483         }else if( this->sendPreferenceEthernet() && !this->canDoIPv6Ethernet() ){
2484             nping_fatal(QT_3, "You requested raw ethernet level transmission and IPv6."
2485                     " In this case, you need to supply source MAC address,"
2486                     " destination MAC address and IPv6 source address.");
2487 
2488         /* CASE 3: User requested raw IP transmission and did not request
2489          * any special IPv6 header options. */
2490         }else if( this->sendPreferenceIP() && this->canDoIPv6ThroughSocket() ){
2491             this->setSendEth(false);
2492 
2493         /* CASE 4: User requested raw IP transmission but also wanted to
2494          * set custom IPv6 header field values. */
2495         }else if (this->sendPreferenceIP() && !this->canDoIPv6ThroughSocket()){
2496             nping_fatal(QT_3, "You requested raw IP transmission mode for IPv6."
2497                          " Nping does not currently allow IPv6 header manipulation"
2498                          " when sending packets at raw IP level due to the limitations"
2499                          " on raw IPv6 sockets, imposed by RFC 2292. Please"
2500                          " use raw Ethernet transmission (option --send-eth)");
2501 
2502 
2503         }
2504     }
2505     else if( this->sendPreferenceEthernet() ){
2506             this->setSendEth(true);
2507     }else{
2508         this->setSendEth(false);
2509     }
2510  }
2511  if( this->getMode()==TCP_CONNECT || this->getMode()==UDP_UNPRIV )
2512     nping_print(DBG_2,"Nping will send packets in unprivileged mode using regular system calls");
2513  else
2514     nping_print(DBG_2,"Nping will send packets at %s",  this->sendEth() ? "raw ethernet level" : "raw IP level" );
2515 }
2516 
2517 /** ECHO MODE ************************************************************/
2518 
2519   if(this->getRole()==ROLE_CLIENT){
2520 
2521     /* Make sure the nping echo client does not generate packets with tcp
2522      * src port or tcp dst port 9929 (or --echo-port N, if that is set),
2523      * because 1) the echo server does not capture those packets and 2) to
2524      * avoid messing with the established side-channel tcp connection. */
2525     if(this->getMode()==TCP){
2526         for(int i=0; i<tportcount; i++){
2527             if( this->target_ports[i]==this->getEchoPort())
2528                 nping_fatal(QT_3, "Packets can't be sent to the same port that is used to connect to the echo server (%d)", this->getEchoPort());
2529             else if(this->getSourcePort()==this->getEchoPort())
2530                 nping_fatal(QT_3, "Packets can't be sent from the same port that is used to connect to the echo server (%d)", this->getEchoPort());
2531         }
2532     }
2533 
2534     /* Check the echo client only produces TCP/UDP/ICMP packets */
2535     switch( this->getMode() ){
2536         case TCP:
2537         case UDP:
2538         case ICMP:
2539         break;
2540 
2541         default:
2542             nping_fatal(QT_3, "The echo client can't be run with protocols other than TCP, UDP or ICMP.");
2543         break;
2544     }
2545   }
2546   #ifndef HAVE_OPENSSL
2547   if(this->getRole()==ROLE_CLIENT || this->getRole()==ROLE_SERVER ){
2548     if( this->doCrypto()==true  ){
2549         nping_fatal(QT_3, "Nping was compiled without OpenSSL so authentications need to be transmitted as cleartext. If you wish to continue, please specify --no-crypto.");
2550     }
2551   }
2552   #endif
2553 
2554 /** FRAGMENTATION ************************************************************/
2555 #if !defined(LINUX) && !defined(OPENBSD) && !defined(FREEBSD) && !defined(NETBSD)
2556   if (this->issetMTU()) {
2557     error("Warning: Packet fragmentation selected on a host other than Linux, OpenBSD, FreeBSD, or NetBSD.  This may or may not work.");
2558   }
2559 #endif
2560 
2561 /** MISCELLANEOUS ************************************************************/
2562 if( this->issetSourcePort() && this->getMode()==TCP_CONNECT && this->getPacketCount()>1 )
2563     error("Warning: Setting a source port in TCP-Connect mode with %d rounds may not work after the first round. You may want to do just one round (use --count 1).", this->getPacketCount() );
2564 } /* End of validateOptions() */
2565 
2566 
2567 /** Returns true if requested mode is a simple TCP connect probe mode */
canRunUDPWithoutPrivileges()2568 bool NpingOps::canRunUDPWithoutPrivileges(){
2569   if( this->issetBadsumIP() ||
2570     this->issetTTL() ||
2571     this->issetHopLimit() ||
2572     this->issetTOS() ||
2573     this->issetIdentification() ||
2574     this->issetMF() ||
2575     this->issetDF() ||
2576     this->issetIPv4SourceAddress() ||
2577     this->issetIPv6SourceAddress() ||
2578     this->issetIPOptions() ||
2579     this->issetMTU() ||
2580     this->issetSpoofSource() ||
2581     this->issetSourceMAC() ||
2582     this->issetDestMAC() ||
2583     this->issetEtherType() ||
2584     this->issetTraceroute() ||
2585     this->issetBPFFilterSpec()
2586   )
2587     return false;
2588   else
2589     return true;
2590 } /* End canRunUDPWithoutPrivileges() */
2591 
2592 
2593 /** Returns true if user did not request any special ethernet or ipv6 header
2594   * options */
canDoIPv6ThroughSocket()2595 bool NpingOps::canDoIPv6ThroughSocket(){
2596   if( this->issetEtherType() ||
2597     this->issetDestMAC() ||
2598     this->issetSourceMAC() ||
2599     this->issetHopLimit() ||
2600     this->issetTrafficClass() ||
2601     this->issetFlowLabel() ||
2602     this->issetIPv6SourceAddress()
2603   )
2604     return false;
2605   else
2606     return true;
2607 } /* End canDoIPv6ThroughSocket() */
2608 
2609 
2610 /** Returns true if user supplied all necessary options to allow IPv6 at raw
2611   * Ethernet level */
canDoIPv6Ethernet()2612 bool NpingOps::canDoIPv6Ethernet(){
2613   if( this->issetDestMAC() &&  this->issetSourceMAC() && this->issetIPv6SourceAddress() )
2614     return true;
2615   else
2616     return false;
2617 } /* End canDoIPv6Ethernet() */
2618 
2619 
2620 /******************************************************************************
2621  *  Miscellaneous                                                             *
2622  ******************************************************************************/
2623 
displayNpingDoneMsg()2624 void NpingOps::displayNpingDoneMsg(){
2625 
2626   if( this->getRole()==ROLE_SERVER ){
2627       nping_print(QT_1, "Nping done: %lu %s served in %.2f seconds",
2628                (unsigned long)this->stats.getEchoClientsServed(),
2629                (this->stats.getEchoClientsServed() == 1)? "client" : "clients",
2630                this->stats.elapsedRuntime()
2631               );
2632   }else{
2633       nping_print(QT_1, "Nping done: %lu %s pinged in %.2f seconds",
2634                this->targets.getTargetsFetched(),
2635                (this->targets.getTargetsFetched() == 1)? "IP address" : "IP addresses",
2636                this->stats.elapsedRuntime()
2637               );
2638   }
2639 } /* End of displayNpingDoneMessage() */
2640 
2641 
2642 /** @warning This method calls targets.rewind() */
displayStatistics()2643 void NpingOps::displayStatistics(){
2644   char auxbuff[256];
2645   memset(auxbuff, 0, 256);
2646   NpingTarget *target=NULL;
2647   this->targets.rewind();
2648 
2649   nping_print(VB_0," "); /* Print newline */
2650 
2651     /* Per-target statistics */
2652     if( this->targets.getTargetsFetched() > 1){
2653         while( (target=this->targets.getNextTarget()) != NULL )
2654             target->printStats();
2655     }else{
2656         target=this->targets.getNextTarget();
2657         if( target!= NULL)
2658             target->printRTTs();
2659     }
2660 
2661 #ifdef WIN32
2662       /* Sent/Recv/Echoed Packets */
2663       if(this->getRole()==ROLE_CLIENT){
2664           nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %I64u ", this->stats.getSentPackets() );
2665           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
2666           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
2667           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2668           nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
2669           nping_print(QT_1|NO_NEWLINE,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2670           nping_print(QT_1|NO_NEWLINE,"| Echoed: %I64u ", this->stats.getEchoedPackets() );
2671           nping_print(QT_1,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
2672       }else if(this->getRole()==ROLE_SERVER){
2673           nping_print(QT_1|NO_NEWLINE, "Raw packets captured: %I64u ", this->stats.getRecvPackets() );
2674           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2675           nping_print(QT_1|NO_NEWLINE,"| Echoed: %I64u ", this->stats.getEchoedPackets() );
2676           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
2677           nping_print(QT_1|NO_NEWLINE,"| Not Matched: %I64u ", this->stats.getUnmatchedPackets() );
2678           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes()-this->stats.getEchoedBytes(), auxbuff, 256));
2679           nping_print(QT_1,"(%.2lf%%)", this->stats.getUnmatchedPacketPercentage100() );
2680       }else if(this->getMode()==TCP_CONNECT){
2681           nping_print(QT_1|NO_NEWLINE, "TCP connection attempts: %I64u ", this->stats.getSentPackets() );
2682           nping_print(QT_1|NO_NEWLINE,"| Successful connections: %I64u ", this->stats.getRecvPackets() );
2683           nping_print(QT_1|NO_NEWLINE,"| Failed: %I64u ", this->stats.getLostPackets() );
2684           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2685       } else if (this->getMode()==UDP_UNPRIV){
2686           nping_print(QT_1|NO_NEWLINE, "UDP packets sent: %I64u ", this->stats.getSentPackets() );
2687           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
2688           nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
2689           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2690       } else{
2691           nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %I64u ", this->stats.getSentPackets() );
2692           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
2693           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
2694           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2695           nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
2696           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2697      }
2698 #else
2699       /* Sent/Recv/Echoed Packets */
2700       if(this->getRole()==ROLE_CLIENT){
2701           nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %llu ", this->stats.getSentPackets() );
2702           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
2703           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
2704           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2705           nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
2706           nping_print(QT_1|NO_NEWLINE,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2707           nping_print(QT_1|NO_NEWLINE,"| Echoed: %llu ", this->stats.getEchoedPackets() );
2708           nping_print(QT_1,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
2709       }else if(this->getRole()==ROLE_SERVER){
2710           nping_print(QT_1|NO_NEWLINE, "Raw packets captured: %llu ", this->stats.getRecvPackets() );
2711           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2712           nping_print(QT_1|NO_NEWLINE,"| Echoed: %llu ", this->stats.getEchoedPackets() );
2713           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
2714           nping_print(QT_1|NO_NEWLINE,"| Not Matched: %llu ", this->stats.getUnmatchedPackets() );
2715           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes()-this->stats.getEchoedBytes(), auxbuff, 256));
2716           nping_print(QT_1,"(%.2lf%%)", this->stats.getUnmatchedPacketPercentage100() );
2717       }else if(this->getMode()==TCP_CONNECT){
2718           nping_print(QT_1|NO_NEWLINE, "TCP connection attempts: %llu ", this->stats.getSentPackets() );
2719           nping_print(QT_1|NO_NEWLINE,"| Successful connections: %llu ", this->stats.getRecvPackets() );
2720           nping_print(QT_1|NO_NEWLINE,"| Failed: %llu ", this->stats.getLostPackets() );
2721           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2722       } else if (this->getMode()==UDP_UNPRIV){
2723           nping_print(QT_1|NO_NEWLINE, "UDP packets sent: %llu ", this->stats.getSentPackets() );
2724           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
2725           nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
2726           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2727       } else{
2728           nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %llu ", this->stats.getSentPackets() );
2729           nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
2730           nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
2731           nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
2732           nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
2733           nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
2734      }
2735 #endif
2736 
2737       /* Transmission times & rates */
2738       nping_print(VB_1|NO_NEWLINE,"Tx time: %.5lfs ", this->stats.elapsedTx() );
2739       nping_print(VB_1|NO_NEWLINE,"| Tx bytes/s: %.2lf ", this->stats.getOverallTxByteRate() );
2740       nping_print(VB_1,"| Tx pkts/s: %.2lf", this->stats.getOverallTxPacketRate() );
2741       nping_print(VB_1|NO_NEWLINE,"Rx time: %.5lfs ", this->stats.elapsedRx() );
2742       nping_print(VB_1|NO_NEWLINE,"| Rx bytes/s: %.2lf ", this->stats.getOverallRxByteRate() );
2743       nping_print(VB_1,"| Rx pkts/s: %.2lf", this->stats.getOverallRxPacketRate() );
2744 
2745 } /* End of displayStatistics() */
2746 
2747 
2748 /* Close open files, free allocated memory, etc. */
cleanup()2749 int NpingOps::cleanup(){
2750   this->targets.freeTargets();
2751   return OP_SUCCESS;
2752 } /* End of cleanup() */
2753 
2754 
select_network_iface()2755 char *NpingOps::select_network_iface(){
2756     char errbuf[PCAP_ERRBUF_SIZE];
2757     pcap_if_t *pcap_ifaces=NULL;
2758 
2759     /* Vars for the current interface in the loop */
2760     pcap_if_t *curr=NULL;             /* Current pcap pcap_if_t element   */
2761     bool current_has_address=false;   /* Does it have an addr of any type? */
2762     bool current_has_ipv6=false;      /* Does it have an IPv6 address?     */
2763     bool current_has_ipv4=false;      /* Does it have an IPv4 address?     */
2764     bool current_is_loopback=false;   /* Is it a loopback interface?       */
2765     bool select_current=false;        /* Is current better than candidate? */
2766     struct sockaddr_in6 devaddr6;     /* We store iface's IPv6 address     */
2767     struct sockaddr_in devaddr4;      /* And also its IPv4 address         */
2768 
2769     /* Vars for our candidate interface */
2770     pcap_if_t *candidate=NULL;
2771     bool candidate_has_address=false;
2772     bool candidate_has_ipv6=false;
2773     bool candidate_has_ipv4=false;
2774     bool candidate_is_loopback=false;
2775     //struct sockaddr_in6 candidate_addr6;
2776     //struct sockaddr_in candidate_addr4;
2777 
2778     /* Ask libpcap for a list of network interfaces */
2779     if( pcap_findalldevs(&pcap_ifaces, errbuf) != 0 )
2780         nping_fatal(QT_3, "Cannot obtain device for packet capture --> %s. You may want to specify one explicitly using option -e", errbuf);
2781 
2782     /* Iterate over the interface list and select the best one */
2783     for(curr=pcap_ifaces; curr!=NULL; curr=curr->next){
2784         current_has_address=false;   candidate_has_ipv6=false;
2785         candidate_is_loopback=false; candidate_has_ipv4=false;
2786         select_current=false;
2787 
2788         if( curr->flags==PCAP_IF_LOOPBACK)
2789             current_is_loopback=true;
2790 
2791         /* Loop through the list of addresses */
2792         for(pcap_addr_t *curraddr=curr->addresses; curraddr!=NULL; curraddr=curraddr->next){
2793             current_has_address=true;
2794             if( curraddr->addr->sa_family==AF_INET){
2795                 current_has_ipv4=true;
2796                 memcpy( &devaddr4, curraddr->addr, sizeof(struct sockaddr_in));
2797             } else if( curraddr->addr->sa_family==AF_INET6){
2798                 current_has_ipv6=true;
2799                 memcpy( &devaddr6, curraddr->addr, sizeof(struct sockaddr_in6));
2800             }
2801          }
2802 
2803         /* If we still have no candidate, take the first one we find */
2804         if( candidate==NULL){
2805             select_current=true;
2806         }
2807         /* If we already have a candidate, check if the one we are
2808          * processing right now is better than the one we've already got */
2809         else{
2810             /* If our candidate does not have an IPv6 address but this one does,
2811              * select the new one. */
2812             if( candidate_has_ipv6==false && current_has_ipv6==true ){
2813                 select_current=true;
2814             }
2815             /* If our candidate does not even have an IPv4 address but this
2816              * one does, select the new one. */
2817             else if( candidate_has_ipv4==false && candidate_has_ipv6==false && current_has_ipv4){
2818                 select_current=true;
2819             }
2820             /* If our candidate is a loopback iface, select the new one */
2821             else if( candidate_is_loopback && !current_is_loopback){
2822 
2823                 /* Select the new one only if it has an IPv6 address
2824                  * and the old one didn't. If our old loopback iface
2825                  * has an IPv6 address and this one does not, we
2826                  * prefer to keep the loopback one, even though the
2827                  * other is not loopback */
2828                 if(current_has_ipv6==true){
2829                     select_current=true;
2830                 }
2831                 /* We also prefer IPv4 capable interfaces than  */
2832                 else if(candidate_has_ipv6==false && current_has_ipv4==true){
2833                     select_current=true;
2834                 }
2835             }
2836             /* If both are loopback, select the best one. */
2837             else if( candidate->flags==PCAP_IF_LOOPBACK && curr->flags==PCAP_IF_LOOPBACK){
2838                 if( candidate_has_ipv6==false && current_has_ipv6 )
2839                     select_current=true;
2840             }
2841         }
2842 
2843         /* Did we determine that we should discard our old candidate? */
2844         if( select_current ){
2845             candidate=curr;
2846             candidate_has_address=current_has_address;
2847             candidate_has_ipv4=current_has_ipv4;
2848             candidate_has_ipv6=current_has_ipv6;
2849             candidate_is_loopback=current_is_loopback;
2850         }
2851 
2852         /* Let's see if we have the interface of our dreams... */
2853         if( candidate_has_address && candidate_has_ipv6 && candidate_has_ipv4 && candidate_is_loopback==false){
2854             break;
2855         }
2856 
2857     }
2858     if(candidate==NULL)
2859         return NULL;
2860     else
2861        return candidate->name;
2862 } /* End of select_network_iface() */
2863 
2864 
setDefaultHeaderValues()2865 int NpingOps::setDefaultHeaderValues(){
2866   if(this->ipv6()){ /* IPv6 */
2867     if(!this->issetTrafficClass())
2868         this->ipv6_tclass=DEFAULT_IPv6_TRAFFIC_CLASS;
2869     if(!this->issetFlowLabel())
2870         this->ipv6_flowlabel=(get_random_u32() % 1048575);
2871     if(!this->issetHopLimit() && !this->issetTraceroute())
2872         this->ttl=DEFAULT_IPv6_TTL;
2873   }else{ /* IPv4 */
2874     if(!this->issetTOS())
2875         this->tos=DEFAULT_IP_TOS;
2876     if(!this->issetIdentification())
2877         this->identification=get_random_u16();
2878     if(!this->issetTTL() && !this->issetTraceroute())
2879         this->ttl=DEFAULT_IP_TTL;
2880 
2881   }
2882   switch( this->getMode() ){
2883     case TCP:
2884         if(!this->issetTargetPorts()){
2885             u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
2886             list[0]=DEFAULT_TCP_TARGET_PORT;
2887             this->setTargetPorts(list, 1);
2888         }
2889         if(!this->issetSourcePort()){
2890             /* Generate any source port higher than 1024 */
2891             if(this->getRole()!=ROLE_CLIENT){
2892                 this->source_port=(1024 + ( get_random_u16()%(65535-1024) ));
2893             }else{
2894                 /* For the echo client, avoid choosing the port used for the echo side channel */
2895                 while( (this->source_port=(1024 + ( get_random_u16()%(65535-1024) )))==this->echo_port );
2896             }
2897         }
2898         if(!this->issetTCPSequence())
2899             this->tcpseq=get_random_u32();
2900         if(!this->issetTCPAck()){
2901             if(this->getFlagTCP(FLAG_ACK))
2902                 this->tcpack=get_random_u32();
2903             else
2904                 this->tcpack=0;
2905         }
2906         if(!this->issetTCPFlags())
2907             this->setFlagTCP(FLAG_SYN);
2908         if(!this->issetTCPWindow())
2909             this->tcpwin=DEFAULT_TCP_WINDOW_SIZE;
2910         /* @todo ADD urgent pointer handling here when it gets implemented */
2911     break;
2912 
2913     case UDP:
2914         if(!this->issetTargetPorts()){
2915             u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
2916             list[0]=DEFAULT_UDP_TARGET_PORT;
2917             this->setTargetPorts(list, 1);
2918         }
2919         if(!this->issetSourcePort())
2920             this->source_port=DEFAULT_UDP_SOURCE_PORT;
2921     break;
2922 
2923     case ICMP:
2924         if(this->ipv6()){
2925             if(!this->issetICMPType()) /* Default to ICMP Echo */
2926                 this->icmp_type=DEFAULT_ICMPv6_TYPE;
2927             if(!this->issetICMPCode())
2928                 this->icmp_code=DEFAULT_ICMPv6_CODE;
2929         }else{
2930             if(!this->issetICMPType()) /* Default to ICMP Echo */
2931                 this->icmp_type=DEFAULT_ICMP_TYPE;
2932             if(!this->issetICMPCode())
2933                 this->icmp_code=DEFAULT_ICMP_CODE;
2934         }
2935     break;
2936 
2937     case ARP:
2938         if(!this->issetARPOpCode())
2939             this->arp_opcode=DEFAULT_ARP_OP;
2940     break;
2941 
2942     case UDP_UNPRIV:
2943         if(!this->issetTargetPorts()){
2944             u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
2945             list[0]=DEFAULT_UDP_TARGET_PORT;
2946             this->setTargetPorts(list, 1);
2947         }
2948         if(!this->issetSourcePort())
2949             this->source_port=DEFAULT_UDP_SOURCE_PORT;
2950     break;
2951 
2952     case TCP_CONNECT:
2953         if( !this->issetTargetPorts() ) {
2954             u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
2955             list[0]=DEFAULT_TCP_TARGET_PORT;
2956             this->setTargetPorts(list, 1);
2957         }
2958 
2959     default:
2960         return OP_FAILURE;
2961     break;
2962   }
2963 
2964   return OP_SUCCESS;
2965 } /* End of setDefaultHeaderValues() */
2966 
2967 
setLastPacketSentTime(struct timeval t)2968 int NpingOps::setLastPacketSentTime(struct timeval t){
2969   this->last_sent_pkt_time=t;
2970   return OP_SUCCESS;
2971 } /* End of setLastPacketSentTime() */
2972 
2973 
getLastPacketSentTime()2974 struct timeval NpingOps::getLastPacketSentTime(){
2975   return this->last_sent_pkt_time;
2976 } /* End of getLastPacketSentTime() */
2977 
2978 
2979 /** Sets the RCVD output to be delayed. The supplied string is strdup()ed, so
2980   * the caller may safely free() it or modify after calling this function.
2981   * The "id" parameter is the nsock timer event scheduled for the output of
2982   * the RCVD string (usually scheduled by ProbeMode). It is provided to allow
2983   * other objects (like EchoClient) to cancel the event if they take care of
2984   * printing the RCVD string before the timer goes off.*/
setDelayedRcvd(const char * str,nsock_event_id id)2985 int NpingOps::setDelayedRcvd(const char *str, nsock_event_id id){
2986   if(str==NULL)
2987     return OP_FAILURE;
2988   this->delayed_rcvd_str=strdup(str);
2989   this->delayed_rcvd_event=id;
2990   this->delayed_rcvd_str_set=true;
2991   return OP_SUCCESS;
2992 } /* End of setDelayedRcvd() */
2993 
2994 
2995 /** Returns a pointer to a delayed RCVD output string. It returns non-NULL
2996   * strings only once per prior setDelayedRcvd() call. This is, when a string
2997   * has been set through a setDelayRcdv() call, the first time getDelayRcvd()
2998   * is called, it returns that string. Subsequent calls will return NULL until
2999   * another string is set, using setDelayRcdv() again.
3000   * The "id" parameter will be filled with the timer event that was supposed
3001   * to print the message. If getDelayedRcvd() is called by the timer handler
3002   * itself, then NULL can be passed safely since the event id is not needed.
3003   * If the caller is some other method that wants to print the RCVD string
3004   * before the timer goes off, it may use the event ID to cancel the scheduled
3005   * event since it's no longer necessary.
3006   * @warning returned string is the strdup()ed version of the string passed
3007   * in the call to setDelayedRcvd(), so the caller MUST free the returned
3008   * pointer when it's done using it.  */
getDelayedRcvd(nsock_event_id * id)3009 char *NpingOps::getDelayedRcvd(nsock_event_id *id){
3010   if(delayed_rcvd_str_set==false){
3011     return NULL;
3012   }else{
3013     this->delayed_rcvd_str_set=false;
3014     char *old=this->delayed_rcvd_str;
3015     this->delayed_rcvd_str=NULL;
3016     if(id!=NULL)
3017         *id=this->delayed_rcvd_event;
3018     return old;
3019   }
3020 } /* End of getDelayedRcvd() */
3021 
3022 
doCrypto()3023 bool NpingOps::doCrypto(){
3024   return this->do_crypto;
3025 }
3026 
doCrypto(bool value)3027 int NpingOps::doCrypto(bool value){
3028   this->do_crypto=value;
3029   return OP_SUCCESS;
3030 }
3031 
3032 /* Returns true if the echo server is allowed to include payloads in NEP_ECHO
3033  * messages. */
echoPayload()3034 bool NpingOps::echoPayload(){
3035   return this->echo_payload;
3036 }
3037 
3038 /* Enables or disables payload echo for the echo server. Pass true to enable
3039  * or false to disable. */
echoPayload(bool value)3040 int NpingOps::echoPayload(bool value){
3041   this->echo_payload=value;
3042   this->echo_payload_set=true;
3043   return OP_SUCCESS;
3044 }
3045 
3046 
3047 /** Returns the total number of probes to be sent (this takes into account
3048   * the number of rounds, ports, and targets. It returns a positive integer
3049   * on success and n<=0 in case of error. */
getTotalProbes()3050 int NpingOps::getTotalProbes(){
3051   int total_ports=0;
3052   this->getTargetPorts(&total_ports);
3053   u64 tmp = (u64) this->getPacketCount() * total_ports;
3054   if (tmp > INT_MAX) {
3055     return -1;
3056   }
3057   tmp *= this->targets.Targets.size();
3058   if (tmp > INT_MAX) {
3059     return -1;
3060   }
3061   return (int) tmp;
3062 }
3063 
3064 
3065 /******************************************************************************
3066  *  Code templates.                                                           *
3067  ******************************************************************************/
3068 
3069 /*
3070 
3071 Attributes for NpingOps:
3072 
3073         TYPE ATTRNAME;
3074         bool ATTRNAME_set;
3075 
3076 Prototypes for NpingOps:
3077 
3078     int setMETHNAME(TYPE val);
3079     TYPE getMETHNAME();
3080     bool issetMETHNAME();
3081 
3082 Initialization for NpingOps::NpingOps()
3083 
3084     ATTRNAME=0;
3085     ATTRNAME_set=false;
3086 */
3087 
3088 /** Sets METHNAME. Supplied parameter must be XXXXXXXX
3089  *  @return OP_SUCCESS on success and OP_FAILURE in case of error.           */
3090 /*int NpingOps::setMETHNAME(TYPE val){
3091    if( 0 ){
3092         nping_fatal(QT_3,"setMETHNAME(): Invalid value supplied\n");
3093         return OP_FAILURE;
3094     }else{
3095         ATTRNAME=val;
3096         ATTRNAME_set=true;
3097     }
3098     return OP_SUCCESS;
3099 } *//* End of setMETHNAME() */
3100 
3101 
3102 
3103 /** Returns value of attribute ATTRNAME */
3104 /*TYPE NpingOps::getMETHNAME(){
3105   return this->ATTRNAME;
3106 } *//* End of getMETHNAME() */
3107 
3108 
3109 /* Returns true if option has been set */
3110 /*bool NpingOps::issetMETHNAME(){
3111   return this->ATTRNAME_set;
3112 } *//* End of issetMETHNAME() */
3113