summaryrefslogtreecommitdiffstats
path: root/nping/NpingOps.cc
diff options
context:
space:
mode:
Diffstat (limited to 'nping/NpingOps.cc')
-rw-r--r--nping/NpingOps.cc3134
1 files changed, 3134 insertions, 0 deletions
diff --git a/nping/NpingOps.cc b/nping/NpingOps.cc
new file mode 100644
index 0000000..71cb4a5
--- /dev/null
+++ b/nping/NpingOps.cc
@@ -0,0 +1,3134 @@
+
+/***************************************************************************
+ * NpingOps.cc -- The NpingOps class contains global options, mostly based *
+ * on user-provided command-line settings. *
+ * *
+ ***********************IMPORTANT NMAP LICENSE TERMS************************
+ *
+ * The Nmap Security Scanner is (C) 1996-2023 Nmap Software LLC ("The Nmap
+ * Project"). Nmap is also a registered trademark of the Nmap Project.
+ *
+ * This program is distributed under the terms of the Nmap Public Source
+ * License (NPSL). The exact license text applying to a particular Nmap
+ * release or source code control revision is contained in the LICENSE
+ * file distributed with that version of Nmap or source code control
+ * revision. More Nmap copyright/legal information is available from
+ * https://nmap.org/book/man-legal.html, and further information on the
+ * NPSL license itself can be found at https://nmap.org/npsl/ . This
+ * header summarizes some key points from the Nmap license, but is no
+ * substitute for the actual license text.
+ *
+ * Nmap is generally free for end users to download and use themselves,
+ * including commercial use. It is available from https://nmap.org.
+ *
+ * The Nmap license generally prohibits companies from using and
+ * redistributing Nmap in commercial products, but we sell a special Nmap
+ * OEM Edition with a more permissive license and special features for
+ * this purpose. See https://nmap.org/oem/
+ *
+ * If you have received a written Nmap license agreement or contract
+ * stating terms other than these (such as an Nmap OEM license), you may
+ * choose to use and redistribute Nmap under those terms instead.
+ *
+ * The official Nmap Windows builds include the Npcap software
+ * (https://npcap.com) for packet capture and transmission. It is under
+ * separate license terms which forbid redistribution without special
+ * permission. So the official Nmap Windows builds may not be redistributed
+ * without special permission (such as an Nmap OEM license).
+ *
+ * Source is provided to this software because we believe users have a
+ * right to know exactly what a program is going to do before they run it.
+ * This also allows you to audit the software for security holes.
+ *
+ * Source code also allows you to port Nmap to new platforms, fix bugs, and add
+ * new features. You are highly encouraged to submit your changes as a Github PR
+ * or by email to the dev@nmap.org mailing list for possible incorporation into
+ * the main distribution. Unless you specify otherwise, it is understood that
+ * you are offering us very broad rights to use your submissions as described in
+ * the Nmap Public Source License Contributor Agreement. This is important
+ * because we fund the project by selling licenses with various terms, and also
+ * because the inability to relicense code has caused devastating problems for
+ * other Free Software projects (such as KDE and NASM).
+ *
+ * The free version of Nmap is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,
+ * indemnification and commercial support are all available through the
+ * Npcap OEM program--see https://nmap.org/oem/
+ *
+ ***************************************************************************/
+
+#ifdef WIN32
+#include "winfix.h"
+#endif
+
+#include "nping.h"
+#include "nbase.h"
+#include "NpingOps.h"
+#include "utils.h"
+#include "utils_net.h"
+#include "ArgParser.h"
+#include "output.h"
+#include "common.h"
+
+
+/******************************************************************************
+ * Constructors and destructors *
+ ******************************************************************************/
+
+/* Constructor */
+NpingOps::NpingOps() {
+
+ /* Probe modes */
+ mode=0;
+ mode_set=false;
+
+ traceroute=false;
+ traceroute_set=false;
+
+ /* Output */
+ vb=DEFAULT_VERBOSITY;
+ vb_set=false;
+
+ dbg=DEFAULT_DEBUGGING;
+ dbg_set=false;
+
+ show_sent_pkts=true;
+ show_sent_pkts_set=false;
+
+ /* Operation and Performance */
+ pcount=0;
+ pcount_set=false;
+
+ sendpref=0;
+ sendpref_set=false;
+
+ send_eth=false;
+ send_eth_set=false;
+
+ delay=0;
+ delay_set=false;
+
+ memset(device, 0, MAX_DEV_LEN);
+ device_set=false;
+
+ spoofsource=false;
+ spoofsource_set=false;
+
+ bpf_filter_spec=NULL;
+ bpf_filter_spec_set=false;
+
+ current_round=0;
+
+ have_pcap=true;
+
+ disable_packet_capture=false;
+ disable_packet_capture_set=false;
+
+ /* Privileges */
+/* If user did not specify --privileged or --unprivileged explicitly, try to
+ * determine if has root privileges. */
+#if defined WIN32 || defined __amigaos__
+ /* TODO: Check this because although nmap does exactly the same, it has a this->have_pcap that may affect to this */
+ isr00t=true;
+#else
+ if (getenv("NMAP_PRIVILEGED") || getenv("NPING_PRIVILEGED"))
+ isr00t=true;
+ else if (getenv("NMAP_UNPRIVILEGED") || getenv("NPING_UNPRIVILEGED"))
+ isr00t=false;
+ else
+ isr00t = !(geteuid());
+#endif
+
+ /* Payloads */
+ payload_type=PL_NONE;
+ payload_type_set=false;
+
+ payload_buff=NULL;
+ payload_buff_set=false;
+
+ payload_len=0;
+ payload_len_set=false;
+
+ /* Roles */
+ role=0;
+ role_set=false;
+
+ /* IP */
+ ttl=0;
+ ttl_set=false;
+
+ tos=0;
+ tos_set=false;
+
+ identification=0;
+ identification_set=false;
+
+ mf=false;
+ mf_set=false;
+
+ df=false;
+ df_set=false;
+
+ mtu=0;
+ mtu_set=false;
+
+ badsum_ip=false;
+ badsum_ip_set=false;
+
+ ipversion=0;
+ ipversion_set=false;
+
+ memset(&ipv4_src_address, 0, sizeof(struct in_addr));
+ ipv4_src_address_set=false;
+
+ ip_options=NULL;
+ ip_options_set=false;
+
+ /* IPv6 */
+ ipv6_tclass=0;
+ ipv6_tclass_set=false;
+
+ ipv6_flowlabel=0;
+ ipv6_flowlabel_set=false;
+
+ memset(&ipv6_src_address, 0, sizeof(struct in6_addr));
+ ipv6_src_address_set=false;
+
+ /* TCP / UDP */
+ target_ports=NULL;
+ tportcount=0;
+ target_ports_set=false;
+
+ source_port=0;
+ source_port_set=false;
+
+ tcpseq=0;
+ tcpseq_set=false;
+
+ memset(tcpflags, 0, 8);
+ tcpflags_set=false;
+
+ tcpack=0;
+ tcpack_set=false;
+
+ tcpwin=0;
+ tcpwin_set=false;
+
+ badsum=false;
+ badsum_set=false;
+
+ /* ICMP */
+ icmp_type=0;
+ icmp_type_set=false;
+
+ icmp_code=0;
+ icmp_code_set=false;
+
+ badsum_icmp=false;
+ badsum_icmp_set=false;
+
+ icmp_redir_addr.s_addr=0;
+ icmp_redir_addr_set=false;
+
+ icmp_paramprob_pnt=0;
+ icmp_paramprob_pnt_set=false;
+
+ icmp_routeadv_ltime=0;
+ icmp_routeadv_ltime_set=false;
+
+ icmp_id=0;
+ icmp_id_set=false;
+
+ icmp_seq=0;
+ icmp_seq_set=false;
+
+ icmp_orig_time=0;
+ icmp_orig_time_set=false;
+
+ icmp_recv_time=0;
+ icmp_recv_time_set=false;
+
+ icmp_trans_time=0;
+ icmp_trans_time_set=false;
+
+ memset( icmp_advert_entry_addr, 0, sizeof(u32)*MAX_ICMP_ADVERT_ENTRIES );
+ memset( icmp_advert_entry_pref, 0, sizeof(u32)*MAX_ICMP_ADVERT_ENTRIES );
+ icmp_advert_entry_count=0;
+ icmp_advert_entry_set=false;
+
+ /* Ethernet */
+ memset(src_mac, 0, 6);
+ src_mac_set=false;
+
+ memset(dst_mac, 0, 6);
+ dst_mac_set=false;
+
+ eth_type=0;
+ eth_type_set=false;
+
+ arp_htype=0;
+ arp_htype_set=false;
+
+ /* ARP/RARP */
+ arp_ptype=0;
+ arp_ptype_set=false;
+
+ arp_hlen=0;
+ arp_hlen_set=false;
+
+ arp_plen=0;
+ arp_plen_set=false;
+
+ arp_opcode=0;
+ arp_opcode_set=false;
+
+ memset(arp_sha, 0, 6);
+ arp_sha_set=false;
+
+ memset(arp_tha, 0, 6);
+ arp_tha_set=false;
+
+ arp_spa.s_addr=0;
+ arp_spa_set=false;
+
+ arp_tpa.s_addr=0;
+ arp_tpa_set=false;
+
+ /* Echo mode */
+ echo_port=DEFAULT_ECHO_PORT;
+ echo_port_set=false;
+
+ do_crypto=true;
+
+ echo_payload=false;
+
+ echo_server_once=false;
+ echo_server_once_set=false;
+
+ memset(echo_passphrase, 0, sizeof(echo_passphrase));
+ echo_passphrase_set=false;
+
+ memset(&last_sent_pkt_time, 0, sizeof(struct timeval));
+
+ delayed_rcvd_str=NULL;
+ delayed_rcvd_str_set=false;
+
+} /* End of NpingOps() */
+
+
+/* Destructor */
+NpingOps::~NpingOps() {
+ if (payload_buff!=NULL)
+ free(payload_buff);
+ if ( ip_options!=NULL )
+ free(ip_options);
+ if ( target_ports!=NULL )
+ free(target_ports);
+ if (delayed_rcvd_str_set)
+ free(delayed_rcvd_str);
+ return;
+} /* End of ~NpingOps() */
+
+
+/******************************************************************************
+ * Nping probe modes *
+ ******************************************************************************/
+
+/** Sets attribute "mode". Mode must be one of: TCP_CONNECT TCP, UDP, ICMP,
+ * ARP
+ * @return OP_SUCCESS on success.
+ * @return OP_FAILURE in case of error. */
+int NpingOps::setMode(int md) {
+ if ( md!=TCP_CONNECT && md!=TCP && md!=UDP && md!=UDP_UNPRIV && md!=ICMP && md!=ARP )
+ return OP_FAILURE;
+ else{
+ this->mode=md;
+ this->mode_set=true;
+ }
+ return OP_SUCCESS;
+} /* End of setMode() */
+
+
+/** Returns value of attribute "mode". The value returned is supposed to be
+ * one of : TCP_CONNECT, TCP, UDP, UDP_UNPRIV, ICMP, ARP */
+int NpingOps::getMode() {
+ return mode;
+} /* End of getMode() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetMode(){
+ return this->mode_set;
+} /* End of isset() */
+
+
+/** Takes a probe mode and returns an ASCII string with the name of the mode.
+ * @warning Returned pointer is a static buffer that subsequent calls
+ * will overwrite.
+ * @return Pointer to the appropriate string on success and pointer to a
+ * string containing "Unknown probe" in case of failure.
+ * */
+char * NpingOps::mode2Ascii(int md) {
+ static char buff[24];
+
+ switch( md ){
+ case TCP_CONNECT:
+ sprintf(buff, "TCP-Connect");
+ break;
+
+ case TCP:
+ sprintf(buff, "TCP");
+ break;
+
+ case UDP:
+ sprintf(buff, "UDP");
+ break;
+
+ case UDP_UNPRIV:
+ sprintf(buff, "UDP-Unprivileged");
+ break;
+
+ case ICMP:
+ sprintf(buff, "ICMP");
+ break;
+
+ case ARP:
+ sprintf(buff, "ARP");
+ break;
+
+ default:
+ sprintf(buff, "Unknown mode");
+ break;
+ }
+ return buff;
+} /* End of mode2Ascii() */
+
+
+/** Returns value of attribute "traceroute" */
+bool NpingOps::getTraceroute() {
+ return traceroute;
+} /* End of getTraceroute() */
+
+
+/** Sets attribute traceroute to "true".
+ * @return previous value of the attribute. */
+bool NpingOps::enableTraceroute() {
+ bool prev = traceroute;
+ this->traceroute=true;
+ this->traceroute_set=true;
+ return prev;
+} /* End of enableTraceroute() */
+
+
+/** Sets attribute traceroute to "false".
+ * @return previous value of the attribute. */
+bool NpingOps::disableTraceroute() {
+ bool prev = traceroute;
+ this->traceroute=false;
+ this->traceroute_set=true;
+ return prev;
+} /* End of disableTraceroute() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTraceroute(){
+ return this->traceroute_set;
+} /* End of issetTraceroute() */
+
+
+/******************************************************************************
+ * Output *
+ ******************************************************************************/
+
+/** Sets verbosity level. Supplied level must be an integer between -4 and
+ * 4. Check man pages for details.
+ *
+ * The thing here is that what the argument parser gets from the user is
+ * number in the range [-4, 4]. However, in NpingOps we don't store negative
+ * verbosity values, we just convert the supplied level into our internal
+ * levels (QT_4, QT_3, ... , VB_0, VB_1, ..., VB_4)
+ * So the rest of the code in Nping should check for these defines, rather
+ * than checking for numbers. Check nping.h for more information on how to
+ * handle verbosity levels.
+ *
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setVerbosity(int level){
+ if( level < -4 || level > 4 ){
+ nping_fatal(QT_3,"setVerbosity(): Invalid verbosity level supplied\n");
+ return OP_FAILURE;
+ }else{
+ switch(level){
+ case -4: vb=QT_4; break;
+ case -3: vb=QT_3; break;
+ case -2: vb=QT_2; break;
+ case -1: vb=QT_1; break;
+ case 0: vb=VB_0; break;
+ case 1: vb=VB_1; break;
+ case 2: vb=VB_2; break;
+ case 3: vb=VB_3; break;
+ case 4: vb=VB_4; break;
+ default:
+ nping_fatal(QT_3,"setVerbosity():2: Invalid verbosity level supplied\n");
+ break;
+ }
+ }
+ this->vb_set=true;
+ return OP_SUCCESS;
+} /* End of setVerbosity() */
+
+
+/** Returns value of attribute vb (current verbosity level) */
+int NpingOps::getVerbosity(){
+ return vb;
+} /* End of getVerbosity() */
+
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetVerbosity(){
+ return this->vb_set;
+} /* End of issetVerbosity() */
+
+
+/** Increments verbosity level by one. (When it reaches VB_4 it stops
+ * getting incremented)
+ * @return previous verbosity level */
+int NpingOps::increaseVerbosity(){
+ this->vb_set=true;
+ if (vb < VB_4){
+ vb++;
+ return vb-1;
+ }else{
+ return vb;
+ }
+} /* End of increaseVerbosity() */
+
+
+/** Decreases verbosity level by one. (When it reaches QT_4 it stops
+ * getting incremented)
+ * @return previous verbosity level */
+int NpingOps::decreaseVerbosity(){
+ this->vb_set=true;
+ if (vb > QT_4){
+ vb--;
+ return vb+1;
+ }else{
+ return vb;
+ }
+} /* End of decreaseVerbosity() */
+
+
+/** Sets debugging level. Supplied level must be an integer between DBG_0 and
+ * DBG_9. Check file nping.h for details
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setDebugging(int level){
+ if( level < 0 || level > 9){
+ nping_fatal(QT_3,"setDebugging(): Invalid debugging level supplied\n");
+ return OP_FAILURE;
+ }else{
+ this->dbg= DBG_0 + level;
+ }
+ this->dbg_set=true;
+ return OP_SUCCESS;
+} /* End of setDebugging() */
+
+
+/** Returns value of attribute dbg (current debugging level) */
+int NpingOps::getDebugging(){
+ return dbg;
+} /* End of getDebugging() */
+
+
+/** Increments debugging level by one. (When it reaches DBG_9 it stops
+ * getting incremented)
+ * * @return previous verbosity level */
+int NpingOps::increaseDebugging(){
+ this->dbg_set=true;
+ if (dbg < DBG_9){
+ dbg++;
+ return dbg-1;
+ }else{
+ return dbg;
+ }
+} /* End of increaseDebugging() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDebugging(){
+ return this->dbg_set;
+} /* End of issetDebugging() */
+
+
+/** Sets ShowSentPackets.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setShowSentPackets(bool val){
+ this->show_sent_pkts=val;
+ this->show_sent_pkts_set=true;
+ return OP_SUCCESS;
+} /* End of setShowSentPackets() */
+
+
+/** Returns value of attribute show_sent_pkts */
+bool NpingOps::showSentPackets(){
+ return this->show_sent_pkts;
+} /* End of showSentPackets() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetShowSentPackets(){
+ return this->show_sent_pkts_set;
+} /* End of issetShowSentPackets() */
+
+
+
+/******************************************************************************
+ * Operation and Performance *
+ ******************************************************************************/
+
+/** Sets packet count (number of packets that should be sent to each target)
+ * Supplied parameter must be a non-negative integer.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setPacketCount(u32 val){
+ /* If zero is supplied, use the highest possible value */
+ if( val==0 )
+ this->pcount=0xFFFFFFFF;
+ else
+ pcount=val;
+ this->pcount_set=true;
+ return OP_SUCCESS;
+} /* End of setPacketCount() */
+
+
+/** Returns value of attribute pcount (number of packets that should be sent
+ * to each target) */
+u32 NpingOps::getPacketCount(){
+ return this->pcount;
+} /* End of getPacketCount() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetPacketCount(){
+ return this->pcount_set;
+} /* End of issetPacketCount() */
+
+
+/** Sets attribute sendpref which defines user's preference for packet
+ * sending. Supplied parameter must be an integer with one of these values:
+ * PACKET_SEND_NOPREF, PACKET_SEND_ETH_WEAK, PACKET_SEND_ETH_STRONG,
+ * PACKET_SEND_ETH, PACKET_SEND_IP_WEAK, PACKET_SEND_IP_STRONG, PACKET_SEND_IP
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setSendPreference(int v){
+ if( v!=PACKET_SEND_NOPREF && v!=PACKET_SEND_ETH_WEAK &&
+ v!=PACKET_SEND_ETH_STRONG && v!=PACKET_SEND_ETH &&
+ v!=PACKET_SEND_IP_WEAK && v!=PACKET_SEND_IP_STRONG &&
+ v!=PACKET_SEND_IP ){
+ nping_fatal(QT_3,"setSendPreference(): Invalid value supplied\n");
+ return OP_FAILURE;
+ }else{
+ sendpref=v;
+ }
+ this->sendpref_set=true;
+ return OP_SUCCESS;
+} /* End of setSendPreference() */
+
+
+/** Returns value of attribute sendpref */
+int NpingOps::getSendPreference(){
+ return this->sendpref;
+} /* End of getSendPreference() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetSendPreference(){
+ return this->sendpref_set;
+} /* End of issetSendPreference() */
+
+
+/* Returns true if send preference is Ethernet */
+bool NpingOps::sendPreferenceEthernet(){
+ if ( this->getSendPreference()==PACKET_SEND_ETH_WEAK )
+ return true;
+ else if (this->getSendPreference()==PACKET_SEND_ETH_STRONG)
+ return true;
+ else if (this->getSendPreference()==PACKET_SEND_ETH )
+ return true;
+ else
+ return false;
+} /* End of sendPreferenceEthernet() */
+
+
+/* Returns true if send preference is Ethernet */
+bool NpingOps::sendPreferenceIP(){
+ if ( this->getSendPreference()==PACKET_SEND_IP_WEAK )
+ return true;
+ else if (this->getSendPreference()==PACKET_SEND_IP_STRONG)
+ return true;
+ else if (this->getSendPreference()==PACKET_SEND_IP )
+ return true;
+ else
+ return false;
+} /* End of sendPreferenceIP() */
+
+
+/** Sets SendEth.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setSendEth(bool val){
+ this->send_eth=val;
+ this->send_eth_set=true;
+ return OP_SUCCESS;
+} /* End of setSendEth() */
+
+
+/** Returns value of attribute send_eth */
+bool NpingOps::sendEth(){
+ return this->send_eth;
+} /* End of getSendEth() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetSendEth(){
+ return this->send_eth_set;
+} /* End of issetSendEth() */
+
+
+/** Sets inter-probe delay. Supplied parameter is assumed to be in milliseconds
+ * and must be a long integer greater than zero.
+ * @warning timeout is assumed to be in milliseconds. Use tval2msecs() from
+ * nbase to obtain a proper value.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setDelay(long t){
+ if( t < 0 )
+ nping_fatal(QT_3,"setDelay(): Invalid time supplied\n");
+ this->delay=t;
+ this->delay_set=true;
+ return OP_SUCCESS;
+} /* End of setDelay() */
+
+
+/** Returns value of attribute delay */
+long NpingOps::getDelay(){
+ return delay;
+} /* End of getDelay() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDelay(){
+ return this->delay_set;
+} /* End of issetDelay() */
+
+
+/** Sets network device. Supplied parameter must be a valid network interface
+ * name.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setDevice(char *n){
+ if( n==NULL ){
+ nping_fatal(QT_3,"setDevice(): Invalid value supplied\n");
+ }else{
+ Strncpy(this->device, n, MAX_DEV_LEN-1);
+ }
+ this->device_set=true;
+ return OP_SUCCESS;
+} /* End of setDevice() */
+
+
+char *NpingOps::getDevice(){
+ return this->device;
+} /* End of getDevice() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDevice(){
+ return this->device_set;
+} /* End of issetDevice() */
+
+
+/** Returns true if user requested explicitly that he wants IP source
+ * spoofing */
+bool NpingOps::spoofSource(){
+ return this->spoofsource;
+} /* End of spoofSource() */
+
+
+bool NpingOps::getSpoofSource(){
+ return this->spoofsource;
+} /* End of getSpoofSource() */
+
+
+int NpingOps::setSpoofSource(){
+ this->spoofsource=true;
+ this->spoofsource_set=true;
+ return OP_SUCCESS;
+} /* End of spoofSource() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetSpoofSource(){
+ return this->spoofsource_set;
+} /* End of issetSpoofSource() */
+
+
+/** Sets BPFFilterSpec.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setBPFFilterSpec(char *val){
+ this->bpf_filter_spec=val;
+ this->bpf_filter_spec_set=true;
+ return OP_SUCCESS;
+} /* End of setBPFFilterSpec() */
+
+
+/** Returns value of attribute bpf_filter_spec */
+char *NpingOps::getBPFFilterSpec(){
+ return this->bpf_filter_spec;
+} /* End of getBPFFilterSpec() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetBPFFilterSpec(){
+ return this->bpf_filter_spec_set;
+} /* End of issetBPFFilterSpec() */
+
+
+/** Sets CurrentRound.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setCurrentRound(int val){
+ this->current_round=val;
+ return OP_SUCCESS;
+} /* End of setCurrentRound() */
+
+
+/** Returns value of attribute current_round */
+int NpingOps::getCurrentRound(){
+ return this->current_round;
+} /* End of getCurrentRound() */
+
+
+bool NpingOps::havePcap(){
+ return this->have_pcap;
+} /* End of havePcap() */
+
+
+int NpingOps::setHavePcap(bool val){
+ this->have_pcap=val;
+ return OP_SUCCESS;
+} /* End of setHavePcap() */
+
+
+/** Sets DisablePacketCapture.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setDisablePacketCapture(bool val){
+ this->disable_packet_capture=val;
+ this->disable_packet_capture_set=true;
+ return OP_SUCCESS;
+} /* End of setDisablePacketCapture() */
+
+
+/** Returns value of attribute disable_packet_capture */
+bool NpingOps::disablePacketCapture(){
+ return this->disable_packet_capture;
+} /* End of disablePacketCapture() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDisablePacketCapture(){
+ return this->disable_packet_capture_set;
+} /* End of issetDisablePacketCapture() */
+
+/** Sets the IP version that will be used in all packets. Supplied parameter
+ * must be either IP_VERSION_4 or IP_VERSION_&.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setIPVersion(u8 val){
+ if( val!=IP_VERSION_4 && val!=IP_VERSION_6 ){
+ nping_fatal(QT_3,"setIPVersion(): Invalid value supplied\n");
+ return OP_FAILURE;
+ }else{
+ this-> ipversion=val;
+ }
+ this->ipversion_set=true;
+ return OP_SUCCESS;
+} /* End of setIPVersion() */
+
+
+/** Returns value of attribute ipversion. */
+int NpingOps::getIPVersion(){
+ return ipversion;
+} /* End of getIPVersion() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetIPVersion(){
+ return this->ipversion_set;
+} /* End of issetIPversion() */
+
+
+/* Returns true if we are using IPv4 */
+bool NpingOps::ipv4(){
+ if( this->getIPVersion() == IP_VERSION_4 )
+ return true;
+ else
+ return false;
+} /* End of ipv4() */
+
+
+/* Returns true if we are using IPv6 */
+bool NpingOps::ipv6(){
+ if( this->getIPVersion() == IP_VERSION_6 )
+ return true;
+ else
+ return false;
+} /* End of ipv6() */
+
+
+/* Returns true if we are sending IPv6 packets at raw TCP level (using a
+ * useless and boring IPv6 socket that doesn't let us include our own IPv6
+ * header)*/
+bool NpingOps::ipv6UsingSocket(){
+ if( this->getIPVersion() == IP_VERSION_6 && this->sendEth()==false)
+ return true;
+ else
+ return false;
+} /* End of ipv6UsingSocket() */
+
+
+/* Returns AF_INET or AF_INET6, depending on current configuration */
+int NpingOps::af(){
+ if( this->getIPVersion() == IP_VERSION_6 )
+ return AF_INET6;
+ else
+ return AF_INET;
+} /* End of af() */
+
+
+/******************************************************************************
+ * User types and Privileges *
+ ******************************************************************************/
+
+/** Sets value of attribute isr00t.
+ * @returns previous isr00t value */
+int NpingOps::setIsRoot(int v) {
+ int prev=this->isr00t;
+ this->isr00t = (v==0) ? 0 : 1;
+ return prev;
+} /* End of setIsRoot() */
+
+
+/** Sets attribute isr00t to value 1.
+ * @returns previous isr00t value */
+int NpingOps::setIsRoot() {
+ int prev=this->isr00t;
+ this->isr00t=1;
+ return prev;
+} /* End of setIsRoot() */
+
+
+/* Returns the state of attribute isr00t */
+bool NpingOps::isRoot() {
+ return (this->isr00t);
+} /* End of isRoot() */
+
+
+/******************************************************************************
+ * Payloads *
+ ******************************************************************************/
+
+/** Sets payload type. Supplied parameter must be one of: PL_RAND, PL_HEX or
+ * PL_FILE;
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setPayloadType(int t){
+ if( t!=PL_RAND && t!=PL_HEX && t!=PL_FILE && t!=PL_STRING){
+ nping_fatal(QT_3,"setPayloadType(): Invalid value supplied\n");
+ return OP_FAILURE;
+ }else{
+ payload_type=t;
+ }
+ this->payload_type_set=true;
+ return OP_SUCCESS;
+} /* End of setPayloadType() */
+
+
+/** Returns value of attribute payload_type */
+int NpingOps::getPayloadType(){
+ return payload_type;
+} /* End of getPayloadType() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetPayloadType(){
+ return this->payload_type_set;
+} /* End of issetPayloadType() */
+
+
+/** Sets payload buffer pointer. Supplied pointer must be a free()able
+ * non-NULL pointer; Supplied length must be a positive integer.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setPayloadBuffer(u8 *p, int len){
+ if( p==NULL || len < 0 ){
+ nping_fatal(QT_3,"setPayloadBuffer(): Invalid value supplied\n");
+ return OP_FAILURE;
+ }else{
+ this->payload_buff=p;
+ this->payload_len=len;
+ }
+ this->payload_buff_set=true;
+ this->payload_len_set=true;
+ return OP_SUCCESS;
+} /* End of setPayloadBuffer() */
+
+
+/** Returns value of attribute payload_type */
+u8 *NpingOps::getPayloadBuffer(){
+ return this->payload_buff;
+} /* End of getPayloadBuffer() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetPayloadBuffer(){
+ return this->payload_buff_set;
+} /* End of issetPayloadBuffer() */
+
+
+/** Returns value of attribute payload_len */
+int NpingOps::getPayloadLen(){
+ return this->payload_len;
+} /* End of getPayloadLen() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetPayloadLen(){
+ return this->payload_len_set;
+} /* End of issetPayloadLen() */
+
+
+/******************************************************************************
+ * Roles (normal, client, server... ) *
+ ******************************************************************************/
+
+/** Sets nping's role. Supplied argument must be one of: ROLE_NORMAL,
+ * ROLE_CLIENT or ROLE_SERVER.
+ * @return previous value of attribute "role" or OP_FAILURE in case of error.
+ * */
+int NpingOps::setRole(int r){
+ int prev = this->role;
+ if (r!=ROLE_NORMAL && r!=ROLE_CLIENT && r!=ROLE_SERVER){
+ nping_warning(QT_2,"setRoleClient(): Invalid role supplied");
+ return OP_FAILURE;
+ }
+ else
+ this->role=r;
+ this->role_set=true;
+ return prev;
+} /* End of setRole() */
+
+
+/** Sets nping's role to ROLE_CLIENT.
+ * @return previous value of attribute "role". */
+int NpingOps::setRoleClient(){
+ int prev = this->role;
+ this->role=ROLE_CLIENT;
+ this->role_set=true;
+ return prev;
+} /* End of setRoleClient() */
+
+
+/** Sets nping's role to ROLE_SERVER.
+ * @return previous value of attribute "role". */
+int NpingOps::setRoleServer(){
+ int prev = this->role;
+ this->role=ROLE_SERVER;
+ this->role_set=true;
+ return prev;
+} /* End of setRoleServer() */
+
+
+/** Sets nping's role to ROLE_NORMAL.
+ * @return previous value of attribute "role". */
+int NpingOps::setRoleNormal(){
+ int prev = this->role;
+ this->role=ROLE_NORMAL;
+ this->role_set=true;
+ return prev;
+} /* End of setRoleNormal() */
+
+/* Returns nping role. */
+int NpingOps::getRole(){
+ return this->role;
+} /* End of getRole() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetRole(){
+ return this->role_set;
+} /* End of issetRole() */
+
+
+
+/******************************************************************************
+ * Internet Protocol Version 4 *
+ ******************************************************************************/
+
+/** Sets IPv4 TTL / IPv6 hop limit. Supplied parameter must be an integer
+ * between 0 and 255 (included).
+ * @return OP_SUCCESS */
+int NpingOps::setTTL(u8 t){
+ this->ttl=t;
+ this->ttl_set=true;
+ return OP_SUCCESS;
+} /* End of setTTL() */
+
+
+/** Sets IPv4 TTL / IPv6 hop limit. This a wrapper for setTTL(). It is provided
+ * for consistency with IPv6 option setters.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setHopLimit(u8 t){
+ return setTTL(t);
+} /* End of setHopLimit() */
+
+
+/** Returns value of attribute ttl */
+u8 NpingOps::getTTL(){
+ return ttl;
+} /* End of getTTL() */
+
+
+/** Returns value of attribute ttl */
+u8 NpingOps::getHopLimit(){
+ return getTTL();
+} /* End of getHopLimit() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTTL(){
+ return this->ttl_set;
+} /* End of issetTTL() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetHopLimit(){
+ return issetTTL();
+} /* End of issetHopLimit() */
+
+
+/** Sets IP TOS. Supplied parameter must be 0<=n<=255
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setTOS(u8 val){
+ this->tos=val;
+ this->tos_set=true;
+ return OP_SUCCESS;
+} /* End of setTOS() */
+
+
+/** Returns value of attribute TOS */
+u8 NpingOps::getTOS(){
+ return this->tos;
+} /* End of getTOS() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTOS(){
+ return this->tos_set;
+} /* End of isset() */
+
+
+/** Sets IP Identification. Supplied parameter must be 0<=n<=255
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setIdentification(u16 val){
+ this->identification=val;
+ this->identification_set=true;
+ return OP_SUCCESS;
+} /* End of setIdentification() */
+
+
+/** Returns value of attribute Identification */
+u16 NpingOps::getIdentification(){
+ return this->identification;
+} /* End of getIdentification() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetIdentification(){
+ return this->identification_set;
+} /* End of issetIdentification() */
+
+
+int NpingOps::setMF(){
+ this->mf = true;
+ this->mf_set=true;
+ return OP_SUCCESS;
+} /* End of setMF() */
+
+
+/* Get MF flag */
+bool NpingOps::getMF(){
+ return this->mf;
+} /* End of getMF() */
+
+
+/** Set DF flag */
+int NpingOps::setDF(){
+ this->df = true;
+ this->df_set=true;
+ return OP_SUCCESS;
+} /* End of setDF() */
+
+
+/** Get DF flag */
+bool NpingOps::getDF(){
+ return this->df;
+} /* End of getDF() */
+
+
+/** Set Reserved / Evil flag */
+int NpingOps::setRF(){
+ this->rf = true;
+ this->rf_set = true;
+ return OP_SUCCESS;
+} /* End of setRF() */
+
+
+/** Get Reserved / Evil flag */
+bool NpingOps::getRF(){
+ return this->rf;
+} /* End of getRF() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetMF(){
+ return this->mf_set;
+} /* End of isset() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDF(){
+ return this->df_set;
+} /* End of isset() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetRF(){
+ return this->rf_set;
+} /* End of isset() */
+
+
+/** Sets Maximum Transmission Unit length. Supplied parameter must be a positive
+ * integer and must be a multiple of 8.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setMTU(u32 t){
+ if(t==0 || (t%8)!=0){
+ nping_fatal(QT_3,"setMTU(): Invalid mtu supplied\n");
+ }else{
+ this->mtu=t;
+ this->mtu_set=true;
+ }
+ return OP_SUCCESS;
+} /* End of setMTU() */
+
+
+/** Returns value of attribute mtu */
+u32 NpingOps::getMTU(){
+ return this->mtu;
+} /* End of getMTU() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetMTU(){
+ return this->mtu_set;
+} /* End of issetMTU() */
+
+
+/** Sets attribute badsum_ip to "true". (Generate invalid checksums in IP
+ * packets)
+ * @return previous value of the attribute. */
+bool NpingOps::enableBadsumIP() {
+ bool prev = this->badsum_ip;
+ this->badsum_ip=true;
+ this->badsum_ip_set=true;
+ return prev;
+} /* End of enableBadsumIP() */
+
+
+/** Sets attribute badsum_ip to "false". (Do NOT Generate invalid checksums
+ * in IP packets)
+ * @return previous value of the attribute. */
+bool NpingOps::disableBadsumIP() {
+ bool prev = badsum_ip;
+ badsum_ip=false;
+ this->badsum_ip_set=true;
+ return prev;
+} /* End of disableBadsumIP() */
+
+
+/** Returns value of attribute badsum_ip */
+bool NpingOps::getBadsumIP() {
+ return this->badsum_ip;
+} /* End of getBadsumIP() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetBadsumIP(){
+ return this->badsum_ip_set;
+} /* End of issetBadsumIP() */
+
+
+/** @warning Supplied parameter must be in NETWORK byte order */
+int NpingOps::setIPv4SourceAddress(struct in_addr i){
+ this->ipv4_src_address=i;
+ this->ipv4_src_address_set=true;
+ return OP_SUCCESS;
+} /* End of setIPv4SourceAddress() */
+
+
+struct in_addr NpingOps::getIPv4SourceAddress(){
+ return ipv4_src_address;
+} /* End of getIPv4SourceAddress() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetIPv4SourceAddress(){
+ return this->ipv4_src_address_set;
+} /* End of issetIPv4SourceAddress() */
+
+
+/** @warning This method makes a copy of the supplied buffer. That copy will
+ * be free()ed by the NpingOps destructor. */
+int NpingOps::setIPOptions(char *txt){
+ if (txt==NULL)
+ nping_fatal(QT_3,"setIPOptions(): NULL pointer supplied\n");
+ this->ip_options=strdup(txt) ;
+ this->ip_options_set=true;
+ return OP_SUCCESS;
+} /* End of setIPOptions() */
+
+
+char *NpingOps::getIPOptions(){
+ return this->ip_options;
+} /* End of getIPOptions() */
+
+
+bool NpingOps::issetIPOptions(){
+ return this->ip_options_set;
+} /* End of issetIPOptions() */
+
+
+/******************************************************************************
+ * Internet Protocol Version 6 *
+ ******************************************************************************/
+/** Sets TrafficClass.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setTrafficClass(u8 val){
+ this->ipv6_tclass=val;
+ this->ipv6_tclass_set=true;
+ return OP_SUCCESS;
+} /* End of setTrafficClass() */
+
+
+/** Returns value of attribute ipv6_tclass */
+u8 NpingOps::getTrafficClass(){
+ return this->ipv6_tclass;
+} /* End of getTrafficClass() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTrafficClass(){
+ return this->ipv6_tclass_set;
+} /* End of issetTrafficClass() */
+
+
+/** Sets FlowLabel.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setFlowLabel(u32 val){
+ this->ipv6_flowlabel=val;
+ this->ipv6_flowlabel_set=true;
+ return OP_SUCCESS;
+} /* End of setFlowLabel() */
+
+
+/** Returns value of attribute ipv6_flowlabel */
+u32 NpingOps::getFlowLabel(){
+ return this->ipv6_flowlabel;
+} /* End of getFlowLabel() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetFlowLabel(){
+ return this->ipv6_flowlabel_set;
+} /* End of issetFlowLabel() */
+
+
+
+int NpingOps::setIPv6SourceAddress(u8 *val){
+ if(val==NULL)
+ nping_fatal(QT_3,"setIPv6SourceAddress(): NULL pointer supplied\n");
+ memcpy(this->ipv6_src_address.s6_addr, val, 16);
+ this->ipv6_src_address_set=true;
+ return OP_SUCCESS;
+} /* End of setIPv6SourceAddress() */
+
+
+int NpingOps::setIPv6SourceAddress(struct in6_addr val){
+ this->ipv6_src_address = val;
+ this->ipv6_src_address_set=true;
+ return OP_SUCCESS;
+} /* End of setIPv6SourceAddress() */
+
+
+struct in6_addr NpingOps::getIPv6SourceAddress(){
+ return ipv6_src_address;
+} /* End of getIPv6SourceAddress() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetIPv6SourceAddress(){
+ return this->ipv6_src_address_set;
+} /* End of issetIPv6SourceAddress() */
+
+
+/* Returns a pointer to a sockaddr_storage structure that contains the
+ * source IP address. This function takes into account this->getIPVersion()
+ * an returns an IPv4 sockaddr_in or an IPv6 sockaddr_in6 struct. */
+struct sockaddr_storage *NpingOps::getSourceSockAddr(){
+ static struct sockaddr_storage ss;
+ return getSourceSockAddr(&ss);
+} /* End of getSourceSockAddr() */
+
+
+/* Returns a pointer to the supplied sockaddr_storage structure that now
+ * contains the source IP address. This function takes into account
+ * this->getIPVersion() an returns an IPv4 sockaddr_in or an IPv6
+ * sockaddr_in6 struct. */
+struct sockaddr_storage *NpingOps::getSourceSockAddr(struct sockaddr_storage *ss){
+ struct sockaddr_in *s4 = (struct sockaddr_in*)ss;
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6*)ss;
+ memset(ss, 0, sizeof(struct sockaddr_storage));
+ if( this->getIPVersion() == IP_VERSION_4){
+ if(this->spoofSource())
+ s4->sin_addr=getIPv4SourceAddress();
+ else
+ s4->sin_addr.s_addr=INADDR_ANY;
+ s4->sin_family=AF_INET;
+ if(this->issetSourcePort())
+ s4->sin_port=htons(this->getSourcePort());
+ else
+ s4->sin_port=0;
+ }
+ else if (this->getIPVersion() == IP_VERSION_6){
+ if(this->spoofSource())
+ s6->sin6_addr=this->getIPv6SourceAddress();
+ else
+ s6->sin6_addr=in6addr_any;
+ s6->sin6_addr=this->getIPv6SourceAddress();
+ s6->sin6_family=AF_INET6;
+ if(this->issetSourcePort())
+ s6->sin6_port=htons(this->getSourcePort());
+ else
+ s6->sin6_port=0;
+ }else{
+ nping_fatal(QT_3, "NpingOps::getSourceSockAddr(): IP version unset.");
+ }
+ return ss;
+} /* End of getSourceSockAddr() */
+
+
+
+/******************************************************************************
+ * Transmission Control Protocol and User Datagram Protocol *
+ ******************************************************************************/
+
+/** @warning Returned ports are in HOST byte order */
+u16 *NpingOps::getTargetPorts( int *len ){
+ if( this->tportcount <= 0)
+ return NULL;
+ if(len!=NULL)
+ *len=this->tportcount;
+ return this->target_ports;
+} /* End of getTargetPorts() */
+
+
+/** @warning ports in the supplied array must be in HOST byte order */
+int NpingOps::setTargetPorts( u16 *pnt, int n ){
+ if(this->tportcount>65536 || this->tportcount<0)
+ nping_fatal(QT_3, "setTargetPorts():: Invalid number of ports supplied.");
+ this->target_ports=pnt;
+ this->tportcount=n;
+ this->target_ports_set=true;
+ return OP_SUCCESS;
+} /* End of setTargetPorts() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTargetPorts(){
+ return this->target_ports_set;
+} /* End of issetTargetPorts() */
+
+/*Returns true if the scan type can use the -p option*/
+bool NpingOps::scan_mode_uses_target_ports(int mode){
+ return (mode==TCP_CONNECT || mode==TCP || mode == UDP || mode == UDP_UNPRIV);
+} /*End of scan_mode_uses_target_ports*/
+
+/** Sets TCP/UPD source port. Supplied parameter must be an integer >=0 &&
+ * <=65535
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setSourcePort(u16 val){
+ this->source_port=val;
+ this->source_port_set=true;
+ return OP_SUCCESS;
+} /* End of setSourcePort() */
+
+
+/** Returns value of attribute source_port */
+u16 NpingOps::getSourcePort(){
+ return this->source_port;
+} /* End of getSourcePort() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetSourcePort(){
+ return this->source_port_set;
+} /* End of issetSourcePort() */
+
+
+/** Sets TCP Seq number. Supplied parameter must be a positive integer between
+ * 0 and 2^32 -1
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setTCPSequence(u32 val){
+ this->tcpseq=val;
+ this->tcpseq_set=true;
+ return OP_SUCCESS;
+} /* End of setTCPSequence() */
+
+
+/** Returns value of attribute tcpseq */
+u32 NpingOps::getTCPSequence(){
+ return this->tcpseq;
+} /* End of getTCPSequence() */
+
+
+/** Returns true if option has been set */
+bool NpingOps::issetTCPSequence(){
+ return this->tcpseq_set;
+} /* End of issetTCPSequence() */
+
+
+/** Sets TCP Ack. Supplied parameter must be a positive integer between 0 and
+ * 2^32 -1
+ * @return OP_SUCCESS */
+int NpingOps::setTCPAck(u32 val){
+ this->tcpack=val;
+ this->tcpack_set=true;
+ return OP_SUCCESS;
+} /* End of setTCPAck() */
+
+
+/** Returns value of attribute tcpack */
+u32 NpingOps::getTCPAck(){
+ return this->tcpack;
+} /* End of getTCPAck() */
+
+
+/** Returns true if option has been set */
+bool NpingOps::issetTCPAck(){
+ return this->tcpack_set;
+} /* End of issetTCPAck() */
+
+
+int NpingOps::setFlagTCP(int flag){
+ if (flag < FLAG_CWR || flag > FLAG_FIN)
+ nping_fatal(QT_3,"setFlagTCP(): Invalid flag supplied\n");
+ else
+ this->tcpflags[flag]=1;
+ this->tcpflags_set=true;
+ return OP_SUCCESS;
+} /* End of setFlagTCP() */
+
+
+int NpingOps::setAllFlagsTCP(){
+ for(int i=FLAG_CWR; i<=FLAG_FIN; i++)
+ this->tcpflags[i]=1;
+ this->tcpflags_set=true;
+ return OP_SUCCESS;
+} /* End of setFlagTCP() */
+
+
+int NpingOps::unsetAllFlagsTCP(){
+ for(int i=FLAG_CWR; i<=FLAG_FIN; i++)
+ this->tcpflags[i]=0;
+ this->tcpflags_set=true;
+ return OP_SUCCESS;
+} /* End of setFlagTCP() */
+
+
+int NpingOps::getFlagTCP(int flag){
+ if (flag < FLAG_CWR || flag > FLAG_FIN)
+ nping_fatal(QT_3,"setFlagTCP(): Invalid flag supplied\n");
+ return this->tcpflags[flag];
+} /* End of getFlagTCP() */
+
+
+u8 NpingOps::getTCPFlags(){
+ u8 octet=0x00;
+ if(this->getFlagTCP(FLAG_CWR))
+ octet |= TH_CWR;
+ if(this->getFlagTCP(FLAG_ECN))
+ octet |= TH_ECN;
+ if(this->getFlagTCP(FLAG_URG))
+ octet |= TH_URG;
+ if(this->getFlagTCP(FLAG_ACK))
+ octet |= TH_ACK;
+ if(this->getFlagTCP(FLAG_PSH))
+ octet |= TH_PSH;
+ if(this->getFlagTCP(FLAG_RST))
+ octet |= TH_RST;
+ if(this->getFlagTCP(FLAG_SYN))
+ octet |= TH_SYN;
+ if(this->getFlagTCP(FLAG_FIN))
+ octet |= TH_FIN;
+ return octet;
+} /* End of getTCPFlags() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetTCPFlags(){
+ return this->tcpflags_set;
+} /* End of isset() */
+
+
+/** Sets TCP Window. Supplied parameter must be a positive integer between 0 and
+ * 2^32 -1
+ * @return OP_SUCCESS */
+int NpingOps::setTCPWindow(u16 val){
+ this->tcpwin=val;
+ this->tcpwin_set=true;
+ return OP_SUCCESS;
+} /* End of setTCPWindow() */
+
+
+/** Returns value of attribute tcpwin */
+u16 NpingOps::getTCPWindow(){
+ return this->tcpwin;
+} /* End of getTCPWindow() */
+
+
+/** Returns true if option has been set */
+bool NpingOps::issetTCPWindow(){
+ return this->tcpwin_set;
+} /* End of issetTCPWindow() */
+
+
+/** Sets attribute badsum to "true". (Generate invalid checksums in UDP / TCP
+ * packets)
+ * @return previous value of the attribute. */
+bool NpingOps::enableBadsum() {
+ bool prev = this->badsum;
+ this->badsum=true;
+ this->badsum_set=true;
+ return prev;
+} /* End of enableBadsumTCP() */
+
+
+/** Sets attribute traceroute to "false". (Do NOT Generate invalid checksums
+ * in UDP / TCP packets)
+ * @return previous value of the attribute. */
+bool NpingOps::disableBadsum() {
+ bool prev = this->badsum;
+ this->badsum=false;
+ this->badsum_set=true;
+ return prev;
+} /* End of disableBadsum() */
+
+
+/** Returns value of attribute badsum */
+bool NpingOps::getBadsum() {
+ return this->badsum;
+} /* End of getBadsum() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetBadsum(){
+ return this->badsum_set;
+} /* End of issetBadsum() */
+
+
+
+/******************************************************************************
+ * Internet Control Message Protocol *
+ ******************************************************************************/
+/** Sets ICMPType.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPType(u8 val){
+ this->icmp_type=val;
+ this->icmp_type_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPType() */
+
+
+/** Returns value of attribute icmp_type */
+u8 NpingOps::getICMPType(){
+ return this->icmp_type;
+} /* End of getICMPType() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPType(){
+ return this->icmp_type_set;
+} /* End of issetICMPType() */
+
+
+/** Sets ICMPCode.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPCode(u8 val){
+ this->icmp_code=val;
+ this->icmp_code_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPCode() */
+
+
+/** Returns value of attribute icmp_code */
+u8 NpingOps::getICMPCode(){
+ return this->icmp_code;
+} /* End of getICMPCode() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPCode(){
+ return this->icmp_code_set;
+} /* End of issetICMPCode() */
+
+
+/** Sets attribute badsum_icmp to "true". (Generate invalid checksums in ICMP
+ * packets)
+ * @return previous value of the attribute. */
+bool NpingOps::enableBadsumICMP() {
+ bool prev = this->badsum_icmp;
+ this->badsum_icmp=true;
+ this->badsum_icmp_set=true;
+ return prev;
+} /* End of enableBadsumICMPTCP() */
+
+
+/** Sets attribute traceroute to "false". (Do NOT Generate invalid checksums
+ * in UDP / TCP packets)
+ * @return previous value of the attribute. */
+bool NpingOps::disableBadsumICMP() {
+ bool prev = this->badsum_icmp;
+ this->badsum_icmp=false;
+ this->badsum_icmp_set=true;
+ return prev;
+} /* End of disableBadsumICMP() */
+
+
+/** Returns value of attribute badsum_icmp */
+bool NpingOps::getBadsumICMP() {
+ return this->badsum_icmp;
+} /* End of getBadsumICMP() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetBadsumICMP(){
+ return this->badsum_icmp_set;
+} /* End of issetBadsumICMP() */
+
+
+/** Sets ICMPRedirectAddress.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPRedirectAddress(struct in_addr val){
+ this->icmp_redir_addr=val;
+ this->icmp_redir_addr_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPRedirectAddress() */
+
+
+/** Returns value of attribute icmp_redir_addr */
+struct in_addr NpingOps::getICMPRedirectAddress(){
+ return this->icmp_redir_addr;
+} /* End of getICMPRedirectAddress() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPRedirectAddress(){
+ return this->icmp_redir_addr_set;
+} /* End of issetICMPRedirectAddress() */
+
+
+/** Sets ICMPParamProblemPointer.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPParamProblemPointer(u8 val){
+ this->icmp_paramprob_pnt=val;
+ this->icmp_paramprob_pnt_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPParamProblemPointer() */
+
+
+/** Returns value of attribute icmp_paramprob_pnt */
+u8 NpingOps::getICMPParamProblemPointer(){
+ return this->icmp_paramprob_pnt;
+} /* End of getICMPParamProblemPointer() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPParamProblemPointer(){
+ return this->icmp_paramprob_pnt_set;
+} /* End of issetICMPParamProblemPointer() */
+
+
+/** Sets ICMPRouterAdvLifetime.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPRouterAdvLifetime(u16 val){
+ this->icmp_routeadv_ltime=val;
+ this->icmp_routeadv_ltime_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPRouterAdvLifetime() */
+
+
+/** Returns value of attribute icmp_routeadv_ltime */
+u16 NpingOps::getICMPRouterAdvLifetime(){
+ return this->icmp_routeadv_ltime;
+} /* End of getICMPRouterAdvLifetime() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPRouterAdvLifetime(){
+ return this->icmp_routeadv_ltime_set;
+} /* End of issetICMPRouterAdvLifetime() */
+
+
+/** Sets ICMPIdentifier.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPIdentifier(u16 val){
+ this->icmp_id=val;
+ this->icmp_id_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPIdentifier() */
+
+/** Returns value of attribute icmp_id */
+u16 NpingOps::getICMPIdentifier(){
+ return this->icmp_id;
+} /* End of getICMPIdentifier() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPIdentifier(){
+ return this->icmp_id_set;
+} /* End of issetICMPIdentifier() */
+
+
+/** Sets ICMPSequence.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPSequence(u16 val){
+ this->icmp_seq=val;
+ this->icmp_seq_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPSequence() */
+
+
+/** Returns value of attribute icmp_seq */
+u16 NpingOps::getICMPSequence(){
+ return this->icmp_seq;
+} /* End of getICMPSequence() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPSequence(){
+ return this->icmp_seq_set;
+} /* End of issetICMPSequence() */
+
+
+/** Sets ICMPOriginateTimestamp.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPOriginateTimestamp(u32 val){
+ this->icmp_orig_time=val;
+ this->icmp_orig_time_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPOriginateTimestamp() */
+
+
+/** Returns value of attribute icmp_orig_time */
+u32 NpingOps::getICMPOriginateTimestamp(){
+ return this->icmp_orig_time;
+} /* End of getICMPOriginateTimestamp() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPOriginateTimestamp(){
+ return this->icmp_orig_time_set;
+} /* End of issetICMPOriginateTimestamp() */
+
+
+/** Sets ICMPReceiveTimestamp.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPReceiveTimestamp(u32 val){
+ this->icmp_recv_time=val;
+ this->icmp_recv_time_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPReceiveTimestamp() */
+
+
+/** Returns value of attribute icmp_recv_time */
+u32 NpingOps::getICMPReceiveTimestamp(){
+ return this->icmp_recv_time;
+} /* End of getICMPReceiveTimestamp() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPReceiveTimestamp(){
+ return this->icmp_recv_time_set;
+} /* End of issetICMPReceiveTimestamp() */
+
+
+/** Sets ICMPTransmitTimestamp.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setICMPTransmitTimestamp(u32 val){
+ this->icmp_trans_time=val;
+ this->icmp_trans_time_set=true;
+ return OP_SUCCESS;
+} /* End of setICMPTransmitTimestamp() */
+
+
+/** Returns value of attribute icmp_trans_time */
+u32 NpingOps::getICMPTransmitTimestamp(){
+ return this->icmp_trans_time;
+} /* End of getICMPTransmitTimestamp() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetICMPTransmitTimestamp(){
+ return this->icmp_trans_time_set;
+} /* End of issetICMPTransmitTimestamp() */
+
+
+int NpingOps::addICMPAdvertEntry(struct in_addr addr, u32 pref ){
+ if( this->icmp_advert_entry_count > MAX_ICMP_ADVERT_ENTRIES )
+ return OP_FAILURE;
+ this->icmp_advert_entry_addr[this->icmp_advert_entry_count] = addr;
+ this->icmp_advert_entry_pref[this->icmp_advert_entry_count] = pref;
+ this->icmp_advert_entry_count++;
+ this->icmp_advert_entry_set=true;
+ return OP_SUCCESS;
+} /* End of addICMPAdvertEntry() */
+
+
+/** @param num means that the caller wants to obtain the num-th entry.
+ * Count starts in 0 so the supplied value must be
+ * 0 <= num < getICMPAdvertEntryCount() */
+int NpingOps::getICMPAdvertEntry(int num, struct in_addr *addr, u32 *pref){
+ if( num<0 || num>=icmp_advert_entry_count )
+ nping_fatal(QT_3,"getICMPAdvertEntry(): Supplied index is out of bounds.\n");
+ if( addr==NULL || pref==NULL)
+ nping_fatal(QT_3,"getICMPAdvertEntry(): NULL pointer supplied\n");
+ *addr = this->icmp_advert_entry_addr[num];
+ *pref = this->icmp_advert_entry_pref[num];
+ return OP_SUCCESS;
+} /* End of getICMPAdvertEntry() */
+
+
+int NpingOps::getICMPAdvertEntryCount(){
+ return this->icmp_advert_entry_count;
+} /* End of getICMPAdvertEntryCount()*/
+
+bool NpingOps::issetICMPAdvertEntry(){
+ return this->icmp_advert_entry_set;
+} /* End of issetICMPAdvertEntry()*/
+
+
+
+/******************************************************************************
+ * Ethernet *
+ ******************************************************************************/
+/** Sets SourceMAC.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setSourceMAC(u8 * val){
+ memcpy(this->src_mac, val, 6);
+ this->src_mac_set=true;
+ return OP_SUCCESS;
+} /* End of setSourceMAC() */
+
+
+/** Returns value of attribute src_mac */
+u8 * NpingOps::getSourceMAC(){
+ return this->src_mac;
+} /* End of getSourceMAC() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetSourceMAC(){
+ return this->src_mac_set;
+} /* End of issetSourceMAC() */
+
+
+/** Sets DestMAC.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setDestMAC(u8 * val){
+ memcpy(this->dst_mac, val, 6);
+ this->dst_mac_set=true;
+ return OP_SUCCESS;
+} /* End of setDestMAC() */
+
+
+/** Returns value of attribute dst_mac */
+u8 * NpingOps::getDestMAC(){
+ return this->dst_mac;
+} /* End of getDestMAC() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetDestMAC(){
+ return this->dst_mac_set;
+} /* End of issetDestMAC() */
+
+/** Sets EtherType.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setEtherType(u16 val){
+ this->eth_type=val;
+ this->eth_type_set=true;
+ return OP_SUCCESS;
+} /* End of setEtherType() */
+
+
+/** Returns value of attribute eth_type */
+u16 NpingOps::getEtherType(){
+ return this->eth_type;
+} /* End of getEtherType() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetEtherType(){
+ return this->eth_type_set;
+} /* End of issetEtherType() */
+
+
+
+/******************************************************************************
+ * Address Resolution Protocol / Reverse Address Resolution Protocol *
+ ******************************************************************************/
+/** Sets ARPHardwareType.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPHardwareType(u16 val){
+ this->arp_htype=val;
+ this->arp_htype_set=true;
+ return OP_SUCCESS;
+} /* End of setARPHardwareType() */
+
+
+/** Returns value of attribute arp_htype */
+u16 NpingOps::getARPHardwareType(){
+ return this->arp_htype;
+} /* End of getARPHardwareType() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPHardwareType(){
+ return this->arp_htype_set;
+} /* End of issetARPHardwareType() */
+
+
+/** Sets ARPProtocolType.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPProtocolType(u16 val){
+ this->arp_ptype=val;
+ this->arp_ptype_set=true;
+ return OP_SUCCESS;
+} /* End of setARPProtocolType() */
+
+
+/** Returns value of attribute arp_ptype */
+u16 NpingOps::getARPProtocolType(){
+ return this->arp_ptype;
+} /* End of getARPProtocolType() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPProtocolType(){
+ return this->arp_ptype_set;
+} /* End of issetARPProtocolType() */
+
+
+/** Sets ARPHwAddrLen.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPHwAddrLen(u8 val){
+ this->arp_hlen=val;
+ this->arp_hlen_set=true;
+ return OP_SUCCESS;
+} /* End of setARPHwAddrLen() */
+
+
+/** Returns value of attribute arp_hlen */
+u8 NpingOps::getARPHwAddrLen(){
+ return this->arp_hlen;
+} /* End of getARPHwAddrLen() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPHwAddrLen(){
+ return this->arp_hlen_set;
+} /* End of issetARPHwAddrLen() */
+
+
+/** Sets ARPProtoAddrLen.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPProtoAddrLen(u8 val){
+ this->arp_plen=val;
+ this->arp_plen_set=true;
+ return OP_SUCCESS;
+} /* End of setARPProtoAddrLen() */
+
+
+/** Returns value of attribute arp_plen */
+u8 NpingOps::getARPProtoAddrLen(){
+ return this->arp_plen;
+} /* End of getARPProtoAddrLen() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPProtoAddrLen(){
+ return this->arp_plen_set;
+} /* End of issetARPProtoAddrLen() */
+
+
+/** Sets ARPOpCode.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPOpCode(u16 val){
+ this->arp_opcode=val;
+ this->arp_opcode_set=true;
+ return OP_SUCCESS;
+} /* End of setARPOpCode() */
+
+
+/** Returns value of attribute arp_opcode */
+u16 NpingOps::getARPOpCode(){
+ return this->arp_opcode;
+} /* End of getARPOpCode() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPOpCode(){
+ return this->arp_opcode_set;
+} /* End of issetARPOpCode() */
+
+
+/** Sets ARPSenderHwAddr.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPSenderHwAddr(u8 * val){
+ memcpy(this->arp_sha, val, 6); /* MAC Address (6 bytes) */
+ this->arp_sha_set=true;
+ return OP_SUCCESS;
+} /* End of setARPSenderHwAddr() */
+
+
+/** Returns value of attribute arp_sha */
+u8 * NpingOps::getARPSenderHwAddr(){
+ return this->arp_sha;
+} /* End of getARPSenderHwAddr() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPSenderHwAddr(){
+ return this->arp_sha_set;
+} /* End of issetARPSenderHwAddr() */
+
+
+/** Sets ARPTargetHwAddr.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPTargetHwAddr(u8 * val){
+ memcpy(this->arp_tha, val, 6); /* MAC Address (6 bytes) */
+ this->arp_tha_set=true;
+ return OP_SUCCESS;
+} /* End of setARPTargetHwAddr() */
+
+
+/** Returns value of attribute arp_tha */
+u8 * NpingOps::getARPTargetHwAddr(){
+ return this->arp_tha;
+} /* End of getARPTargetHwAddr() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPTargetHwAddr(){
+ return this->arp_tha_set;
+} /* End of issetARPTargetHwAddr() */
+
+
+/** Sets ARPSenderProtoAddr.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPSenderProtoAddr(struct in_addr val){
+ this->arp_spa=val;
+ this->arp_spa_set=true;
+ return OP_SUCCESS;
+} /* End of setARPSenderProtoAddr() */
+
+
+/** Returns value of attribute arp_spa */
+struct in_addr NpingOps::getARPSenderProtoAddr(){
+ return this->arp_spa;
+} /* End of getARPSenderProtoAddr() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPSenderProtoAddr(){
+ return this->arp_spa_set;
+} /* End of issetARPSenderProtoAddr() */
+
+
+/** Sets ARPTargetProtoAddr.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setARPTargetProtoAddr(struct in_addr val){
+ this->arp_tpa=val;
+ this->arp_tpa_set=true;
+ return OP_SUCCESS;
+} /* End of setARPTargetProtoAddr() */
+
+
+/** Returns value of attribute arp_tpa */
+struct in_addr NpingOps::getARPTargetProtoAddr(){
+ return this->arp_tpa;
+} /* End of getARPTargetProtoAddr() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetARPTargetProtoAddr(){
+ return this->arp_tpa_set;
+} /* End of issetARPTargetProtoAddr() */
+
+
+/** Sets EchoPort.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setEchoPort(u16 val){
+ this->echo_port=val;
+ this->echo_port_set=true;
+ return OP_SUCCESS;
+} /* End of setEchoPort() */
+
+
+/** Returns value of attribute echo_port */
+u16 NpingOps::getEchoPort(){
+ return this->echo_port;
+} /* End of getEchoPort() */
+
+
+/* Returns true if option has been set */
+bool NpingOps::issetEchoPort(){
+ return this->echo_port_set;
+} /* End of issetEchoPort() */
+
+
+int NpingOps::setEchoPassphrase(const char *str){
+ strncpy(this->echo_passphrase, str, sizeof(echo_passphrase)-1);
+ this->echo_passphrase_set=true;
+ return OP_SUCCESS;
+} /* End of setEchoPassphrase() */
+
+
+char *NpingOps::getEchoPassphrase(){
+ return this->echo_passphrase;
+} /* End of getEchoPassphrase() */
+
+
+bool NpingOps::issetEchoPassphrase(){
+ return this->echo_passphrase_set;
+} /* End of issetEchoPassphrase() */
+
+/** Sets value of this->echo_server_once. When true, the echo server
+ * will exit after attending one client. */
+int NpingOps::setOnce(bool val){
+ this->echo_server_once=val;
+ this->echo_server_once_set=true;
+ return OP_SUCCESS;
+} /* End of once() */
+
+
+/** Returns value of attribute echo_port */
+bool NpingOps::once(){
+ return this->echo_server_once;
+} /* End of once() */
+
+
+/******************************************************************************
+ * Option Validation *
+ ******************************************************************************/
+
+void NpingOps::validateOptions() {
+
+/** DETERMINE ROOT PRIVILEGES ************************************************/
+const char *privreq = "root privileges";
+#ifdef WIN32
+ //if (!this->have_pcap)
+ privreq = "Npcap, but it seems to be missing.\n\
+Npcap is available from https://npcap.com. The Npcap driver service must\n\
+be started by an administrator before Npcap can be used. Running nping.exe\n\
+will open a UAC dialog where you can start the service if you have\n\
+administrator privileges.";
+#endif
+
+if (this->havePcap()==false){
+ #ifdef WIN32
+ nping_fatal(QT_3, "Nping requires %s", privreq);
+ #else
+ nping_fatal(QT_3, "Nping requires libpcap to be installed on your system.");
+ #endif
+}
+
+
+/** ROLE SELECTION ***********************************************************/
+ /* Ensure that at least one role is selected */
+ if ( !this->issetRole() ) {
+ this->setRoleNormal();
+ }
+
+/** TARGET SPECIFICATION *****************************************************/
+ /* Check if user entered at least one target spec */
+ if( this->getRole() == ROLE_NORMAL ){
+ if ( this->targets.getTargetSpecCount() <= 0 )
+ nping_fatal(QT_3,"WARNING: No targets were specified, so 0 hosts pinged.");
+ }else if( this->getRole() == ROLE_CLIENT ){
+ if ( this->targets.getTargetSpecCount() <= 0 )
+ nping_fatal(QT_3,"No echo server was specified.");
+ }
+
+/** IP VERSION ***************************************************************/
+ /* Default to IP version 4 */
+ if( !this->issetIPVersion() )
+ this->setIPVersion( IP_VERSION_4 );
+
+
+/** PROBE MODE SELECTION *****************************************************/
+ /* Ensure that one probe mode is selected */
+ if( !this->issetMode() ){
+ if ( this->isRoot() ){
+ if( !this->ipv6() )
+ this->setMode(ICMP);
+ else
+ this->setMode(TCP);
+ }
+ else
+ this->setMode(TCP_CONNECT);
+ }
+
+/** PACKET COUNT / ROUNDS ****************************************************/
+ if( !this->issetPacketCount() ){
+ /* If --traceroute is set, the packet count is higher */
+ if(this->issetTraceroute() )
+ this->setPacketCount( TRACEROUTE_PACKET_COUNT );
+ else
+ this->setPacketCount( DEFAULT_PACKET_COUNT );
+ }
+
+
+ if( !this->issetDelay() )
+ this->setDelay( DEFAULT_DELAY );
+
+/** UDP UNPRIVILEGED MODE? ***************************************************/
+ /* If user is NOT root and specified UDP mode, check if he did not specify
+ * any option that requires privileges. In that case, we enter
+ * UDP-Unprivileged mode, where users can send UDP packets and read responses
+ * trough a normal UDP socket. */
+ if( !this->isRoot() && this->getMode()==UDP && canRunUDPWithoutPrivileges() )
+ this->setMode( UDP_UNPRIV );
+
+/** CHECK PRIVILEGES FOR CURRENT ROLE ****************************************/
+ if( !this->isRoot() && (this->getRole()==ROLE_SERVER || this->getRole()==ROLE_CLIENT) )
+ nping_fatal(QT_3,"Echo mode requires %s.", privreq);
+
+/** CHECK PRIVILEGES FOR CURRENT MODE ****************************************/
+ if( !this->isRoot() && this->getMode()!=UDP_UNPRIV && this->getMode()!=TCP_CONNECT )
+ nping_fatal(QT_3,"Mode %s requires %s.", this->mode2Ascii( this->getMode() ), privreq);
+
+
+/** DEFAULT HEADER PARAMETERS *************************************************/
+ this->setDefaultHeaderValues();
+
+/** ARP MODE RELATED PARAMETERS *********************************************/
+ if(this->getMode()==ARP && this->ipv6()) {
+ nping_fatal(QT_3, "Sorry, ARP does not support IPv6 and Nping does not yet support NDP.");
+ }
+
+/** TCP CONNECT RELATED PARAMETERS *********************************************/
+ if(this->getMode()==TCP_CONNECT) {
+ if(this->issetPayloadBuffer())
+ nping_print(VB_0, "Warning: Payload supplied in TCP Connect mode. Payload will be ignored.");
+ }
+
+/** SOURCE IP, SOURCE MAC and NETWORK DEVICE *********************************/
+/* If we are in a mode where we need to craft IP packets, then we need to
+ * obtain a network interface name and a source IP address. There are three
+ * different possibilities:
+ * 1. User did NOT specify both network interface and source IP address.
+ * 2. User did specify a network interface but not a source IP address.
+ * 3. User did actually supply a source IP but not a network interface name
+ *
+ * I know the following code is ugly but the thing is that we want to determine
+ * interface and source IP without user intervention, so we try in many ways
+ * until either we succeed or we run out of possibilities and fatal().
+ */
+if( this->getMode()!=TCP_CONNECT && this->getMode()!=UDP_UNPRIV && this->getRole()!=ROLE_SERVER){
+
+ char devbuff[32];
+ char *dev;
+ struct sockaddr_storage ss, ifaddr;
+ struct sockaddr_in *s4=(struct sockaddr_in *)&ifaddr;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ifaddr;
+ size_t ss_len;
+ char hostname[128];
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+ memset(&ifaddr, 0, sizeof(struct sockaddr_storage));
+
+
+ /* CASE 1: User did not specify a device so we have to select one. */
+ if( !this->issetDevice() ){
+ if( this->ipv4() ){
+ /* Ugly hack. Get the first resolvable target and determine net interface. Let's
+ * hope user did not specify something that mixes localhost with
+ * other targets, like "nping localhost google.com playboy.com" */
+ for(int z=0; z<this->targets.getTargetSpecCount(); z++){
+ if( this->targets.getNextTargetAddressAndName(&ss, &ss_len, hostname, sizeof(hostname)) == OP_SUCCESS )
+ break;
+ else if( z>=(this->targets.getTargetSpecCount()-1) )
+ 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");
+ }
+ this->targets.rewind();
+
+ /* Try to obtain a device name from the target IP */
+ if ( getNetworkInterfaceName( &ss , devbuff) != OP_SUCCESS ) {
+ /* If that didn't work, ask libpcap */
+ if ( (dev = this->select_network_iface()) == NULL)
+ nping_fatal(QT_3, "Cannot obtain device for packet capture");
+ else
+ this->setDevice( dev );
+ /* Libpcap gave us a device name, try to obtain it's IP */
+ if ( devname2ipaddr_alt(this->getDevice(), &ifaddr) != 0 ){
+ if( this->isRoot() )
+ nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, does it even exist?", this->getDevice());
+ else
+ nping_fatal(QT_3,"Cannot figure out what source address to use for device %s, are you root?", this->getDevice());
+ }
+ else{
+ if( s4->sin_family==AF_INET )
+ this->setIPv4SourceAddress(s4->sin_addr);
+ else if ( s6->sin6_family==AF_INET6 )
+ this->setIPv6SourceAddress(s6->sin6_addr.s6_addr);
+ }
+ }else{
+ this->setDevice(devbuff);
+ }
+ }else{ /* In IPv6 we just select one in libpcap and hope is the right one */
+ char *selected_iface=this->select_network_iface();
+ if(selected_iface==NULL)
+ nping_fatal(QT_3, "Error trying to find a suitable network interface ");
+ else
+ this->setDevice( selected_iface );
+ }
+ } /* CASE 2: User did actually supply a device name */
+ else{
+ nping_print(DBG_2, "Using network interface \"%s\"", this->getDevice() );
+ }
+
+/* The echo server needs to find out a network interface*/
+}else if (this->getRole()==ROLE_SERVER && this->issetDevice()==false){
+ char *selected_iface=this->select_network_iface();
+ if(selected_iface==NULL)
+ nping_fatal(QT_3, "Error trying to find a suitable network interface ");
+ else
+ this->setDevice( selected_iface );
+ nping_print(DBG_2, "Using network interface \"%s\"", this->getDevice() );
+}
+
+/** RAW IP AND RAW ETHERNET TRANSMISSION MODES *******************************/
+/* Determine if we need to send at raw ip level or at raw ethernet level */
+if(this->getRole()!=ROLE_SERVER){
+ if (!this->issetSendPreference()) {
+
+
+ /* CASE 1: ARP requested. We have to do raw ethernet transmission */
+ if(this->getMode()==ARP ){
+ this->setSendEth(true);
+ this->setSendPreference( PACKET_SEND_ETH_STRONG );
+ }
+
+ /* CASE 2: If we are dealing with IPv6 we have two options: send at raw
+ * eth level or sent at raw transport layer level. So here, we check if the
+ * user has specified some IPv6 header specific options. If he has, we then
+ * have to use raw ethernet (since we cannot include our own IPv6 header in
+ * raw IPv6 sockets). If he hasn't, the best way is to send at raw TCP/UDP
+ * level so we disable sendEth() */
+ else if (this->ipv6() ){
+
+ /* CASE 2.A: If user did not specify custom IPv6 header or Ethernet
+ * field values go for raw transport layer level transmission */
+ if( this->canDoIPv6ThroughSocket() ){
+ this->setSendEth(false);
+ this->setSendPreference( PACKET_SEND_IP_STRONG );
+ }
+ /* CASE 2.B: User wants to set some IPv6 or Ethernet values. So here we
+ * check if enough parameters were supplied. */
+ else if (this->canDoIPv6Ethernet() ){
+ this->setSendEth(true);
+ this->setSendPreference( PACKET_SEND_ETH_STRONG );
+ }else{
+ nping_fatal(QT_3, "If you want to control some of the fields"
+ " in the IPv6 header you also have to supply source and"
+ " destination MAC address. However, you can always"
+ " choose to let the kernel create the IPv6 header"
+ " choosing not to pass --source-IP, --traffic-class"
+ " or --flow options. That should simplify things a bit");
+ }
+ }
+ /* CASE 3: We are dealing with regular, IPv4-based modes. In this case
+ * we just select transmission mode based on current OS. For Windows
+ * we choose raw eth level because MS has disable raw sockets support.
+ * For the rest of systems, we chose raw IP because it's easier for us
+ * as we don't have to deal with all the source MAC and next-hop MAC address
+ * determination process. */
+ else{
+ #ifdef WIN32
+ this->setSendPreference( PACKET_SEND_ETH_STRONG );
+ this->setSendEth(true);
+ #else
+ this->setSendPreference( PACKET_SEND_IP_WEAK );
+ this->setSendEth(false);
+ #endif
+ }
+
+ /* User did actually supplied his own sending preference. Let's check if we
+ * can actually send probes the way he wants. */
+ }else{
+
+ if( this->getMode()==ARP && !this->sendPreferenceEthernet() ){
+ this->setSendEth(true);
+ nping_warning(QT_2, "Warning: ARP mode requires raw ethernet frame transmission. Specified preference will be ignored.");
+ }
+ else if( this->ipv6() ){
+
+ /* CASE 1: User requested ethernet explicitly and supplied all
+ * necessary options. */
+ if( this->sendPreferenceEthernet() && this->canDoIPv6Ethernet() ){
+ this->setSendEth(true);
+
+ /* CASE 2: User requested Ethernet but did not really supplied all
+ * the information we need */
+ }else if( this->sendPreferenceEthernet() && !this->canDoIPv6Ethernet() ){
+ nping_fatal(QT_3, "You requested raw ethernet level transmission and IPv6."
+ " In this case, you need to supply source MAC address,"
+ " destination MAC address and IPv6 source address.");
+
+ /* CASE 3: User requested raw IP transmission and did not request
+ * any special IPv6 header options. */
+ }else if( this->sendPreferenceIP() && this->canDoIPv6ThroughSocket() ){
+ this->setSendEth(false);
+
+ /* CASE 4: User requested raw IP transmission but also wanted to
+ * set custom IPv6 header field values. */
+ }else if (this->sendPreferenceIP() && !this->canDoIPv6ThroughSocket()){
+ nping_fatal(QT_3, "You requested raw IP transmission mode for IPv6."
+ " Nping does not currently allow IPv6 header manipulation"
+ " when sending packets at raw IP level due to the limitations"
+ " on raw IPv6 sockets, imposed by RFC 2292. Please"
+ " use raw Ethernet transmission (option --send-eth)");
+
+
+ }
+ }
+ else if( this->sendPreferenceEthernet() ){
+ this->setSendEth(true);
+ }else{
+ this->setSendEth(false);
+ }
+ }
+ if( this->getMode()==TCP_CONNECT || this->getMode()==UDP_UNPRIV )
+ nping_print(DBG_2,"Nping will send packets in unprivileged mode using regular system calls");
+ else
+ nping_print(DBG_2,"Nping will send packets at %s", this->sendEth() ? "raw ethernet level" : "raw IP level" );
+}
+
+/** ECHO MODE ************************************************************/
+
+ if(this->getRole()==ROLE_CLIENT){
+
+ /* Make sure the nping echo client does not generate packets with tcp
+ * src port or tcp dst port 9929 (or --echo-port N, if that is set),
+ * because 1) the echo server does not capture those packets and 2) to
+ * avoid messing with the established side-channel tcp connection. */
+ if(this->getMode()==TCP){
+ for(int i=0; i<tportcount; i++){
+ if( this->target_ports[i]==this->getEchoPort())
+ 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());
+ else if(this->getSourcePort()==this->getEchoPort())
+ 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());
+ }
+ }
+
+ /* Check the echo client only produces TCP/UDP/ICMP packets */
+ switch( this->getMode() ){
+ case TCP:
+ case UDP:
+ case ICMP:
+ break;
+
+ default:
+ nping_fatal(QT_3, "The echo client can't be run with protocols other than TCP, UDP or ICMP.");
+ break;
+ }
+ }
+ #ifndef HAVE_OPENSSL
+ if(this->getRole()==ROLE_CLIENT || this->getRole()==ROLE_SERVER ){
+ if( this->doCrypto()==true ){
+ 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.");
+ }
+ }
+ #endif
+
+/** FRAGMENTATION ************************************************************/
+#if !defined(LINUX) && !defined(OPENBSD) && !defined(FREEBSD) && !defined(NETBSD)
+ if (this->issetMTU()) {
+ error("Warning: Packet fragmentation selected on a host other than Linux, OpenBSD, FreeBSD, or NetBSD. This may or may not work.");
+ }
+#endif
+
+/** MISCELLANEOUS ************************************************************/
+if( this->issetSourcePort() && this->getMode()==TCP_CONNECT && this->getPacketCount()>1 )
+ 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() );
+} /* End of validateOptions() */
+
+
+/** Returns true if requested mode is a simple TCP connect probe mode */
+bool NpingOps::canRunUDPWithoutPrivileges(){
+ if( this->issetBadsumIP() ||
+ this->issetTTL() ||
+ this->issetHopLimit() ||
+ this->issetTOS() ||
+ this->issetIdentification() ||
+ this->issetMF() ||
+ this->issetDF() ||
+ this->issetRF() ||
+ this->issetIPv4SourceAddress() ||
+ this->issetIPv6SourceAddress() ||
+ this->issetIPOptions() ||
+ this->issetMTU() ||
+ this->issetSpoofSource() ||
+ this->issetSourceMAC() ||
+ this->issetDestMAC() ||
+ this->issetEtherType() ||
+ this->issetTraceroute() ||
+ this->issetBPFFilterSpec()
+ )
+ return false;
+ else
+ return true;
+} /* End canRunUDPWithoutPrivileges() */
+
+
+/** Returns true if user did not request any special ethernet or ipv6 header
+ * options */
+bool NpingOps::canDoIPv6ThroughSocket(){
+ if( this->issetEtherType() ||
+ this->issetDestMAC() ||
+ this->issetSourceMAC() ||
+ this->issetHopLimit() ||
+ this->issetTrafficClass() ||
+ this->issetFlowLabel() ||
+ this->issetIPv6SourceAddress()
+ )
+ return false;
+ else
+ return true;
+} /* End canDoIPv6ThroughSocket() */
+
+
+/** Returns true if user supplied all necessary options to allow IPv6 at raw
+ * Ethernet level */
+bool NpingOps::canDoIPv6Ethernet(){
+ if( this->issetDestMAC() && this->issetSourceMAC() && this->issetIPv6SourceAddress() )
+ return true;
+ else
+ return false;
+} /* End canDoIPv6Ethernet() */
+
+
+/******************************************************************************
+ * Miscellaneous *
+ ******************************************************************************/
+
+void NpingOps::displayNpingDoneMsg(){
+
+ if( this->getRole()==ROLE_SERVER ){
+ nping_print(QT_1, "Nping done: %lu %s served in %.2f seconds",
+ (unsigned long)this->stats.getEchoClientsServed(),
+ (this->stats.getEchoClientsServed() == 1)? "client" : "clients",
+ this->stats.elapsedRuntime()
+ );
+ }else{
+ nping_print(QT_1, "Nping done: %lu %s pinged in %.2f seconds",
+ this->targets.getTargetsFetched(),
+ (this->targets.getTargetsFetched() == 1)? "IP address" : "IP addresses",
+ this->stats.elapsedRuntime()
+ );
+ }
+} /* End of displayNpingDoneMessage() */
+
+
+/** @warning This method calls targets.rewind() */
+void NpingOps::displayStatistics(){
+ char auxbuff[256];
+ memset(auxbuff, 0, 256);
+ NpingTarget *target=NULL;
+ this->targets.rewind();
+
+ nping_print(VB_0," "); /* Print newline */
+
+ /* Per-target statistics */
+ if( this->targets.getTargetsFetched() > 1){
+ while( (target=this->targets.getNextTarget()) != NULL )
+ target->printStats();
+ }else{
+ target=this->targets.getNextTarget();
+ if( target!= NULL)
+ target->printRTTs();
+ }
+
+#ifdef WIN32
+ /* Sent/Recv/Echoed Packets */
+ if(this->getRole()==ROLE_CLIENT){
+ nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %I64u ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ nping_print(QT_1|NO_NEWLINE,"| Echoed: %I64u ", this->stats.getEchoedPackets() );
+ nping_print(QT_1,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
+ }else if(this->getRole()==ROLE_SERVER){
+ nping_print(QT_1|NO_NEWLINE, "Raw packets captured: %I64u ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Echoed: %I64u ", this->stats.getEchoedPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Not Matched: %I64u ", this->stats.getUnmatchedPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes()-this->stats.getEchoedBytes(), auxbuff, 256));
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getUnmatchedPacketPercentage100() );
+ }else if(this->getMode()==TCP_CONNECT){
+ nping_print(QT_1|NO_NEWLINE, "TCP connection attempts: %I64u ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Successful connections: %I64u ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Failed: %I64u ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ } else if (this->getMode()==UDP_UNPRIV){
+ nping_print(QT_1|NO_NEWLINE, "UDP packets sent: %I64u ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ } else{
+ nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %I64u ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %I64u ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %I64u ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ }
+#else
+ /* Sent/Recv/Echoed Packets */
+ if(this->getRole()==ROLE_CLIENT){
+ nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %llu ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ nping_print(QT_1|NO_NEWLINE,"| Echoed: %llu ", this->stats.getEchoedPackets() );
+ nping_print(QT_1,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
+ }else if(this->getRole()==ROLE_SERVER){
+ nping_print(QT_1|NO_NEWLINE, "Raw packets captured: %llu ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Echoed: %llu ", this->stats.getEchoedPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getEchoedBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Not Matched: %llu ", this->stats.getUnmatchedPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes()-this->stats.getEchoedBytes(), auxbuff, 256));
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getUnmatchedPacketPercentage100() );
+ }else if(this->getMode()==TCP_CONNECT){
+ nping_print(QT_1|NO_NEWLINE, "TCP connection attempts: %llu ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Successful connections: %llu ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Failed: %llu ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ } else if (this->getMode()==UDP_UNPRIV){
+ nping_print(QT_1|NO_NEWLINE, "UDP packets sent: %llu ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ } else{
+ nping_print(QT_1|NO_NEWLINE, "Raw packets sent: %llu ", this->stats.getSentPackets() );
+ nping_print(QT_1|NO_NEWLINE, "(%s) ", format_bytecount(this->stats.getSentBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Rcvd: %llu ", this->stats.getRecvPackets() );
+ nping_print(QT_1|NO_NEWLINE,"(%s) ", format_bytecount(this->stats.getRecvBytes(), auxbuff, 256));
+ nping_print(QT_1|NO_NEWLINE,"| Lost: %llu ", this->stats.getLostPackets() );
+ nping_print(QT_1,"(%.2lf%%)", this->stats.getLostPacketPercentage100() );
+ }
+#endif
+
+ /* Transmission times & rates */
+ nping_print(VB_1|NO_NEWLINE,"Tx time: %.5lfs ", this->stats.elapsedTx() );
+ nping_print(VB_1|NO_NEWLINE,"| Tx bytes/s: %.2lf ", this->stats.getOverallTxByteRate() );
+ nping_print(VB_1,"| Tx pkts/s: %.2lf", this->stats.getOverallTxPacketRate() );
+ nping_print(VB_1|NO_NEWLINE,"Rx time: %.5lfs ", this->stats.elapsedRx() );
+ nping_print(VB_1|NO_NEWLINE,"| Rx bytes/s: %.2lf ", this->stats.getOverallRxByteRate() );
+ nping_print(VB_1,"| Rx pkts/s: %.2lf", this->stats.getOverallRxPacketRate() );
+
+} /* End of displayStatistics() */
+
+
+/* Close open files, free allocated memory, etc. */
+int NpingOps::cleanup(){
+ this->targets.freeTargets();
+ return OP_SUCCESS;
+} /* End of cleanup() */
+
+
+char *NpingOps::select_network_iface(){
+ char errbuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *pcap_ifaces=NULL;
+
+ /* Vars for the current interface in the loop */
+ pcap_if_t *curr=NULL; /* Current pcap pcap_if_t element */
+ bool current_has_address=false; /* Does it have an addr of any type? */
+ bool current_has_ipv6=false; /* Does it have an IPv6 address? */
+ bool current_has_ipv4=false; /* Does it have an IPv4 address? */
+ bool current_is_loopback=false; /* Is it a loopback interface? */
+ bool select_current=false; /* Is current better than candidate? */
+ struct sockaddr_in6 devaddr6; /* We store iface's IPv6 address */
+ struct sockaddr_in devaddr4; /* And also its IPv4 address */
+
+ /* Vars for our candidate interface */
+ pcap_if_t *candidate=NULL;
+ bool candidate_has_address=false;
+ bool candidate_has_ipv6=false;
+ bool candidate_has_ipv4=false;
+ bool candidate_is_loopback=false;
+ //struct sockaddr_in6 candidate_addr6;
+ //struct sockaddr_in candidate_addr4;
+
+ /* Ask libpcap for a list of network interfaces */
+ if( pcap_findalldevs(&pcap_ifaces, errbuf) != 0 )
+ nping_fatal(QT_3, "Cannot obtain device for packet capture --> %s. You may want to specify one explicitly using option -e", errbuf);
+
+ /* Iterate over the interface list and select the best one */
+ for(curr=pcap_ifaces; curr!=NULL; curr=curr->next){
+ current_has_address=false; candidate_has_ipv6=false;
+ candidate_is_loopback=false; candidate_has_ipv4=false;
+ select_current=false;
+
+ if( curr->flags==PCAP_IF_LOOPBACK)
+ current_is_loopback=true;
+
+ /* Loop through the list of addresses */
+ for(pcap_addr_t *curraddr=curr->addresses; curraddr!=NULL; curraddr=curraddr->next){
+ current_has_address=true;
+ if( curraddr->addr->sa_family==AF_INET){
+ current_has_ipv4=true;
+ memcpy( &devaddr4, curraddr->addr, sizeof(struct sockaddr_in));
+ } else if( curraddr->addr->sa_family==AF_INET6){
+ current_has_ipv6=true;
+ memcpy( &devaddr6, curraddr->addr, sizeof(struct sockaddr_in6));
+ }
+ }
+
+ /* If we still have no candidate, take the first one we find */
+ if( candidate==NULL){
+ select_current=true;
+ }
+ /* If we already have a candidate, check if the one we are
+ * processing right now is better than the one we've already got */
+ else{
+ /* If our candidate does not have an IPv6 address but this one does,
+ * select the new one. */
+ if( candidate_has_ipv6==false && current_has_ipv6==true ){
+ select_current=true;
+ }
+ /* If our candidate does not even have an IPv4 address but this
+ * one does, select the new one. */
+ else if( candidate_has_ipv4==false && candidate_has_ipv6==false && current_has_ipv4){
+ select_current=true;
+ }
+ /* If our candidate is a loopback iface, select the new one */
+ else if( candidate_is_loopback && !current_is_loopback){
+
+ /* Select the new one only if it has an IPv6 address
+ * and the old one didn't. If our old loopback iface
+ * has an IPv6 address and this one does not, we
+ * prefer to keep the loopback one, even though the
+ * other is not loopback */
+ if(current_has_ipv6==true){
+ select_current=true;
+ }
+ /* We also prefer IPv4 capable interfaces than */
+ else if(candidate_has_ipv6==false && current_has_ipv4==true){
+ select_current=true;
+ }
+ }
+ /* If both are loopback, select the best one. */
+ else if( candidate->flags==PCAP_IF_LOOPBACK && curr->flags==PCAP_IF_LOOPBACK){
+ if( candidate_has_ipv6==false && current_has_ipv6 )
+ select_current=true;
+ }
+ }
+
+ /* Did we determine that we should discard our old candidate? */
+ if( select_current ){
+ candidate=curr;
+ candidate_has_address=current_has_address;
+ candidate_has_ipv4=current_has_ipv4;
+ candidate_has_ipv6=current_has_ipv6;
+ candidate_is_loopback=current_is_loopback;
+ }
+
+ /* Let's see if we have the interface of our dreams... */
+ if( candidate_has_address && candidate_has_ipv6 && candidate_has_ipv4 && candidate_is_loopback==false){
+ break;
+ }
+
+ }
+ if(candidate==NULL)
+ return NULL;
+ else
+ return candidate->name;
+} /* End of select_network_iface() */
+
+
+int NpingOps::setDefaultHeaderValues(){
+ if(this->ipv6()){ /* IPv6 */
+ if(!this->issetTrafficClass())
+ this->ipv6_tclass=DEFAULT_IPv6_TRAFFIC_CLASS;
+ if(!this->issetFlowLabel())
+ this->ipv6_flowlabel=(get_random_u32() % 1048575);
+ if(!this->issetHopLimit() && !this->issetTraceroute())
+ this->ttl=DEFAULT_IPv6_TTL;
+ }else{ /* IPv4 */
+ if(!this->issetTOS())
+ this->tos=DEFAULT_IP_TOS;
+ if(!this->issetIdentification())
+ this->identification=get_random_u16();
+ if(!this->issetTTL() && !this->issetTraceroute())
+ this->ttl=DEFAULT_IP_TTL;
+
+ }
+ switch( this->getMode() ){
+ case TCP:
+ if(!this->issetTargetPorts()){
+ u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
+ list[0]=DEFAULT_TCP_TARGET_PORT;
+ this->setTargetPorts(list, 1);
+ }
+ if(!this->issetSourcePort()){
+ /* Generate any source port higher than 1024 */
+ if(this->getRole()!=ROLE_CLIENT){
+ this->source_port=(1024 + ( get_random_u16()%(65535-1024) ));
+ }else{
+ /* For the echo client, avoid choosing the port used for the echo side channel */
+ while( (this->source_port=(1024 + ( get_random_u16()%(65535-1024) )))==this->echo_port );
+ }
+ }
+ if(!this->issetTCPSequence())
+ this->tcpseq=get_random_u32();
+ if(!this->issetTCPAck()){
+ if(this->getFlagTCP(FLAG_ACK))
+ this->tcpack=get_random_u32();
+ else
+ this->tcpack=0;
+ }
+ if(!this->issetTCPFlags())
+ this->setFlagTCP(FLAG_SYN);
+ if(!this->issetTCPWindow())
+ this->tcpwin=DEFAULT_TCP_WINDOW_SIZE;
+ /* @todo ADD urgent pointer handling here when it gets implemented */
+ break;
+
+ case UDP:
+ if(!this->issetTargetPorts()){
+ u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
+ list[0]=DEFAULT_UDP_TARGET_PORT;
+ this->setTargetPorts(list, 1);
+ }
+ if(!this->issetSourcePort())
+ this->source_port=DEFAULT_UDP_SOURCE_PORT;
+ break;
+
+ case ICMP:
+ if(this->ipv6()){
+ if(!this->issetICMPType()) /* Default to ICMP Echo */
+ this->icmp_type=DEFAULT_ICMPv6_TYPE;
+ if(!this->issetICMPCode())
+ this->icmp_code=DEFAULT_ICMPv6_CODE;
+ }else{
+ if(!this->issetICMPType()) /* Default to ICMP Echo */
+ this->icmp_type=DEFAULT_ICMP_TYPE;
+ if(!this->issetICMPCode())
+ this->icmp_code=DEFAULT_ICMP_CODE;
+ }
+ break;
+
+ case ARP:
+ if(!this->issetARPOpCode())
+ this->arp_opcode=DEFAULT_ARP_OP;
+ break;
+
+ case UDP_UNPRIV:
+ if(!this->issetTargetPorts()){
+ u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
+ list[0]=DEFAULT_UDP_TARGET_PORT;
+ this->setTargetPorts(list, 1);
+ }
+ if(!this->issetSourcePort())
+ this->source_port=DEFAULT_UDP_SOURCE_PORT;
+ break;
+
+ case TCP_CONNECT:
+ if( !this->issetTargetPorts() ) {
+ u16 *list = (u16 *)safe_zalloc( sizeof(u16) );
+ list[0]=DEFAULT_TCP_TARGET_PORT;
+ this->setTargetPorts(list, 1);
+ }
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+
+ return OP_SUCCESS;
+} /* End of setDefaultHeaderValues() */
+
+
+int NpingOps::setLastPacketSentTime(struct timeval t){
+ this->last_sent_pkt_time=t;
+ return OP_SUCCESS;
+} /* End of setLastPacketSentTime() */
+
+
+struct timeval NpingOps::getLastPacketSentTime(){
+ return this->last_sent_pkt_time;
+} /* End of getLastPacketSentTime() */
+
+
+/** Sets the RCVD output to be delayed. The supplied string is strdup()ed, so
+ * the caller may safely free() it or modify after calling this function.
+ * The "id" parameter is the nsock timer event scheduled for the output of
+ * the RCVD string (usually scheduled by ProbeMode). It is provided to allow
+ * other objects (like EchoClient) to cancel the event if they take care of
+ * printing the RCVD string before the timer goes off.*/
+int NpingOps::setDelayedRcvd(const char *str, nsock_event_id id){
+ if(str==NULL)
+ return OP_FAILURE;
+ this->delayed_rcvd_str=strdup(str);
+ this->delayed_rcvd_event=id;
+ this->delayed_rcvd_str_set=true;
+ return OP_SUCCESS;
+} /* End of setDelayedRcvd() */
+
+
+/** Returns a pointer to a delayed RCVD output string. It returns non-NULL
+ * strings only once per prior setDelayedRcvd() call. This is, when a string
+ * has been set through a setDelayRcdv() call, the first time getDelayRcvd()
+ * is called, it returns that string. Subsequent calls will return NULL until
+ * another string is set, using setDelayRcdv() again.
+ * The "id" parameter will be filled with the timer event that was supposed
+ * to print the message. If getDelayedRcvd() is called by the timer handler
+ * itself, then NULL can be passed safely since the event id is not needed.
+ * If the caller is some other method that wants to print the RCVD string
+ * before the timer goes off, it may use the event ID to cancel the scheduled
+ * event since it's no longer necessary.
+ * @warning returned string is the strdup()ed version of the string passed
+ * in the call to setDelayedRcvd(), so the caller MUST free the returned
+ * pointer when it's done using it. */
+char *NpingOps::getDelayedRcvd(nsock_event_id *id){
+ if(delayed_rcvd_str_set==false){
+ return NULL;
+ }else{
+ this->delayed_rcvd_str_set=false;
+ char *old=this->delayed_rcvd_str;
+ this->delayed_rcvd_str=NULL;
+ if(id!=NULL)
+ *id=this->delayed_rcvd_event;
+ return old;
+ }
+} /* End of getDelayedRcvd() */
+
+
+bool NpingOps::doCrypto(){
+ return this->do_crypto;
+}
+
+int NpingOps::doCrypto(bool value){
+ this->do_crypto=value;
+ return OP_SUCCESS;
+}
+
+/* Returns true if the echo server is allowed to include payloads in NEP_ECHO
+ * messages. */
+bool NpingOps::echoPayload(){
+ return this->echo_payload;
+}
+
+/* Enables or disables payload echo for the echo server. Pass true to enable
+ * or false to disable. */
+int NpingOps::echoPayload(bool value){
+ this->echo_payload=value;
+ this->echo_payload_set=true;
+ return OP_SUCCESS;
+}
+
+
+/** Returns the total number of probes to be sent (this takes into account
+ * the number of rounds, ports, and targets. It returns a positive integer
+ * on success and n<=0 in case of error. */
+int NpingOps::getTotalProbes(){
+ int total_ports=0;
+ this->getTargetPorts(&total_ports);
+ u64 tmp = (u64) this->getPacketCount() * total_ports;
+ if (tmp > INT_MAX) {
+ return -1;
+ }
+ tmp *= this->targets.Targets.size();
+ if (tmp > INT_MAX) {
+ return -1;
+ }
+ return (int) tmp;
+}
+
+
+/******************************************************************************
+ * Code templates. *
+ ******************************************************************************/
+
+/*
+
+Attributes for NpingOps:
+
+ TYPE ATTRNAME;
+ bool ATTRNAME_set;
+
+Prototypes for NpingOps:
+
+ int setMETHNAME(TYPE val);
+ TYPE getMETHNAME();
+ bool issetMETHNAME();
+
+Initialization for NpingOps::NpingOps()
+
+ ATTRNAME=0;
+ ATTRNAME_set=false;
+*/
+
+/** Sets METHNAME. Supplied parameter must be XXXXXXXX
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+/*int NpingOps::setMETHNAME(TYPE val){
+ if( 0 ){
+ nping_fatal(QT_3,"setMETHNAME(): Invalid value supplied\n");
+ return OP_FAILURE;
+ }else{
+ ATTRNAME=val;
+ ATTRNAME_set=true;
+ }
+ return OP_SUCCESS;
+} *//* End of setMETHNAME() */
+
+
+
+/** Returns value of attribute ATTRNAME */
+/*TYPE NpingOps::getMETHNAME(){
+ return this->ATTRNAME;
+} *//* End of getMETHNAME() */
+
+
+/* Returns true if option has been set */
+/*bool NpingOps::issetMETHNAME(){
+ return this->ATTRNAME_set;
+} *//* End of issetMETHNAME() */