From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- nping/ArgParser.cc | 1823 +++++ nping/ArgParser.h | 83 + nping/Crypto.cc | 279 + nping/Crypto.h | 86 + nping/EchoClient.cc | 1098 +++ nping/EchoClient.h | 131 + nping/EchoHeader.cc | 970 +++ nping/EchoHeader.h | 331 + nping/EchoServer.cc | 1567 ++++ nping/EchoServer.h | 131 + nping/LICENSE | 3 + nping/Makefile.in | 167 + nping/NEPContext.cc | 552 ++ nping/NEPContext.h | 213 + nping/NpingOps.cc | 3134 ++++++++ nping/NpingOps.h | 650 ++ nping/NpingTarget.cc | 1046 +++ nping/NpingTarget.h | 261 + nping/NpingTargets.cc | 387 + nping/NpingTargets.h | 111 + nping/ProbeMode.cc | 2342 ++++++ nping/ProbeMode.h | 133 + nping/common.cc | 65 + nping/common.h | 69 + nping/common_modified.cc | 782 ++ nping/common_modified.h | 140 + nping/config.guess | 1421 ++++ nping/config.sub | 1807 +++++ nping/configure | 7714 ++++++++++++++++++++ nping/configure.ac | 562 ++ nping/docs/AUTHORS | 16 + nping/docs/EchoProtoRFC.txt | 1158 +++ nping/docs/leet-nping-ascii-art.txt | 18 + nping/docs/nping-man.xml | 3575 +++++++++ nping/docs/nping-usage.txt | 120 + nping/docs/nping-usage.xml | 2 + nping/docs/nping.1 | 1797 +++++ nping/docs/npingmanhtml.xml | 13 + nping/doxyfile | 239 + nping/global_structures.h | 33 + nping/nping-dev/Diagram1.dia | Bin 0 -> 5086 bytes nping/nping-dev/EchoProtoRFC_v0.txt | 741 ++ nping/nping-dev/NpingCommandLine.txt | 151 + nping/nping-dev/NpingExamples.txt | 56 + nping/nping-dev/NpingRequirements.txt | 165 + nping/nping-dev/PacketDiff_RFC.txt | 538 ++ nping/nping-dev/README | 40 + nping/nping-dev/configFiles.txt | 12 + nping/nping-dev/do_valgrind.sh | 2 + nping/nping-dev/echo_proposal.txt | 222 + nping/nping-dev/nping_logo.svg | 483 ++ nping/nping-dev/packetDiagram.png | Bin 0 -> 44131 bytes .../pythonscripts/TemplateGettersSetters.txt | 25 + nping/nping-dev/pythonscripts/TemplateNpingOps.txt | 45 + nping/nping-dev/pythonscripts/addGettersSetters.py | 28 + .../nping-dev/pythonscripts/addManSectionEntry.py | 43 + nping/nping-dev/pythonscripts/addNpingOpsAttr.py | 12 + .../pythonscripts/man-section-entry-template.xml | 25 + .../pythonscripts/man-section-template.xml | 34 + nping/nping-dev/test/caps/tcpconnect_T1.cap | Bin 0 -> 2318 bytes nping/nping-dev/test/caps/tcpconnect_T2.cap | Bin 0 -> 824 bytes nping/nping-dev/test/caps/tcpconnect_T3.cap | Bin 0 -> 744 bytes nping/nping-dev/test/test_nping.sh | 1526 ++++ nping/nping-dev/valgrind_supress.txt | 85 + nping/nping.cc | 251 + nping/nping.h | 363 + nping/nping.spec | 54 + nping/nping.vcxproj | 199 + nping/nping_config.h.in | 154 + nping/nping_winconfig.h | 90 + nping/output.cc | 244 + nping/output.h | 114 + nping/stats.cc | 390 + nping/stats.h | 210 + nping/utils.cc | 438 ++ nping/utils.h | 105 + nping/utils_net.cc | 1941 +++++ nping/utils_net.h | 155 + nping/winfix.cc | 264 + nping/winfix.h | 35 + 80 files changed, 44269 insertions(+) create mode 100644 nping/ArgParser.cc create mode 100644 nping/ArgParser.h create mode 100644 nping/Crypto.cc create mode 100644 nping/Crypto.h create mode 100644 nping/EchoClient.cc create mode 100644 nping/EchoClient.h create mode 100644 nping/EchoHeader.cc create mode 100644 nping/EchoHeader.h create mode 100644 nping/EchoServer.cc create mode 100644 nping/EchoServer.h create mode 100644 nping/LICENSE create mode 100644 nping/Makefile.in create mode 100644 nping/NEPContext.cc create mode 100644 nping/NEPContext.h create mode 100644 nping/NpingOps.cc create mode 100644 nping/NpingOps.h create mode 100644 nping/NpingTarget.cc create mode 100644 nping/NpingTarget.h create mode 100644 nping/NpingTargets.cc create mode 100644 nping/NpingTargets.h create mode 100644 nping/ProbeMode.cc create mode 100644 nping/ProbeMode.h create mode 100644 nping/common.cc create mode 100644 nping/common.h create mode 100644 nping/common_modified.cc create mode 100644 nping/common_modified.h create mode 100755 nping/config.guess create mode 100755 nping/config.sub create mode 100755 nping/configure create mode 100644 nping/configure.ac create mode 100644 nping/docs/AUTHORS create mode 100644 nping/docs/EchoProtoRFC.txt create mode 100644 nping/docs/leet-nping-ascii-art.txt create mode 100644 nping/docs/nping-man.xml create mode 100644 nping/docs/nping-usage.txt create mode 100644 nping/docs/nping-usage.xml create mode 100644 nping/docs/nping.1 create mode 100644 nping/docs/npingmanhtml.xml create mode 100644 nping/doxyfile create mode 100644 nping/global_structures.h create mode 100644 nping/nping-dev/Diagram1.dia create mode 100644 nping/nping-dev/EchoProtoRFC_v0.txt create mode 100644 nping/nping-dev/NpingCommandLine.txt create mode 100644 nping/nping-dev/NpingExamples.txt create mode 100644 nping/nping-dev/NpingRequirements.txt create mode 100644 nping/nping-dev/PacketDiff_RFC.txt create mode 100644 nping/nping-dev/README create mode 100644 nping/nping-dev/configFiles.txt create mode 100755 nping/nping-dev/do_valgrind.sh create mode 100644 nping/nping-dev/echo_proposal.txt create mode 100644 nping/nping-dev/nping_logo.svg create mode 100644 nping/nping-dev/packetDiagram.png create mode 100644 nping/nping-dev/pythonscripts/TemplateGettersSetters.txt create mode 100755 nping/nping-dev/pythonscripts/TemplateNpingOps.txt create mode 100644 nping/nping-dev/pythonscripts/addGettersSetters.py create mode 100755 nping/nping-dev/pythonscripts/addManSectionEntry.py create mode 100755 nping/nping-dev/pythonscripts/addNpingOpsAttr.py create mode 100644 nping/nping-dev/pythonscripts/man-section-entry-template.xml create mode 100644 nping/nping-dev/pythonscripts/man-section-template.xml create mode 100644 nping/nping-dev/test/caps/tcpconnect_T1.cap create mode 100644 nping/nping-dev/test/caps/tcpconnect_T2.cap create mode 100644 nping/nping-dev/test/caps/tcpconnect_T3.cap create mode 100755 nping/nping-dev/test/test_nping.sh create mode 100644 nping/nping-dev/valgrind_supress.txt create mode 100644 nping/nping.cc create mode 100644 nping/nping.h create mode 100644 nping/nping.spec create mode 100644 nping/nping.vcxproj create mode 100644 nping/nping_config.h.in create mode 100644 nping/nping_winconfig.h create mode 100644 nping/output.cc create mode 100644 nping/output.h create mode 100644 nping/stats.cc create mode 100644 nping/stats.h create mode 100644 nping/utils.cc create mode 100644 nping/utils.h create mode 100644 nping/utils_net.cc create mode 100644 nping/utils_net.h create mode 100644 nping/winfix.cc create mode 100644 nping/winfix.h (limited to 'nping') diff --git a/nping/ArgParser.cc b/nping/ArgParser.cc new file mode 100644 index 0000000..fcc2aea --- /dev/null +++ b/nping/ArgParser.cc @@ -0,0 +1,1823 @@ + +/*************************************************************************** + * ArgParser.cc -- The ArgParser Class is the one in charge of command line* + * argument parsing. Essentially it contains method parseArguments() that * + * takes the usual argc and *argv[] parameters and fills the general * + * NpingOps class with all the information needed for the execution of * + * Nping. * + * * + ***********************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/ + * + ***************************************************************************/ + +#include "nping.h" + +#include "ArgParser.h" +#include "NpingOps.h" +#include "common.h" +#include "nbase.h" +#include "utils.h" +#include "utils_net.h" +#include "output.h" + +extern NpingOps o; + + +ArgParser::ArgParser() { + +} /* End of ArgParser constructor */ + + + +ArgParser::~ArgParser() { + +} /* End of ArgParser destructor */ + + + +int ArgParser::parseArguments(int argc, char *argv[]) { + int arg=0; + int auxint=0; + long l=0; + int option_index=0; + struct in_addr aux_ip4; + u32 aux32=0; + u16 aux16=0; + u8 aux8=0; + u8 auxmac[6]; + u8 *auxbuff=NULL; + u16 *portlist=NULL; + char errstr[256]; + char *script_kiddie; + + struct option long_options[] = { + + /* Probe modes */ + {"tcp-connect", no_argument, 0, 0}, + {"tcp", no_argument, 0, 0}, + {"udp", no_argument, 0, 0}, + {"icmp", no_argument, 0, 0}, + {"arp", no_argument, 0, 0}, + {"tr", no_argument, 0, 0}, + {"traceroute", no_argument, 0, 0}, + + /* Mode shortcuts */ + {"echo-request", no_argument, 0, 0}, + {"destination-unreachable", no_argument, 0, 0}, + {"dest-unr", no_argument, 0, 0}, + {"timestamp", no_argument, 0, 0}, + {"timestamp-request", no_argument, 0, 0}, + {"information", no_argument, 0, 0}, + {"information-request", no_argument, 0, 0}, + {"netmask", no_argument, 0, 0}, + {"netmask-request", no_argument, 0, 0}, + {"arp-request", no_argument, 0, 0}, + {"arp-reply", no_argument, 0, 0}, + {"rarp-request", no_argument, 0, 0}, + {"rarp-reply", no_argument, 0, 0}, + + /* TCP/UDP */ + {"source-port", required_argument, 0, 'g'}, + {"dest-port", required_argument, 0, 'p'}, + {"seq", required_argument, 0, 0}, + {"flags", required_argument, 0, 0}, + {"ack", required_argument, 0, 0}, + {"win", required_argument, 0, 0}, + {"badsum", no_argument, 0, 0}, + + /* ICMP */ + {"icmp-type", required_argument, 0, 0}, + {"icmp-code", required_argument, 0, 0}, + {"icmp-id", required_argument, 0, 0}, + {"icmp-seq", required_argument, 0, 0}, + {"icmp-redirect-addr", required_argument, 0, 0}, + {"icmp-param-pointer", required_argument, 0, 0}, + {"icmp-advert-lifetime", required_argument, 0, 0}, + {"icmp-advert-entry", required_argument, 0, 0}, + {"icmp-orig-time", required_argument, 0, 0}, + {"icmp-recv-time", required_argument, 0, 0}, + {"icmp-trans-time", required_argument, 0, 0}, + /* TODO: Add relevant flags for different ICMP options */ + + /* ARP/RARP */ + /* 1) ARP operation codes. */ + {"arp-type", required_argument, 0, 0}, + {"rarp-type", required_argument, 0, 0}, + {"arp-code", required_argument, 0, 0}, + {"rarp-code", required_argument, 0, 0}, + {"arp-operation", required_argument, 0, 0}, + {"arp-op", required_argument, 0, 0}, + {"rarp-operation", required_argument, 0, 0}, + {"rarp-op", required_argument, 0, 0}, + /* 2) Rest of the fields */ + {"arp-sender-mac", required_argument, 0, 0}, + {"arp-sender-ip", required_argument, 0, 0}, + {"arp-target-mac", required_argument, 0, 0}, + {"arp-target-ip", required_argument, 0, 0}, + {"rarp-sender-mac", required_argument, 0, 0}, + {"rarp-sender-ip", required_argument, 0, 0}, + {"rarp-target-mac", required_argument, 0, 0}, + {"rarp-target-ip", required_argument, 0, 0}, + + /* Ethernet */ + {"dest-mac", required_argument, 0, 0}, + {"source-mac", required_argument, 0, 0}, + {"spoof-mac", required_argument, 0, 0}, + {"ethertype", required_argument, 0, 0}, + {"ethtype", required_argument, 0, 0}, + {"ether-type", required_argument, 0, 0}, + + /* IPv4 */ + {"IPv4", no_argument, 0, '4'}, + {"ipv4", no_argument, 0, '4'}, + {"source-ip", required_argument, 0, 'S'}, + {"dest-ip", required_argument, 0, 0}, + {"tos", required_argument, 0, 0}, + {"id", required_argument, 0, 0}, + {"df", no_argument, 0, 0}, + {"mf", no_argument, 0, 0}, + {"evil", no_argument, 0, 0}, + {"ttl", required_argument, 0, 0}, + {"badsum-ip", no_argument, 0, 0}, + {"ip-options", required_argument, 0, 0}, + {"mtu", required_argument, 0, 0}, + /* Remember also: "-f" : Fragment packets*/ + + /* IPv6 */ + {"IPv6", no_argument, 0, '6'}, + {"ipv6", no_argument, 0, '6'}, + {"hop-limit", required_argument, 0, 0}, + {"tc", required_argument, 0, 0}, + {"traffic-class", required_argument, 0, 0}, + {"flow", required_argument, 0, 0}, + + /* Payload */ + {"data", required_argument, 0, 0}, + {"data-length", required_argument, 0, 0}, + {"data-string", required_argument, 0, 0}, + + /* Echo client/server */ + {"echo-client", required_argument, 0, 0}, + {"ec", required_argument, 0, 0}, + {"echo-server", required_argument, 0, 0}, + {"es", required_argument, 0, 0}, + {"echo-port", required_argument, 0, 0}, + {"ep", required_argument, 0, 0}, + {"no-crypto", no_argument, 0, 0}, + {"nc", no_argument, 0, 0}, + {"once", no_argument, 0, 0}, + {"safe-payloads", no_argument, 0, 0}, + {"include-payloads", no_argument, 0, 0}, + + /* Timing and performance */ + {"delay", required_argument, 0, 0}, + {"rate", required_argument, 0, 0}, + + /* Misc */ + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"count", required_argument, 0, 'c'}, + {"interface", required_argument, 0, 'e'}, + {"privileged", no_argument, 0, 0}, + {"unprivileged", no_argument, 0, 0}, + {"send-eth", no_argument, 0, 0}, + {"send-ip", no_argument, 0, 0}, + {"bpf-filter", required_argument, 0, 0}, + {"filter", required_argument, 0, 0}, + {"nsock-engine", required_argument, 0, 0}, + {"no-capture", no_argument, 0, 'N'}, + {"hide-sent", no_argument, 0, 'H'}, + + /* Output */ + {"verbose", optional_argument, 0, 'v'}, + {"reduce-verbosity", optional_argument, 0, 'q'}, + {"debug", no_argument, 0, 0}, + {"quiet", no_argument, 0, 0}, + {0, 0, 0, 0} + }; + + if( argc <= 1 ){ + this->printUsage(); + exit(1); + } + + /* Let's get this parsing party started */ + while((arg = getopt_long_only(argc,argv,"46c:d::e:fg:hHK:NP:q::p:S:Vv::", long_options, &option_index)) != EOF) { + + aux8=aux16=aux32=aux_ip4.s_addr=0; + + switch(arg) { + + case 0: + +/* PROBE MODES ***************************************************************/ + if (strcmp(long_options[option_index].name, "tcp-connect") == 0) { + if( o.issetMode() && o.getMode()!=TCP_CONNECT) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(TCP_CONNECT) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(TCP_CONNECT); + } else if (strcmp(long_options[option_index].name, "tcp") == 0) { + if( o.issetMode() && o.getMode()!=TCP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(TCP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(TCP); + } else if (strcmp(long_options[option_index].name, "udp") == 0) { + if( o.issetMode() && o.getMode()!=UDP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(UDP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(UDP); + } else if (strcmp(long_options[option_index].name, "icmp") == 0) { + if( o.issetMode() && o.getMode()!=ICMP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ICMP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ICMP); + } else if (strcmp(long_options[option_index].name, "arp") == 0) { + if( o.issetMode() && o.getMode()!=ARP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ARP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ARP); + } else if (strcmp(long_options[option_index].name, "traceroute") == 0 || + strcmp(long_options[option_index].name, "tr") == 0) { + o.enableTraceroute(); + + /* Now shortcuts that we support but that are not actual modes */ + } else if (strcmp(long_options[option_index].name, "arp-request") == 0) { + if( o.issetMode() && o.getMode()!=ARP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ARP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ARP); + o.setARPOpCode(OP_ARP_REQUEST); + } else if (strcmp(long_options[option_index].name, "arp-reply") == 0) { + if( o.issetMode() && o.getMode()!=ARP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ARP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ARP); + o.setARPOpCode(OP_ARP_REPLY); + } else if (strcmp(long_options[option_index].name, "rarp-request") == 0) { + if( o.issetMode() && o.getMode()!=ARP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ARP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ARP); + o.setARPOpCode(OP_RARP_REQUEST); + } else if (strcmp(long_options[option_index].name, "rarp-reply") == 0) { + if( o.issetMode() && o.getMode()!=ARP) + nping_fatal(QT_3,"Cannot specify more than one probe mode. Choose either %s or %s.", + strdup( o.mode2Ascii(ARP) ), strdup( o.mode2Ascii(o.getMode()) ) ); + o.setMode(ARP); + o.setARPOpCode(OP_RARP_REPLY); + } else if (strcmp(long_options[option_index].name, "destination-unreachable") == 0 || + strcmp(long_options[option_index].name, "dest-unr") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP Destination unreachable messages.", o.mode2Ascii(o.getMode())); + o.setMode(ICMP); + o.setICMPType( ICMP_UNREACH ); + } else if( strcmp(long_options[option_index].name, "echo-request") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP Echo request messages.", o.mode2Ascii(o.getMode())); + o.setMode(ICMP); + o.setICMPType( ICMP_ECHO ); + } else if (strcmp(long_options[option_index].name, "timestamp") == 0 || + strcmp(long_options[option_index].name, "timestamp-request") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP Timestamp request messages.", o.mode2Ascii(o.getMode())); + o.setMode(ICMP); + o.setICMPType( ICMP_TSTAMP ); + } else if (strcmp(long_options[option_index].name, "information") == 0 || + strcmp(long_options[option_index].name, "information-request") == 0 ) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP Information request messages.", o.mode2Ascii(o.getMode())); + o.setMode(ICMP); + o.setICMPType( ICMP_TSTAMP ); + } else if (strcmp(long_options[option_index].name, "netmask") == 0 || + strcmp(long_options[option_index].name, "netmask-request") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP Information request messages.", o.mode2Ascii(o.getMode())); + o.setMode(ICMP); + o.setICMPType( ICMP_MASK ); + + +/* TCP/UDP OPTIONS ***********************************************************/ + /* TCP Sequence number */ + } else if (strcmp(long_options[option_index].name, "seq") == 0) { + if ( parse_u32(optarg, &aux32) != OP_SUCCESS ) + nping_fatal(QT_3, "Invalid TCP Sequence number. Value must be 0<=N<2^32."); + else + o.setTCPSequence( aux32 ); + /* TCP Flags */ + } else if (strcmp(long_options[option_index].name, "flags") == 0) { + /* CASE 1: User is a freak and supplied a numeric value directly */ + /* We initially parse it as an u32 so we give the proper error + * for values like 0x100. */ + if ( parse_u32(optarg, &aux32) == OP_SUCCESS ){ + if( meansRandom(optarg) ){ + aux8=get_random_u8(); + }else if(aux32>255){ + nping_fatal(QT_3, "Invalid TCP flag specification. Numerical values must be in the range [0,255]."); + }else{ + aux8=(u8)aux32; + } + if(aux8==0){ + o.unsetAllFlagsTCP(); + }else{ + if( aux8 & 0x80 ) + o.setFlagTCP( FLAG_CWR ); + if( aux8 & 0x40 ) + o.setFlagTCP( FLAG_ECN ); + if( aux8 & 0x20 ) + o.setFlagTCP( FLAG_URG ); + if( aux8 & 0x10 ) + o.setFlagTCP( FLAG_ACK ); + if( aux8 & 0x08 ) + o.setFlagTCP( FLAG_PSH ); + if( aux8 & 0x04 ) + o.setFlagTCP( FLAG_RST ); + if( aux8 & 0x02 ) + o.setFlagTCP( FLAG_SYN ); + if( aux8 & 0x01 ) + o.setFlagTCP( FLAG_FIN ); + } + /* CASE 2: User supplied a list of flags in the format "syn,ack,ecn" */ + }else if( contains(optarg, ",") ){ + if( ((strlen(optarg)+1)%4) !=0 ) + nping_fatal(QT_3, "Invalid format in --flag. Make sure you specify a comma-separated list that contains 3-character flag names (e.g: --flags syn,ack,psh)"); + + for( size_t f=0; f< strlen(optarg); f+=4 ){ + if(!strncasecmp((optarg+f), "CWR",3)){ o.setFlagTCP(FLAG_CWR); } + else if(!strncasecmp((optarg+f), "ECN",3)){ o.setFlagTCP(FLAG_ECN); } + else if(!strncasecmp((optarg+f), "ECE",3)){ o.setFlagTCP(FLAG_ECN); } + else if(!strncasecmp((optarg+f), "URG",3)){ o.setFlagTCP(FLAG_URG); } + else if(!strncasecmp((optarg+f), "ACK",3)){ o.setFlagTCP(FLAG_ACK); } + else if(!strncasecmp((optarg+f), "PSH",3)){ o.setFlagTCP(FLAG_PSH); } + else if(!strncasecmp((optarg+f), "RST",3)){ o.setFlagTCP(FLAG_RST); } + else if(!strncasecmp((optarg+f), "SYN",3)){ o.setFlagTCP(FLAG_SYN); } + else if(!strncasecmp((optarg+f), "FIN",3)){ o.setFlagTCP(FLAG_FIN); } + else if(!strncasecmp((optarg+f), "ALL",3)){ o.setAllFlagsTCP(); } + else if(!strncasecmp((optarg+f), "NIL",3)){ o.unsetAllFlagsTCP(); } + else{ + char wrongopt[4]; + memcpy(wrongopt, (optarg+f), 3); + wrongopt[3]='\0'; + nping_fatal(QT_3, "Invalid TCP flag specification: \"%s\"", wrongopt); + } + } + + /* CASE 3: User supplied flag initials in format "XYZ..." */ + }else{ + bool flag3_ok=false; + /* SPECIAL CASE: User entered exactly 3 chars so we don't know if + * only one flag was entered or three flags in format "XYZ..." */ + if( strlen(optarg) == 3 ){ + if(!strcasecmp(optarg, "CWR")){ o.setFlagTCP(FLAG_CWR); flag3_ok=true; } + else if(!strcasecmp(optarg, "ECN")){ o.setFlagTCP(FLAG_ECN); flag3_ok=true; } + else if(!strcasecmp(optarg, "ECE")){ o.setFlagTCP(FLAG_ECN); flag3_ok=true; } + else if(!strcasecmp(optarg, "URG")){ o.setFlagTCP(FLAG_URG); flag3_ok=true; } + else if(!strcasecmp(optarg, "ACK")){ o.setFlagTCP(FLAG_ACK); flag3_ok=true; } + else if(!strcasecmp(optarg, "PSH")){ o.setFlagTCP(FLAG_PSH); flag3_ok=true; } + else if(!strcasecmp(optarg, "RST")){ o.setFlagTCP(FLAG_RST); flag3_ok=true; } + else if(!strcasecmp(optarg, "SYN")){ o.setFlagTCP(FLAG_SYN); flag3_ok=true; } + else if(!strcasecmp(optarg, "FIN")){ o.setFlagTCP(FLAG_FIN); flag3_ok=true; } + else if(!strcasecmp(optarg, "ALL")){ o.setAllFlagsTCP(); flag3_ok=true; } + else if(!strcasecmp(optarg, "NIL")){ o.unsetAllFlagsTCP(); flag3_ok=true; } + else{ + flag3_ok=false; + } + }else if( strlen(optarg) == 0 ){ + o.unsetAllFlagsTCP(); + } + /* SPECIAL CASE: User supplied special flag "NONE" */ + if(!strcasecmp(optarg, "NONE") ){ o.unsetAllFlagsTCP(); flag3_ok=true; } + + /* User definitely supplied flag initials in format "XYZ..."*/ + if( flag3_ok==false ){ + for(size_t f=0; fparseICMPTimestamp(optarg, &aux32); + o.setICMPOriginateTimestamp(aux32); + /* ICMP Timestamp receive timestamp */ + } else if (strcmp(long_options[option_index].name, "icmp-recv-time") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP messages.", o.mode2Ascii(o.getMode())); + this->parseICMPTimestamp(optarg, &aux32); + o.setICMPReceiveTimestamp(aux32); + /* ICMP Timestamp transmit timestamp */ + } else if (strcmp(long_options[option_index].name, "icmp-trans-time") == 0) { + if ( o.issetMode() && o.getMode() != ICMP ) + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ICMP messages.", o.mode2Ascii(o.getMode())); + this->parseICMPTimestamp(optarg, &aux32); + o.setICMPTransmitTimestamp(aux32); + /* TODO: Add more relevant flags for different ICMP options */ + + +/* ARP/RARP OPTIONS **********************************************************/ + /* Operation code */ + } else if (strcmp(long_options[option_index].name, "arp-type") == 0 || + strcmp(long_options[option_index].name, "rarp-type") == 0 || + strcmp(long_options[option_index].name, "arp-code") == 0 || + strcmp(long_options[option_index].name, "rarp-code") == 0 || + strcmp(long_options[option_index].name, "arp-operation") == 0 || + strcmp(long_options[option_index].name, "arp-op") == 0 || + strcmp(long_options[option_index].name, "rarp-operation") == 0 || + strcmp(long_options[option_index].name, "rarp-op") == 0 ){ + if ( o.issetMode() && o.getMode() != ARP ){ + nping_fatal(QT_3,"You cannot specify mode %s if you want to send ARP messages.", o.mode2Ascii(o.getMode())); + }else if( !o.issetMode() ){ + o.setMode(ARP); + } + if( atoARPOpCode(optarg, &aux16) != OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid ARP type/operation code"); + }else{ + o.setARPOpCode(aux16); + } + /* ARP Sender MAC Address */ + } else if (strcmp(long_options[option_index].name, "arp-sender-mac") == 0 || + strcmp(long_options[option_index].name, "rarp-sender-mac") == 0 ){ + if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid ARP Sender MAC address."); + }else{ + o.setARPSenderHwAddr(auxmac); + } + /* ARP Sender IP Address */ + } else if (strcmp(long_options[option_index].name, "arp-sender-ip") == 0 || + strcmp(long_options[option_index].name, "rarp-sender-ip") == 0 ){ + if ( atoIP(optarg, &aux_ip4)!=OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid ARP Sender IP address."); + }else{ + o.setARPSenderProtoAddr(aux_ip4); + } + /* ARP Target MAC Address */ + } else if (strcmp(long_options[option_index].name, "arp-target-mac") == 0 || + strcmp(long_options[option_index].name, "rarp-target-mac") == 0 ){ + if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid ARP Target MAC address."); + }else{ + o.setARPTargetHwAddr(auxmac); + } + /* ARP Target IP Address */ + } else if (strcmp(long_options[option_index].name, "arp-target-ip") == 0 || + strcmp(long_options[option_index].name, "rarp-target-ip") == 0 ){ + if ( atoIP(optarg, &aux_ip4)!=OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid ARP Target IP address."); + }else{ + o.setARPTargetProtoAddr(aux_ip4); + } + + +/* ETHERNET OPTIONS **********************************************************/ + /* Destination MAC address */ + } else if (strcmp(long_options[option_index].name, "dest-mac") == 0 ){ + if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid Ethernet Destination MAC address."); + }else{ + o.setDestMAC(auxmac); + } + if( !o.issetSendPreference() ) + o.setSendPreference(PACKET_SEND_ETH_STRONG); + /* Source MAC address */ + } else if (strcmp(long_options[option_index].name, "source-mac") == 0 || + strcmp(long_options[option_index].name, "spoof-mac") == 0 ){ + if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){ + nping_fatal(QT_3, "Invalid Ethernet Source MAC address."); + }else{ + o.setSourceMAC(auxmac); + } + if( !o.issetSendPreference() ) + o.setSendPreference(PACKET_SEND_ETH_STRONG); + /* Ethernet type field */ + } else if (strcmp(long_options[option_index].name, "ethertype") == 0 || + strcmp(long_options[option_index].name, "ethtype") == 0 || + strcmp(long_options[option_index].name, "ether-type") == 0 ){ + if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){ + o.setEtherType(aux16); + }else if ( atoEtherType(optarg, &aux16) == OP_SUCCESS ){ + o.setEtherType(aux16); + }else{ + nping_fatal(QT_3, "Invalid Ethernet Type."); + } + if( !o.issetSendPreference() ) + o.setSendPreference(PACKET_SEND_ETH_STRONG); + + +/* IPv4 OPTIONS **************************************************************/ + /* Destination IP address. This is just another way to specify targets, + * provided for consistency with the rest of the parameters. */ + } else if (strcmp(long_options[option_index].name, "dest-ip") == 0 ){ + o.targets.addSpec( strdup(optarg) ); + /* IP Type of service*/ + } else if (strcmp(long_options[option_index].name, "tos") == 0 ){ + if ( parse_u8(optarg, &aux8) == OP_SUCCESS ){ + o.setTOS(aux8); + }else{ + nping_fatal(QT_3,"TOS option must be a number between 0 and 255 (inclusive)"); + } + /* IP Identification field */ + } else if (strcmp(long_options[option_index].name, "id") == 0 ){ + if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){ + o.setIdentification(aux16); + }else{ + nping_fatal(QT_3,"Identification must be a number between 0 and 65535 (inclusive)"); + } + /* Don't fragment bit */ + } else if (strcmp(long_options[option_index].name, "df") == 0 ){ + o.setDF(); + /* More fragments bit */ + } else if (strcmp(long_options[option_index].name, "mf") == 0 ){ + o.setMF(); + /* Reserved / Evil bit */ + } else if (strcmp(long_options[option_index].name, "evil") == 0 ){ + o.setRF(); + /* Time to live (hop-limit in IPv6) */ + } else if (strcmp(long_options[option_index].name, "ttl") == 0 || + strcmp(long_options[option_index].name, "hop-limit") == 0 ){ + /* IPv6 TTL field is named "hop limit" but has exactly the same + * function as in IPv4 so handling of that option should be the + * same in both versions. */ + if ( parse_u8(optarg, &aux8) == OP_SUCCESS ){ + o.setTTL(aux8); + }else{ + nping_fatal(QT_3,"%s option must be a number between 0 and 255 (inclusive)", + strcmp(long_options[option_index].name, "ttl")==0 ? "TTL" : "Hop Limit" + ); + } + /* TODO: At some point we may want to let users specify TTLs like "linux", + * "bsd" etc, so the default TTL for those systems is used. Check + * http://members.cox.net/~ndav1/self_published/TTL_values.html + * for more information */ + /* Set up a bad IP checksum */ + } else if (strcmp(long_options[option_index].name, "badsum-ip") == 0 ){ + o.enableBadsumIP(); + /* IP Options */ + } else if (strcmp(long_options[option_index].name, "ip-options") == 0 ){ + /* We need to know if options specification is correct so we perform + * a little test here, instead of waiting until the IPv4Header + * complains and fatal()s we just call parse_ip_options() ourselves. + * The call should fatal if something is wrong with user-supplied opts */ + int foo=0, bar=0; + u8 buffer[128]; + if( parse_ip_options(optarg, buffer, 128, &foo, &bar, errstr, sizeof(errstr)) < 0 ) + nping_fatal(QT_3, "Incorrect IP options specification."); + /* If we get here it's safe to store the options */ + o.setIPOptions( optarg ); + /* Maximum Transmission Unit */ + } else if (strcmp(long_options[option_index].name, "mtu") == 0 ){ + /* Special treatment for random here since the generated number must be n%8==0 */ + if(!strcasecmp("rand", optarg) || !strcasecmp("random", optarg)){ + aux16=get_random_u16(); /* We limit the random mtu to a max of 65535 */ + /* Make sure generated number is multiple of 8, adding a few units */ + if(aux16 > 8 ) + aux16-=(aux16%8); + else + aux16+=(8-(aux16%8)); + o.setMTU(aux16); + }else if ( (parse_u32(optarg, &aux32)==OP_SUCCESS) && aux32!=0 && aux32%8==0){ + o.setMTU(aux32); + }else{ + nping_fatal(QT_3,"MTU must be >0 and multiple of 8"); + } + + +/* IPv6 OPTIONS **************************************************************/ + /* IPv6 Traffic class */ + } else if (strcmp(long_options[option_index].name, "traffic-class") == 0 || + strcmp(long_options[option_index].name, "tc") == 0 ){ + if ( parse_u8(optarg, &aux8) == OP_SUCCESS ) + o.setTrafficClass(aux8); + else + nping_fatal(QT_3,"IPv6 Traffic Class must be a number between 0 and 255 (inclusive)"); + /* IPv6 Flow label */ + } else if (strcmp(long_options[option_index].name, "flow") == 0 ){ + if( meansRandom(optarg) ){ + o.setFlowLabel( get_random_u32()%1048575 ); /* Mod 2^20 so it doesn't exceed 20bits */ + }else if ( parse_u32(optarg, &aux32) == OP_SUCCESS ){ + if( aux32>1048575 ) + nping_fatal(QT_3, "IPv6 Flow Label cannot be greater than 1048575 "); + else + o.setFlowLabel(aux32); + }else{ + nping_fatal(QT_3,"IPv6 Flow Label must be a number between 0 and 1048575"); + } + + +/* PACKET PAYLOAD OPTIONS ***************************************************/ + /* Hexadecimal payload specification */ + } else if (strcmp(long_options[option_index].name, "data") == 0 ){ + u8 *tempbuff=NULL; + size_t len=0; + if( (tempbuff=parseBufferSpec(optarg, &len))==NULL) + nping_fatal(QT_3,"Invalid hex string specification\n"); + else{ + u8 *buff = (u8 *) safe_malloc(len); + memcpy(buff, tempbuff, len); + o.setPayloadBuffer(buff, len); + o.setPayloadType(PL_HEX); + } + /* Random payload */ + } else if (strcmp(long_options[option_index].name, "data-length") == 0 ){ + if( o.issetPayloadType() != false ) + nping_fatal(QT_3,"Only one type of payload may be selected."); + if( meansRandom(optarg) ){ + /* We do not generate more than Ethernet standard MTU */ + aux32 = 1 + get_random_u16() % (MAX_RANDOM_PAYLOAD-1); + }else if ( parse_u32(optarg, &aux32) != OP_SUCCESS ){ + nping_fatal(QT_3,"Invalid payload length specification"); + } + if ( aux32 > MAX_PAYLOAD_ALLOWED ) + nping_fatal(QT_3,"data-length must be a value between 0 and %d.", MAX_PAYLOAD_ALLOWED); + if ( aux32 > MAX_RECOMMENDED_PAYLOAD ) + nping_print(QT_3, "WARNING: Payload exceeds maximum recommended payload (%d)", MAX_RECOMMENDED_PAYLOAD); + o.setPayloadType(PL_RAND); + /* Allocate a buffer big enough to hold the desired payload */ + if( (auxbuff=(u8 *)safe_malloc(aux32)) == NULL ) + nping_fatal(QT_3,"Not enough memory to store payload."); + /* Generate random data and store the payload */ + get_random_bytes(auxbuff, aux32); + o.setPayloadBuffer(auxbuff, aux32); + /* ASCII string payload */ + } else if (strcmp(long_options[option_index].name, "data-string") == 0 ){ + o.setPayloadType(PL_STRING); + int plen=strlen(optarg); + if ( plen>MAX_PAYLOAD_ALLOWED ) + nping_fatal(QT_3,"data-string must be between 0 and %d characters.", MAX_PAYLOAD_ALLOWED); + if ( plen > MAX_RECOMMENDED_PAYLOAD ) + nping_print(QT_3, "WARNING: Payload exceeds maximum recommended payload (%d)", MAX_RECOMMENDED_PAYLOAD); + if( meansRandom(optarg) ){ + auxbuff=(u8*)strdup(getRandomTextPayload()); + plen=strlen((char*)auxbuff); + }else { + auxbuff=(u8*)safe_zalloc(plen); + memcpy(auxbuff, optarg, plen); + } + o.setPayloadBuffer((u8*)auxbuff, plen); + + +/* ECHO C/S MODE OPTIONS *****************************************************/ + } else if (strcmp(long_options[option_index].name, "echo-client")==0 || + strcmp(long_options[option_index].name, "ec")==0 ){ + o.setRoleClient(); + o.setEchoPassphrase(optarg); + } else if (strcmp(long_options[option_index].name, "echo-server")==0 || + strcmp(long_options[option_index].name, "es")==0 ){ + o.setRoleServer(); + o.setEchoPassphrase(optarg); + } else if (strcmp(long_options[option_index].name, "echo-port")==0 || + strcmp(long_options[option_index].name, "ep")==0 ){ + if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){ + if(aux16==0) + nping_fatal(QT_3, "Invalid echo port. Port can't be zero."); + else + o.setEchoPort( aux16 ); + }else{ + nping_fatal(QT_3, "Invalid echo port. Value must be 0= 10 * 1000 && tval_unit(optarg) == NULL) + nping_fatal(QT_3,"Since April 2010, the default unit for --delay is seconds, so your time of \"%s\" is %g seconds. Use \"%sms\" for %g milliseconds.", optarg, l / 1000.0, optarg, l / 1000.0); + o.setDelay(l); + /* Tx rate */ + } else if (strcmp(long_options[option_index].name, "rate") == 0 ){ + if (parse_u32(optarg, &aux32)==OP_SUCCESS){ + if(aux32==0){ + nping_fatal(QT_3,"Invalid rate supplied. Rate can never be zero."); + }else{ + /* Compute delay from rate: delay= 1000ms/rate*/ + aux32 = 1000 / aux32; + o.setDelay(aux32); + } + }else{ + nping_fatal(QT_3,"Invalid rate supplied. Rate must be a valid, positive integer"); + } + +/* MISC OPTIONS **************************************************************/ + } else if (strcmp(long_options[option_index].name, "privileged") == 0 ){ + o.setIsRoot(); + } else if (strcmp(long_options[option_index].name, "unprivileged") == 0 ){ + o.setIsRoot(0); + } else if (strcmp(long_options[option_index].name, "send-eth") == 0 ){ + o.setSendPreference(PACKET_SEND_ETH_STRONG); + } else if (strcmp(long_options[option_index].name, "send-ip") == 0 ){ + o.setSendPreference(PACKET_SEND_IP_STRONG); + } else if (strcmp(long_options[option_index].name, "bpf-filter") == 0 || strcmp(long_options[option_index].name, "filter") == 0){ + o.setBPFFilterSpec( optarg ); + if( o.issetDisablePacketCapture() && o.disablePacketCapture()==true ) + nping_warning(QT_2, "Warning: There is no point on specifying a BPF filter if you disable packet capture. BPF filter will be ignored."); + } else if (strcmp(long_options[option_index].name, "nsock-engine") == 0){ + if (nsock_set_default_engine(optarg) < 0) + nping_fatal(QT_3, "Unknown or non-available engine: %s", optarg); + /* Output Options */ + } else if (strcmp(long_options[option_index].name, "quiet") == 0 ){ + o.setVerbosity(-4); + o.setDebugging(0); + }else if (strcmp(long_options[option_index].name, "debug") == 0 ){ + o.setVerbosity(4); + o.setDebugging(9); + } + + break; /* case 0 */ + + +/* OPTIONS THAT CAN BE SPECIFIED AS A SINGLE CHARACTER ***********************/ + + case '4': /* IPv4 */ + o.setIPVersion(IP_VERSION_4); + break; /* case '4': */ + + case '6': /* IPv6 */ + o.setIPVersion(IP_VERSION_6); + break; /* case '6': */ + + case 'f': /* Fragment packets */ + if( o.issetMTU() == true ){ + nping_warning(QT_3,"WARNING: -f is irrelevant if an MTU has been previously specified"); + } + else{ + nping_print(DBG_1, "Setting default MTU=%d", DEFAULT_MTU_FOR_FRAGMENTATION); + o.setMTU( DEFAULT_MTU_FOR_FRAGMENTATION ); + } + break; + + case 'g': /* Source port */ + if( o.issetSourcePort() ){ + nping_fatal(QT_3,"Cannot specify source port twice."); + }else if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){ + o.setSourcePort(aux16); + if(aux16==0) + nping_warning(QT_1, "WARNING: a source port of zero may not work on all systems."); + }else{ + nping_fatal(QT_3,"Source port must be a number between 0 and 65535 (inclusive)"); + } + break; /* case 'g': */ + + case 'p': /* Destination port */ + /* Parse port spec */ + nping_getpts_simple(optarg, &portlist, &auxint); + if( portlist == NULL || auxint <= 0 ){ + nping_fatal(QT_3,"Invalid target ports specification."); + }else{ + o.setTargetPorts(portlist, auxint); + } + break; /* case 'p': */ + + case 'S': /* Source IP */ + if( o.getIPVersion() == IP_VERSION_6){ + struct sockaddr_storage sourceaddr; + struct sockaddr_in6 *source6=(struct sockaddr_in6 *)&sourceaddr; + memset(&sourceaddr, 0, sizeof(struct sockaddr_storage)); + struct in6_addr ipv6addr; + + /* Set random address */ + if( meansRandom(optarg) ){ + for(int i6=0; i6<16; i6++) + ipv6addr.s6_addr[i6]=get_random_u8(); + } + /* Set user supplied address (if we manage to resolve it) */ + else if ( atoIP(optarg, &sourceaddr, PF_INET6) != OP_SUCCESS){ + nping_fatal(QT_3, "Could not resolve source IPv6 address."); + }else{ + ipv6addr = source6->sin6_addr; + } + o.setIPv6SourceAddress(ipv6addr); + o.setSpoofSource(); + } + else{ + if( meansRandom(optarg) ) + while ( (aux_ip4.s_addr=get_random_u32()) == 0 ); + else if ( atoIP(optarg, &aux_ip4) != OP_SUCCESS) + nping_fatal(QT_3, "Could not resolve source IPv4 address."); + o.setIPv4SourceAddress(aux_ip4); + o.setSpoofSource(); + } + break; /* case 'S': */ + + case '?': + printUsage(); + exit(1); + break; /* case 'h': */ + + case 'h': /* Help */ + printUsage(); + exit(0); + break; /* case 'h': */ + + case 'V': /* Version */ + printVersion(); + exit(0); + break; /* case 'V': */ + + case 'c': /* Packet count */ + if( meansRandom(optarg) ){ + o.setPacketCount( get_random_u32()%1024 ); + }else if( parse_u32(optarg, &aux32) == OP_SUCCESS ){ + o.setPacketCount(aux32); + }else{ + nping_fatal(QT_3,"Packet count must be an integer greater than or equal to 0."); + } + break; /* case 'c': */ + + case 'e': /* Network interface */ + if(strlen(optarg)==0) + nping_fatal(QT_3,"Invalid network interface supplied. Interface name cannot be NULL."); + else + o.setDevice( strdup(optarg) ); + break; /* case 'e': */ + + case 'N': /* Don't capture packets */ + o.setDisablePacketCapture(true); + if( o.issetBPFFilterSpec() ) + nping_warning(QT_2, "Warning: A custom BPF filter was specified before disabling packet capture. BPF filter will be ignored."); + break; /* case 'N': */ + + case 'H': /* Hide sent packets */ + o.setShowSentPackets(false); + break; /* case 'H': */ + + case 'd': /* Debug mode */ + if (optarg){ + if (isdigit(optarg[0]) || optarg[0]=='-'){ + auxint = strtol( optarg, NULL, 10); + if ( ((auxint==0) && (optarg[0] != '0')) || auxint<0 || auxint > 9) + nping_fatal(QT_3,"Debugging level must be an integer between 0 and 9."); + else{ + o.setDebugging( auxint ); + /* When user specifies a debugging level, if no verbosity was specified, + * increase it automatically. If user specified a verbosity level, then leave + * it like it was. */ + if(o.issetVerbosity()==false) + o.setVerbosity( (auxint>4) ? 4 : auxint ); + } + }else { + const char *p; + o.increaseVerbosity(); + o.increaseDebugging(); + for (p = optarg != NULL ? optarg : ""; *p == 'd'; p++){ + o.increaseVerbosity(); + o.increaseDebugging(); + } + if (*p != '\0') + nping_fatal(QT_3,"Invalid argument to -d: \"%s\".", optarg); + } + }else{ + o.increaseVerbosity(); + o.increaseDebugging(); + } + break; /* case 'd': */ + + case 'v': /* Verbosity */ + if (optarg){ + if (isdigit(optarg[0]) || optarg[0]=='-'){ + auxint = strtol( optarg, NULL, 10); + if ( ((auxint==0) && (optarg[0] != '0')) || auxint<(-4) || auxint > 4) + nping_fatal(QT_3,"Verbosity level must be an integer between -4 and +4."); + else + o.setVerbosity( auxint ); + }else { + const char *p; + o.increaseVerbosity(); + for (p = optarg != NULL ? optarg : ""; *p == 'v'; p++) + o.increaseVerbosity(); + if (*p != '\0') + nping_fatal(QT_3,"Invalid argument to -v: \"%s\".", optarg); + } + }else{ + o.increaseVerbosity(); + } + break; /* case 'v': */ + + case 'q': /* Reduce verbosity */ + if (optarg){ + if (isdigit(optarg[0])){ + auxint = strtol( optarg, NULL, 10); + if ( ((auxint==0) && (optarg[0] != '0')) || auxint<0 || auxint > 4) + nping_fatal(QT_3,"You can only reduce verbosity from level 0 to level -4."); + else + o.setVerbosity( -auxint ); + }else { + const char *p; + o.decreaseVerbosity(); + for (p = optarg != NULL ? optarg : ""; *p == 'q'; p++) + o.decreaseVerbosity(); + if (*p != '\0') + nping_fatal(QT_3,"Invalid argument to -q: \"%s\".", optarg); + } + }else{ + o.decreaseVerbosity(); + } + break; /* case 'q': */ + + } /* End of switch */ + + } /* End of getopt while */ + + + /* Option --evil is implied when SCRIPT_KIDDIE has a non-zero value */ + script_kiddie = getenv("SCRIPT_KIDDIE"); + if (script_kiddie != NULL && strcmp(script_kiddie, "0") != 0) + o.setRF(); + + /* Now it's time to parse target host specifications. As nmap does, Nping + * treats everything getopt() can't parse as a host specification. At this + * point, var optind should point to the argv[] position that contains the + * first unparsed argument. User may specify multiple target hosts so to + * handle this, function grab_next_host_spec() returns the next target + * specification available. This function will be called until there are no + * more target hosts to parse (returned NULL). Once we have a spec, we use + * class NpingTargets, that stores the specs and will provide the targets + * through calls to getNextTarget(); + * */ + const char *next_spec=NULL; + while ( (next_spec= grab_next_host_spec(NULL, false, argc, (const char **) argv)) != NULL ) + o.targets.addSpec( (char *) next_spec ); + + return OP_SUCCESS; +} /* End of parseArguments() */ + + + + +/** Prints version information to stdout */ +void ArgParser::printVersion(void){ + printf("\n%s version %s ( %s )\n", NPING_NAME, NPING_VERSION, NPING_URL); + return; +} /* End of printVersion() */ + + + +/** Prints usage information to stdout */ +void ArgParser::printUsage(void){ + + printf("%s %s ( %s )\n" +"Usage: nping [Probe mode] [Options] {target specification}\n" +"\n" +"TARGET SPECIFICATION:\n" +" Targets may be specified as hostnames, IP addresses, networks, etc.\n" +" Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.*.1-24\n" +"PROBE MODES:\n" +" --tcp-connect : Unprivileged TCP connect probe mode.\n" +" --tcp : TCP probe mode.\n" +" --udp : UDP probe mode.\n" +" --icmp : ICMP probe mode.\n" +" --arp : ARP/RARP probe mode.\n" +" --tr, --traceroute : Traceroute mode (can only be used with \n" +" TCP/UDP/ICMP modes).\n" +"TCP CONNECT MODE:\n" +" -p, --dest-port : Set destination port(s).\n" +" -g, --source-port : Try to use a custom source port.\n" +"TCP PROBE MODE:\n" +" -g, --source-port : Set source port.\n" +" -p, --dest-port : Set destination port(s).\n" +" --seq : Set sequence number.\n" +" --flags : Set TCP flags (ACK,PSH,RST,SYN,FIN...)\n" +" --ack : Set ACK number.\n" +" --win : Set window size.\n" +" --badsum : Use a random invalid checksum. \n" +"UDP PROBE MODE:\n" +" -g, --source-port : Set source port.\n" +" -p, --dest-port : Set destination port(s).\n" +" --badsum : Use a random invalid checksum. \n" +"ICMP PROBE MODE:\n" +" --icmp-type : ICMP type.\n" +" --icmp-code : ICMP code.\n" +" --icmp-id : Set identifier.\n" +" --icmp-seq : Set sequence number.\n" +" --icmp-redirect-addr : Set redirect address.\n" +" --icmp-param-pointer : Set parameter problem pointer.\n" +" --icmp-advert-lifetime