summaryrefslogtreecommitdiffstats
path: root/nping
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nping/ArgParser.cc1823
-rw-r--r--nping/ArgParser.h83
-rw-r--r--nping/Crypto.cc279
-rw-r--r--nping/Crypto.h86
-rw-r--r--nping/EchoClient.cc1098
-rw-r--r--nping/EchoClient.h131
-rw-r--r--nping/EchoHeader.cc970
-rw-r--r--nping/EchoHeader.h331
-rw-r--r--nping/EchoServer.cc1567
-rw-r--r--nping/EchoServer.h131
-rw-r--r--nping/LICENSE3
-rw-r--r--nping/Makefile.in167
-rw-r--r--nping/NEPContext.cc552
-rw-r--r--nping/NEPContext.h213
-rw-r--r--nping/NpingOps.cc3134
-rw-r--r--nping/NpingOps.h650
-rw-r--r--nping/NpingTarget.cc1046
-rw-r--r--nping/NpingTarget.h261
-rw-r--r--nping/NpingTargets.cc387
-rw-r--r--nping/NpingTargets.h111
-rw-r--r--nping/ProbeMode.cc2342
-rw-r--r--nping/ProbeMode.h133
-rw-r--r--nping/common.cc65
-rw-r--r--nping/common.h69
-rw-r--r--nping/common_modified.cc782
-rw-r--r--nping/common_modified.h140
-rwxr-xr-xnping/config.guess1421
-rwxr-xr-xnping/config.sub1807
-rwxr-xr-xnping/configure7714
-rw-r--r--nping/configure.ac562
-rw-r--r--nping/docs/AUTHORS16
-rw-r--r--nping/docs/EchoProtoRFC.txt1158
-rw-r--r--nping/docs/leet-nping-ascii-art.txt18
-rw-r--r--nping/docs/nping-man.xml3575
-rw-r--r--nping/docs/nping-usage.txt120
-rw-r--r--nping/docs/nping-usage.xml2
-rw-r--r--nping/docs/nping.11797
-rw-r--r--nping/docs/npingmanhtml.xml13
-rw-r--r--nping/doxyfile239
-rw-r--r--nping/global_structures.h33
-rw-r--r--nping/nping-dev/Diagram1.diabin0 -> 5086 bytes
-rw-r--r--nping/nping-dev/EchoProtoRFC_v0.txt741
-rw-r--r--nping/nping-dev/NpingCommandLine.txt151
-rw-r--r--nping/nping-dev/NpingExamples.txt56
-rw-r--r--nping/nping-dev/NpingRequirements.txt165
-rw-r--r--nping/nping-dev/PacketDiff_RFC.txt538
-rw-r--r--nping/nping-dev/README40
-rw-r--r--nping/nping-dev/configFiles.txt12
-rwxr-xr-xnping/nping-dev/do_valgrind.sh2
-rw-r--r--nping/nping-dev/echo_proposal.txt222
-rw-r--r--nping/nping-dev/nping_logo.svg483
-rw-r--r--nping/nping-dev/packetDiagram.pngbin0 -> 44131 bytes
-rw-r--r--nping/nping-dev/pythonscripts/TemplateGettersSetters.txt25
-rwxr-xr-xnping/nping-dev/pythonscripts/TemplateNpingOps.txt45
-rw-r--r--nping/nping-dev/pythonscripts/addGettersSetters.py28
-rwxr-xr-xnping/nping-dev/pythonscripts/addManSectionEntry.py43
-rwxr-xr-xnping/nping-dev/pythonscripts/addNpingOpsAttr.py12
-rw-r--r--nping/nping-dev/pythonscripts/man-section-entry-template.xml25
-rw-r--r--nping/nping-dev/pythonscripts/man-section-template.xml34
-rw-r--r--nping/nping-dev/test/caps/tcpconnect_T1.capbin0 -> 2318 bytes
-rw-r--r--nping/nping-dev/test/caps/tcpconnect_T2.capbin0 -> 824 bytes
-rw-r--r--nping/nping-dev/test/caps/tcpconnect_T3.capbin0 -> 744 bytes
-rwxr-xr-xnping/nping-dev/test/test_nping.sh1526
-rw-r--r--nping/nping-dev/valgrind_supress.txt85
-rw-r--r--nping/nping.cc251
-rw-r--r--nping/nping.h363
-rw-r--r--nping/nping.spec54
-rw-r--r--nping/nping.vcxproj199
-rw-r--r--nping/nping_config.h.in154
-rw-r--r--nping/nping_winconfig.h90
-rw-r--r--nping/output.cc244
-rw-r--r--nping/output.h114
-rw-r--r--nping/stats.cc390
-rw-r--r--nping/stats.h210
-rw-r--r--nping/utils.cc438
-rw-r--r--nping/utils.h105
-rw-r--r--nping/utils_net.cc1941
-rw-r--r--nping/utils_net.h155
-rw-r--r--nping/winfix.cc264
-rw-r--r--nping/winfix.h35
80 files changed, 44269 insertions, 0 deletions
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; f<strlen(optarg); f++){
+ switch( optarg[f] ){
+ case 'C': case 'c': o.setFlagTCP(FLAG_CWR); break;
+ case 'E': case 'e': o.setFlagTCP(FLAG_ECN); break;
+ case 'U': case 'u': o.setFlagTCP(FLAG_URG); break;
+ case 'A': case 'a': o.setFlagTCP(FLAG_ACK); break;
+ case 'P': case 'p': o.setFlagTCP(FLAG_PSH); break;
+ case 'R': case 'r': o.setFlagTCP(FLAG_RST); break;
+ case 'S': case 's': o.setFlagTCP(FLAG_SYN); break;
+ case 'F': case 'f': o.setFlagTCP(FLAG_FIN); break;
+ default:
+ if( isdigit(optarg[f]) )
+ nping_fatal(QT_3, "Invalid TCP flag supplied (%c). If you want to specify flags using a number you must add prefix \"0x\"", optarg[f]);
+ else
+ nping_fatal(QT_3, "Invalid TCP flag supplied: %c", optarg[f]);
+
+ }
+ }
+ }
+ }
+ /* TCP Acknowledgement number */
+ } else if (strcmp(long_options[option_index].name, "ack") == 0) {
+ if ( parse_u32(optarg, &aux32) != OP_SUCCESS )
+ nping_fatal(QT_3, "Invalid TCP ACK number. Value must be 0<=N<2^32.");
+ else
+ o.setTCPAck( aux32 );
+ /* TCP Window size */
+ } else if (strcmp(long_options[option_index].name, "win") == 0) {
+ if ( parse_u16(optarg, &aux16) != OP_SUCCESS )
+ nping_fatal(QT_3, "Invalid TCP Window size. Value must be 0<=N<65535.");
+ else
+ o.setTCPWindow( aux16 );
+ /* Set a bad TCP checksum */
+ } else if (strcmp(long_options[option_index].name, "badsum") == 0) {
+ o.enableBadsum();
+
+/* ICMP OPTIONS **************************************************************/
+ /* ICMP Type */
+ } else if (strcmp(long_options[option_index].name, "icmp-type") == 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()));
+ /* User may have supplied type as a number */
+ if ( parse_u8(optarg, &aux8) == OP_SUCCESS )
+ o.setICMPType( aux8 );
+ /* Or maybe the supplied arg is a string that we can recognize */
+ else if ( atoICMPType(optarg, &aux8) == OP_SUCCESS )
+ o.setICMPType( aux8 );
+ /* Looks like user supplied a bogus value */
+ else
+ nping_fatal(QT_3, "Invalid ICMP Type. Value must be 0<=N<=255.");
+ /* Warn if ICMP Type is not RFC-compliant */
+ if( !isICMPType(aux8) )
+ nping_warning(QT_1, "Warning: Specified ICMP type (%d) is not RFC compliant.", aux8);
+ /* ICMP Code */
+ } else if (strcmp(long_options[option_index].name, "icmp-code") == 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()));
+ /* User may have supplied code as a number */
+ if ( parse_u8(optarg, &aux8) == OP_SUCCESS )
+ o.setICMPCode( aux8 );
+ /* Or maybe the supplied arg is a string that we can recognize */
+ else if ( atoICMPCode(optarg, &aux8) == OP_SUCCESS )
+ o.setICMPCode( aux8 );
+ /* Looks like user supplied a bogus value */
+ else
+ nping_fatal(QT_3, "Invalid ICMP Code. Value must be 0<=N<=255.");
+ /* ICMP Identification field */
+ } else if (strcmp(long_options[option_index].name, "icmp-id") == 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()));
+ if ( parse_u16(optarg, &aux16) == OP_SUCCESS )
+ o.setICMPIdentifier( aux16 );
+ else
+ nping_fatal(QT_3, "Invalid ICMP Identifier. Value must be 0<=N<2^16.");
+ /* ICMP Sequence number */
+ } else if (strcmp(long_options[option_index].name, "icmp-seq") == 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()));
+ if ( parse_u16(optarg, &aux16) == OP_SUCCESS )
+ o.setICMPSequence( aux16 );
+ else
+ nping_fatal(QT_3, "Invalid ICMP Sequence number. Value must be 0<=N<2^16.");
+ /* ICMP Redirect Address */
+ } else if (strcmp(long_options[option_index].name, "icmp-redirect-addr") == 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()));
+ if( meansRandom(optarg) ){
+ while ( (aux_ip4.s_addr=get_random_u32()) == 0 );
+ o.setICMPRedirectAddress( aux_ip4 );
+ }else{
+ if ( atoIP(optarg, &aux_ip4) != OP_SUCCESS)
+ nping_fatal(QT_3, "Could not resolve specified ICMP Redirect Address.");
+ else
+ o.setICMPRedirectAddress( aux_ip4 );
+ }
+ /* ICMP Parameter problem pointer */
+ } else if (strcmp(long_options[option_index].name, "icmp-param-pointer") == 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()));
+ if ( parse_u8(optarg, &aux8) == OP_SUCCESS )
+ o.setICMPParamProblemPointer( aux8 );
+ else
+ nping_fatal(QT_3, "Invalid ICMP Parameter problem pointer. Value must be 0<=N<=255..");
+ /* ICMP Router Advertisement lifetime */
+ } else if (strcmp(long_options[option_index].name, "icmp-advert-lifetime") == 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()));
+ if ( parse_u16(optarg, &aux16) == OP_SUCCESS )
+ o.setICMPRouterAdvLifetime( aux16 );
+ else
+ nping_fatal(QT_3, "Invalid ICMP Router advertisement lifetime. Value must be 0<=N<2^16..");
+ /* ICMP Router Advertisement entry */
+ } else if (strcmp(long_options[option_index].name, "icmp-advert-entry") == 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()));
+ /* Format should be "IPADDR,PREF": "192.168.10.99,31337" */
+ if( meansRandom(optarg) ){
+ while( (aux_ip4.s_addr=get_random_u32()) == 0);
+ o.addICMPAdvertEntry( aux_ip4, get_random_u32() );
+ }else{
+ struct in_addr aux_addr;
+ u32 aux_pref=0;
+ parseAdvertEntry(optarg, &aux_addr, &aux_pref); /* fatal()s on error */
+ o.addICMPAdvertEntry(aux_addr, aux_pref);
+ }
+ /* ICMP Timestamp originate timestamp */
+ } else if (strcmp(long_options[option_index].name, "icmp-orig-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.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<N<2^16.");
+ }
+ } else if (strcmp(long_options[option_index].name, "once")==0 ){
+ o.setOnce(true);
+ } else if (strcmp(long_options[option_index].name, "no-crypto")==0 ||
+ strcmp(long_options[option_index].name, "nc")==0 ){
+ o.doCrypto(false);
+ } else if (strcmp(long_options[option_index].name, "safe-payloads")==0 ){
+ o.echoPayload(false);
+ } else if (strcmp(long_options[option_index].name, "include-payloads")==0 ){
+ o.echoPayload(true);
+
+
+/* TIMING AND PERFORMANCE OPTIONS ********************************************/
+ /* Inter-packet delay */
+ } else if (strcmp(long_options[option_index].name, "delay") == 0 ){
+ if ( (l= tval2msecs(optarg)) == -1)
+ nping_fatal(QT_3,"Invalid delay supplied. Delay must be a valid, positive integer or floating point number.");
+ else if(l<0)
+ nping_fatal(QT_3,"Invalid delay supplied. Delays can never be negative.");
+ if (l >= 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 <port spec> : Set destination port(s).\n"
+" -g, --source-port <portnumber> : Try to use a custom source port.\n"
+"TCP PROBE MODE:\n"
+" -g, --source-port <portnumber> : Set source port.\n"
+" -p, --dest-port <port spec> : Set destination port(s).\n"
+" --seq <seqnumber> : Set sequence number.\n"
+" --flags <flag list> : Set TCP flags (ACK,PSH,RST,SYN,FIN...)\n"
+" --ack <acknumber> : Set ACK number.\n"
+" --win <size> : Set window size.\n"
+" --badsum : Use a random invalid checksum. \n"
+"UDP PROBE MODE:\n"
+" -g, --source-port <portnumber> : Set source port.\n"
+" -p, --dest-port <port spec> : Set destination port(s).\n"
+" --badsum : Use a random invalid checksum. \n"
+"ICMP PROBE MODE:\n"
+" --icmp-type <type> : ICMP type.\n"
+" --icmp-code <code> : ICMP code.\n"
+" --icmp-id <id> : Set identifier.\n"
+" --icmp-seq <n> : Set sequence number.\n"
+" --icmp-redirect-addr <addr> : Set redirect address.\n"
+" --icmp-param-pointer <pnt> : Set parameter problem pointer.\n"
+" --icmp-advert-lifetime <time> : Set router advertisement lifetime.\n"
+" --icmp-advert-entry <IP,pref> : Add router advertisement entry.\n"
+" --icmp-orig-time <timestamp> : Set originate timestamp.\n"
+" --icmp-recv-time <timestamp> : Set receive timestamp.\n"
+" --icmp-trans-time <timestamp> : Set transmit timestamp.\n"
+"ARP/RARP PROBE MODE:\n"
+" --arp-type <type> : Type: ARP, ARP-reply, RARP, RARP-reply.\n"
+" --arp-sender-mac <mac> : Set sender MAC address.\n"
+" --arp-sender-ip <addr> : Set sender IP address.\n"
+" --arp-target-mac <mac> : Set target MAC address.\n"
+" --arp-target-ip <addr> : Set target IP address.\n"
+"IPv4 OPTIONS:\n"
+" -S, --source-ip : Set source IP address.\n"
+" --dest-ip <addr> : Set destination IP address (used as an \n"
+" alternative to {target specification} ). \n"
+" --tos <tos> : Set type of service field (8bits).\n"
+" --id <id> : Set identification field (16 bits).\n"
+" --df : Set Don't Fragment flag.\n"
+" --mf : Set More Fragments flag.\n"
+" --evil : Set Reserved / Evil flag.\n"
+" --ttl <hops> : Set time to live [0-255].\n"
+" --badsum-ip : Use a random invalid checksum. \n"
+" --ip-options <R|S [route]|L [route]|T|U ...> : Set IP options\n"
+" --ip-options <hex string> : Set IP options\n"
+" --mtu <size> : Set MTU. Packets get fragmented if MTU is\n"
+" small enough.\n"
+"IPv6 OPTIONS:\n"
+" -6, --IPv6 : Use IP version 6.\n"
+" --dest-ip : Set destination IP address (used as an\n"
+" alternative to {target specification}).\n"
+" --hop-limit : Set hop limit (same as IPv4 TTL).\n"
+" --traffic-class <class> : : Set traffic class.\n"
+" --flow <label> : Set flow label.\n"
+"ETHERNET OPTIONS:\n"
+" --dest-mac <mac> : Set destination mac address. (Disables\n"
+" ARP resolution)\n"
+" --source-mac <mac> : Set source MAC address.\n"
+" --ether-type <type> : Set EtherType value.\n"
+"PAYLOAD OPTIONS:\n"
+" --data <hex string> : Include a custom payload.\n"
+" --data-string <text> : Include a custom ASCII text.\n"
+" --data-length <len> : Include len random bytes as payload.\n"
+"ECHO CLIENT/SERVER:\n"
+" --echo-client <passphrase> : Run Nping in client mode.\n"
+" --echo-server <passphrase> : Run Nping in server mode.\n"
+" --echo-port <port> : Use custom <port> to listen or connect.\n"
+" --no-crypto : Disable encryption and authentication.\n"
+" --once : Stop the server after one connection.\n"
+" --safe-payloads : Erase application data in echoed packets.\n"
+"TIMING AND PERFORMANCE:\n"
+ " Options which take <time> are in seconds, or append 'ms' (milliseconds),\n"
+" 's' (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m, 0.25h).\n"
+" --delay <time> : Adjust delay between probes.\n"
+" --rate <rate> : Send num packets per second.\n"
+"MISC:\n"
+" -h, --help : Display help information.\n"
+" -V, --version : Display current version number. \n"
+" -c, --count <n> : Stop after <n> rounds.\n"
+" -e, --interface <name> : Use supplied network interface.\n"
+" -H, --hide-sent : Do not display sent packets.\n"
+" -N, --no-capture : Do not try to capture replies.\n"
+" --privileged : Assume user is fully privileged.\n"
+" --unprivileged : Assume user lacks raw socket privileges.\n"
+" --send-eth : Send packets at the raw Ethernet layer.\n"
+" --send-ip : Send packets using raw IP sockets.\n"
+" --bpf-filter <filter spec> : Specify custom BPF filter.\n"
+"OUTPUT:\n"
+" -v : Increment verbosity level by one.\n"
+" -v[level] : Set verbosity level. E.g: -v4\n"
+" -d : Increment debugging level by one.\n"
+" -d[level] : Set debugging level. E.g: -d3\n"
+" -q : Decrease verbosity level by one.\n"
+" -q[N] : Decrease verbosity level N times\n"
+" --quiet : Set verbosity and debug level to minimum.\n"
+" --debug : Set verbosity and debug to the max level.\n"
+"EXAMPLES:\n"
+" nping scanme.nmap.org\n"
+" nping --tcp -p 80 --flags rst --ttl 2 192.168.1.1\n"
+" nping --icmp --icmp-type time --delay 500ms 192.168.254.254\n"
+" nping --echo-server \"public\" -e wlan0 -vvv \n"
+" nping --echo-client \"public\" echo.nmap.org --tcp -p1-1024 --flags ack\n"
+"\n"
+"SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES\n\n",
+NPING_NAME, NPING_VERSION, NPING_URL);
+
+} /* End of printUsage() */
+
+
+int ArgParser::parseAdvertEntry(char *str, struct in_addr *addr, u32 *pref){
+ char *aux=NULL;
+ struct in_addr auxIP;
+ u32 auxPref=0;
+ size_t len=0;
+ static char first[256];
+ static char last[256];
+ memset(first, 0, 256);
+ memset(last, 0, 256);
+
+ if (str==NULL || addr==NULL || pref==NULL)
+ return OP_FAILURE;
+
+ len =strlen(str);
+
+ /* I guess one can try to lookup something as short as a single char */
+ if ( len < strlen("a,1") )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: too short");
+ /* Im going to limit this to 255 chars. */
+ if( len > 255 )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: too long");
+
+ /* Let's find the comma */
+ aux=strstr(str, ",");
+
+ if(aux==NULL )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, missing comma delimiter");
+ if(aux==str)
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, comma cannot be placed at start");
+ if(aux>=str+len-1 )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, comma cannot be placed at the end");
+
+ /* Looks like at least the syntax is correct */
+ memcpy(first, str, aux-str);
+ memcpy(last, aux+1, len-(aux-str) );
+
+ if( atoIP(first, &auxIP) == OP_FAILURE )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: Unable to resolve %s", first);
+ if( isNumber_u32( last ) == false )
+ nping_fatal(QT_3, "Invalid Router Advertising Entry specification: %s is not a valid preference number", last);
+
+ auxPref=strtoul( last, NULL, 10);
+ *pref=auxPref;
+ *addr=auxIP;
+ return OP_SUCCESS;
+} /* End of parseAdvertEntry() */
+
+
+
+
+/* ALLOWED format:
+ *
+ * Full option name: destination-unreachable
+ * Four letters - three letters: dest-unr
+ * Initials: du
+ *
+ * In ICMP types that REQUEST something, the word "request" is always omitted.
+ * For example: Echo request should be specified as "echo" or "e",
+ * not "echo-request"/"echo-req"/"er"
+ *
+ * EXCEPTIONS. To avoid confusion:
+ * - Initials for "Timestamp" are "tm"
+ * - Initial for Traceroute are "tc"
+ * */
+int ArgParser::atoICMPType(char *opt, u8 *type){
+ if(type==NULL)
+ return OP_FAILURE;
+
+ if ( !strcasecmp(opt, "echo-reply") ||
+ !strcasecmp(opt, "echo-rep") ||
+ !strcasecmp(opt, "er") )
+ *type=0;
+ else if ( !strcasecmp(opt, "destination-unreachable") ||
+ !strcasecmp(opt, "dest-unr") ||
+ !strcasecmp(opt, "du") )
+ *type=3;
+ else if ( !strcasecmp(opt, "source-quench") ||
+ !strcasecmp(opt, "sour-que") ||
+ !strcasecmp(opt, "sq") )
+ *type=4;
+ else if ( !strcasecmp(opt, "redirect") ||
+ !strcasecmp(opt, "redi") ||
+ !strcasecmp(opt, "r") )
+ *type=5;
+ else if ( !strcasecmp(opt, "echo-request") || /* Ok, I'll also allow this */
+ !strcasecmp(opt, "echo") ||
+ !strcasecmp(opt, "e") )
+ *type=8;
+ else if ( !strcasecmp(opt, "router-advertisement") ||
+ !strcasecmp(opt, "rout-adv") ||
+ !strcasecmp(opt, "ra") )
+ *type=9;
+ else if ( !strcasecmp(opt, "router-solicitation") ||
+ !strcasecmp(opt, "rout-sol") ||
+ !strcasecmp(opt, "rs") )
+ *type=10;
+ else if ( !strcasecmp(opt, "time-exceeded") ||
+ !strcasecmp(opt, "time-exc") ||
+ !strcasecmp(opt, "te") )
+ *type=11;
+ else if ( !strcasecmp(opt, "parameter-problem") ||
+ !strcasecmp(opt, "para-pro") ||
+ !strcasecmp(opt, "pp") )
+ *type=12;
+ else if ( !strcasecmp(opt, "timestamp") ||
+ !strcasecmp(opt, "time") ||
+ !strcasecmp(opt, "tm") )
+ *type=13;
+ else if ( !strcasecmp(opt, "timestamp-reply") ||
+ !strcasecmp(opt, "time-rep") ||
+ !strcasecmp(opt, "tr") )
+ *type=14;
+ else if ( !strcasecmp(opt, "information") ||
+ !strcasecmp(opt, "info") ||
+ !strcasecmp(opt, "i") )
+ *type=15;
+ else if ( !strcasecmp(opt, "information-reply") ||
+ !strcasecmp(opt, "info-rep") ||
+ !strcasecmp(opt, "ir") )
+ *type=16;
+ else if ( !strcasecmp(opt, "mask-request") ||
+ !strcasecmp(opt, "mask") ||
+ !strcasecmp(opt, "m") )
+ *type=17;
+ else if ( !strcasecmp(opt, "mask-reply") ||
+ !strcasecmp(opt, "mask-rep") ||
+ !strcasecmp(opt, "mr") )
+ *type=18;
+ else if ( !strcasecmp(opt, "traceroute") ||
+ !strcasecmp(opt, "trace") ||
+ !strcasecmp(opt, "tc") )
+ *type=30;
+ else
+ return OP_FAILURE;
+
+/* TODO: They are not implemented but there are more types in
+ http://www.iana.org/assignments/icmp-parameters
+
+ 31 Datagram Conversion Error [RFC1475]
+ 32 Mobile Host Redirect [David Johnson]
+ 33 IPv6 Where-Are-You [Bill Simpson]
+ 34 IPv6 I-Am-Here [Bill Simpson]
+ 35 Mobile Registration Request [Bill Simpson]
+ 36 Mobile Registration Reply [Bill Simpson]
+ 37 Domain Name Request [RFC1788]
+ 38 Domain Name Reply [RFC1788]
+ 39 SKIP [Markson]
+ 40 Photuris [RFC2521]
+ 41 ICMP messages utilized by experimental [RFC4065]
+ mobility protocols such as Seamoby
+ 42-255 Reserved [JBP]
+
+*/
+ return OP_SUCCESS;
+} /* End of atoICMPType() */
+
+
+/* Names are taken from http://www.iana.org/assignments/icmp-parameters */
+/* ALLOWED format:
+ *
+ * Full option name: needs-fragmentation
+ * Four letters - three letters: need-fra
+ * Our own version (varies): frag
+ *
+ * In ICMP types that REQUEST something, the word "request" is always omitted.
+ * For example: Echo request should be specified as "echo" or "e",
+ * not "echo-request"/"echo-req"/"er"
+ *
+ * EXCEPTIONS. To avoid confusion:
+ * - Initials for "Timestamp" are "tm"
+ * - Initial for Traceroute are "tc"
+ * */
+int ArgParser::atoICMPCode(char *opt, u8 *code){
+
+ if(code==NULL || opt==NULL)
+ return OP_FAILURE;
+
+ /* Destination Unreachable */
+ if ( !strcasecmp(opt, "network-unreachable") ||
+ !strcasecmp(opt, "netw-unr") ||
+ !strcasecmp(opt, "net") ) /**/
+ *code=0;
+ else if ( !strcasecmp(opt, "host-unreachable") ||
+ !strcasecmp(opt, "host-unr") ||
+ !strcasecmp(opt, "host") )
+ *code=1;
+ else if ( !strcasecmp(opt, "protocol-unreachable") ||
+ !strcasecmp(opt, "prot-unr") ||
+ !strcasecmp(opt, "proto") )
+ *code=2;
+ else if ( !strcasecmp(opt, "port-unreachable") ||
+ !strcasecmp(opt, "port-unr") ||
+ !strcasecmp(opt, "port") )
+ *code=3;
+ else if ( !strcasecmp(opt, "needs-fragmentation") ||
+ !strcasecmp(opt, "need-fra") ||
+ !strcasecmp(opt, "frag") )
+ *code=4;
+ else if ( !strcasecmp(opt, "source-route-failed") ||
+ !strcasecmp(opt, "sour-rou") ||
+ !strcasecmp(opt, "routefail") )
+ *code=5;
+ else if ( !strcasecmp(opt, "network-unknown") ||
+ !strcasecmp(opt, "netw-unk") ||
+ !strcasecmp(opt, "net?") )
+ *code=6;
+ else if ( !strcasecmp(opt, "host-unknown") ||
+ !strcasecmp(opt, "host-unk") ||
+ !strcasecmp(opt, "host?") )
+ *code=7;
+ else if ( !strcasecmp(opt, "host-isolated") ||
+ !strcasecmp(opt, "host-iso") ||
+ !strcasecmp(opt, "isolated") )
+ *code=8;
+ else if ( !strcasecmp(opt, "network-prohibited") ||
+ !strcasecmp(opt, "netw-pro") ||
+ !strcasecmp(opt, "!net") )
+ *code=9;
+ else if ( !strcasecmp(opt, "host-prohibited") ||
+ !strcasecmp(opt, "host-pro") ||
+ !strcasecmp(opt, "!host") )
+ *code=10;
+ else if ( !strcasecmp(opt, "network-tos") ||
+ !strcasecmp(opt, "unreachable-network-tos") ||
+ !strcasecmp(opt, "netw-tos") ||
+ !strcasecmp(opt, "tosnet") )
+ /* Not to be confused with redirect-network-tos*/
+ *code=11;
+ else if ( !strcasecmp(opt, "host-tos") ||
+ !strcasecmp(opt, "unreachable-host-tos") ||
+ !strcasecmp(opt, "toshost") )
+ /* Not to be confused with redirect-network-tos*/
+ *code=12;
+ else if ( !strcasecmp(opt, "communication-prohibited") ||
+ !strcasecmp(opt, "comm-pro") ||
+ !strcasecmp(opt, "!comm") )
+ *code=13;
+ else if ( !strcasecmp(opt, "host-precedence-violation") ||
+ !strcasecmp(opt, "precedence-violation") ||
+ !strcasecmp(opt, "prec-vio") ||
+ !strcasecmp(opt, "violation") )
+ *code=14;
+ else if ( !strcasecmp(opt, "precedence-cutoff") ||
+ !strcasecmp(opt, "prec-cut") ||
+ !strcasecmp(opt, "cutoff") )
+ *code=15;
+
+ /* Redirect */
+ else if ( !strcasecmp(opt, "redirect-network") ||
+ !strcasecmp(opt, "redi-net") ||
+ !strcasecmp(opt, "net") )
+ /* "net" is the same as in Destination unreachable and there is no
+ * conflict because both codes use value 0 */
+ *code=0;
+ else if ( !strcasecmp(opt, "redirect-host") ||
+ !strcasecmp(opt, "redi-host") ||
+ !strcasecmp(opt, "host") )
+ /* "host" is the same as in Destination unreachable and there is no
+ * conflict because both codes use value 0 */
+ *code=1;
+ else if ( !strcasecmp(opt, "redirect-network-tos") ||
+ !strcasecmp(opt, "redi-ntos") ||
+ !strcasecmp(opt, "redir-ntos") )
+ *code=2;
+ else if ( !strcasecmp(opt, "redirect-host-tos") ||
+ !strcasecmp(opt, "redi-htos") ||
+ !strcasecmp(opt, "redir-htos") )
+ *code=3;
+
+ /* Router Advertisement */
+ else if ( !strcasecmp(opt, "normal-advertisement") ||
+ !strcasecmp(opt, "norm-adv") ||
+ !strcasecmp(opt, "normal") ||
+ !strcasecmp(opt, "zero") ||
+ !strcasecmp(opt, "default") ||
+ !strcasecmp(opt, "def") )
+ /* This one corresponds with "Normal router advertisement" but
+ * with the word "normal", can be reused for any other code as
+ * 0 is the default value if the code field is unused. */
+ *code=0;
+ else if ( !strcasecmp(opt, "not-route-common-traffic") ||
+ !strcasecmp(opt, "not-rou") ||
+ !strcasecmp(opt, "mobile-ip") ||
+ !strcasecmp(opt, "!route") ||
+ !strcasecmp(opt, "!commontraffic") )
+ *code=16;
+
+ /* Time Exceeded */
+ else if ( !strcasecmp(opt, "ttl-exceeded-in-transit") ||
+ !strcasecmp(opt, "ttl-exc") ||
+ !strcasecmp(opt, "ttl-zero") ||
+ !strcasecmp(opt, "ttl-transit") ||
+ !strcasecmp(opt, "ttl-0") ||
+ !strcasecmp(opt, "!ttl") )
+ *code=0;
+ else if ( !strcasecmp(opt, "fragment-reassembly-time-exceeded") ||
+ !strcasecmp(opt, "frag-exc") ||
+ !strcasecmp(opt, "frag-time") ||
+ !strcasecmp(opt, "!timefrag") ||
+ !strcasecmp(opt, "!frag") )
+ *code=1;
+
+ /* Parameter problem */
+ else if ( !strcasecmp(opt, "pointer-indicates-error") ||
+ !strcasecmp(opt, "poin-ind") ||
+ !strcasecmp(opt, "pointer-indicates") ||
+ !strcasecmp(opt, "pointer") ||
+ !strcasecmp(opt, "pointertells") )
+ *code=0;
+ else if ( !strcasecmp(opt, "missing-required-option") ||
+ !strcasecmp(opt, "miss-req") ||
+ !strcasecmp(opt, "miss-option") ||
+ !strcasecmp(opt, "option-missing") ||
+ !strcasecmp(opt, "missing-option") ||
+ !strcasecmp(opt, "!option") )
+ *code=1;
+ else if ( !strcasecmp(opt, "bad-length") ||
+ !strcasecmp(opt, "bad-len") ||
+ !strcasecmp(opt, "badlen") ||
+ !strcasecmp(opt, "badlength") ||
+ !strcasecmp(opt, "!len") )
+ *code=2;
+
+ /* ICMP Security Failures Messages (Experimental) */
+ else if ( !strcasecmp(opt, "bad-spi") ||
+ !strcasecmp(opt, "badspi") ||
+ !strcasecmp(opt, "!spi") )
+ *code=0;
+ else if ( !strcasecmp(opt, "authentication-failed") ||
+ !strcasecmp(opt, "auth-fai") ||
+ !strcasecmp(opt, "auth-failed") ||
+ !strcasecmp(opt, "authfail") ||
+ !strcasecmp(opt, "!auth") )
+ *code=1;
+ else if ( !strcasecmp(opt, "decompression-failed") ||
+ !strcasecmp(opt, "deco-fai") ||
+ !strcasecmp(opt, "decom-failed") ||
+ !strcasecmp(opt, "!decompress") ||
+ !strcasecmp(opt, "!decompression") )
+ *code=2;
+ else if ( !strcasecmp(opt, "decryption-failed") ||
+ !strcasecmp(opt, "decr-fai") ||
+ !strcasecmp(opt, "decrypt-failed") ||
+ !strcasecmp(opt, "!decrypt") ||
+ !strcasecmp(opt, "!decryption") )
+ *code=3;
+ else if ( !strcasecmp(opt, "need-authentication") ||
+ !strcasecmp(opt, "need-aut") ||
+ !strcasecmp(opt, "need-auth") ||
+ !strcasecmp(opt, "auth-needed") ||
+ !strcasecmp(opt, "!auth") ||
+ !strcasecmp(opt, "") )
+ *code=4;
+ else if ( !strcasecmp(opt, "need-authorization") ||
+ !strcasecmp(opt, "need-author") ||
+ !strcasecmp(opt, "authorization-needed") ||
+ !strcasecmp(opt, "author-needed") ||
+ !strcasecmp(opt, "!author") ||
+ !strcasecmp(opt, "!authorization") )
+ *code=5;
+/*
+ else if ( !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") )
+ *code=;
+*/
+ else
+ return OP_FAILURE;
+
+ return OP_SUCCESS;
+} /* End of atoICMPCode() */
+
+
+
+/* Same as atoICMPCode() but for ARP operation codes */
+int ArgParser::atoARPOpCode(char *opt, u16 *code){
+
+ if(code==NULL || opt==NULL)
+ return OP_FAILURE;
+
+ if ( !strcasecmp(opt, "arp-request") ||
+ !strcasecmp(opt, "arp") ||
+ !strcasecmp(opt, "a") ) /**/
+ *code=1;
+ else if ( !strcasecmp(opt, "arp-reply") ||
+ !strcasecmp(opt, "arp-rep") ||
+ !strcasecmp(opt, "ar") )
+ *code=2;
+ else if ( !strcasecmp(opt, "rarp-request") ||
+ !strcasecmp(opt, "rarp") ||
+ !strcasecmp(opt, "r") )
+ *code=3;
+ else if ( !strcasecmp(opt, "rarp-reply") ||
+ !strcasecmp(opt, "rarp-rep") ||
+ !strcasecmp(opt, "rr") )
+ *code=4;
+ else if ( !strcasecmp(opt, "drarp-request") ||
+ !strcasecmp(opt, "drarp") ||
+ !strcasecmp(opt, "d") )
+ *code=5;
+ else if ( !strcasecmp(opt, "drarp-reply") ||
+ !strcasecmp(opt, "drarp-rep") ||
+ !strcasecmp(opt, "dr") )
+ *code=6;
+ else if ( !strcasecmp(opt, "drarp-error") ||
+ !strcasecmp(opt, "drarp-err") ||
+ !strcasecmp(opt, "de") )
+ *code=7;
+ else if ( !strcasecmp(opt, "inarp-request") ||
+ !strcasecmp(opt, "inarp") ||
+ !strcasecmp(opt, "i") ) /**/
+ *code=8;
+ else if ( !strcasecmp(opt, "inarp-reply") ||
+ !strcasecmp(opt, "inarp-rep") ||
+ !strcasecmp(opt, "ir") ) /**/
+ *code=9;
+ else if ( !strcasecmp(opt, "arp-nak") ||
+ !strcasecmp(opt, "an") )
+ *code=10;
+
+/*
+ else if ( !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") )
+ *code=;
+*/
+ else
+ return OP_FAILURE;
+
+ return OP_SUCCESS;
+} /* End of atoARPOpCode() */
+
+
+
+
+int ArgParser::atoEtherType(char *opt, u16 *type){
+ if(type==NULL || opt==NULL)
+ return OP_FAILURE;
+
+ if ( !strcasecmp(opt, "ip") ||
+ !strcasecmp(opt, "ipv4") ||
+ !strcasecmp(opt, "4") ) /**/
+ *type=0x0800;
+ else if ( !strcasecmp(opt, "arp") )
+ *type=0x0806;
+ else if ( !strcasecmp(opt, "frame-relay") ||
+ !strcasecmp(opt, "frelay") ||
+ !strcasecmp(opt, "fr") )
+ *type=0x0808;
+ else if ( !strcasecmp(opt, "ppp") )
+ *type=0x880B;
+ else if ( !strcasecmp(opt, "gsmp") )
+ *type=0x880C;
+ else if ( !strcasecmp(opt, "rarp") )
+ *type=0x8035;
+ else if ( !strcasecmp(opt, "ipv6") ||
+ !strcasecmp(opt, "6") ) /**/
+ *type=0x86DD;
+ else if ( !strcasecmp(opt, "mpls") )
+ *type=0x8847;
+ else if ( !strcasecmp(opt, "mps-ual") ||
+ !strcasecmp(opt, "mps") )
+ *type=0x8848;
+ else if ( !strcasecmp(opt, "mcap") )
+ *type=0x8861;
+ else if ( !strcasecmp(opt, "pppoe-discovery")||
+ !strcasecmp(opt, "pppoe-d") )
+ *type=0x8863;
+ else if ( !strcasecmp(opt, "pppoe-session")||
+ !strcasecmp(opt, "pppoe-s") )
+ *type=0x8864;
+ else if ( !strcasecmp(opt, "ctag") )
+ *type=0x8100;
+ else if ( !strcasecmp(opt, "epon") )
+ *type=0x8808;
+ else if ( !strcasecmp(opt, "pbnac") )
+ *type=0x888E;
+ else if ( !strcasecmp(opt, "stag") )
+ *type=0x88A8;
+ else if ( !strcasecmp(opt, "ethexp1") )
+ *type=0x88B5;
+ else if ( !strcasecmp(opt, "ethexp2") )
+ *type=0x88B6;
+ else if ( !strcasecmp(opt, "ethoui") )
+ *type=0x88B7;
+ else if ( !strcasecmp(opt, "preauth") )
+ *type=0x88C7;
+ else if ( !strcasecmp(opt, "lldp") )
+ *type=0x88CC;
+ else if ( !strcasecmp(opt, "macsec") ||
+ !strcasecmp(opt, "mac-sec") ||
+ !strcasecmp(opt, "mac-security") )
+ *type=0x88E5;
+ else if ( !strcasecmp(opt, "mvrp") )
+ *type=0x88F5;
+ else if ( !strcasecmp(opt, "mmrp") )
+ *type=0x88F6;
+ else if ( !strcasecmp(opt, "frrr") )
+ *type=0x890D;
+/*
+ else if ( !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") ||
+ !strcasecmp(opt, "") )
+ *type=;
+*/
+ else
+ return OP_FAILURE;
+
+ return OP_SUCCESS;
+
+} /* End of atoEtherType() */
+
+
+
+
+int ArgParser::parseICMPTimestamp(char *optarg, u32 *dst){
+
+long diff=0;
+
+ if(optarg==NULL || dst==NULL)
+ nping_fatal(QT_3, "parseICMPTimestamp(): NULL pointer supplied.");
+
+ if( meansRandom(optarg) ){
+ while( (*dst=get_random_u32()) == 0);
+ }
+ else if( !strncmp("now-", optarg, 4) ){
+ if ( (diff= tval2msecs(optarg+4)) < 0 )
+ nping_fatal(QT_3,"You must specify a valid time value after now- (e.g. 1000, 2s, 25m, etc.)");
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if( ((((u32)now.tv_sec)%86400)*1000) < (u32)diff )
+ nping_fatal(QT_3,"Value is %s is too high for current time.", optarg+4 );
+ else
+ *dst= ((((u32)now.tv_sec)%86400)*1000) - diff;
+ }
+ else if( !strncmp("now+", optarg, 4) ) {
+ if ( (diff= tval2msecs(optarg+4)) < 0 )
+ nping_fatal(QT_3,"You must specify a valid time value after now+ (e.g. 1000, 2s, 25m, etc.)");
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ if( ((((u32)now.tv_sec)%86400)*1000) + diff > 0xFFFFFFFF )
+ nping_fatal(QT_3,"Value is %s is too high for current time.", optarg+4 );
+ else
+ *dst= ((((u32)now.tv_sec)%86400)*1000) + diff;
+ }
+ else if( !strcmp("now", optarg) ) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
+ *dst = ((((u32)now.tv_sec)%86400)*1000);
+ }
+ else {
+ if ( (diff= tval2msecs(optarg)) == -1)
+ nping_fatal(QT_3,"Invalid time supplied");
+ else
+ *dst=diff;
+ }
+
+ return OP_SUCCESS;
+} /* End of parseICMPTimestamp() */
diff --git a/nping/ArgParser.h b/nping/ArgParser.h
new file mode 100644
index 0000000..dd89dc4
--- /dev/null
+++ b/nping/ArgParser.h
@@ -0,0 +1,83 @@
+
+/***************************************************************************
+ * ArgParser.h -- 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/
+ *
+ ***************************************************************************/
+
+#ifndef NPING_ARGPARSER_H
+#define NPING_ARGPARSER_H
+class ArgParser {
+
+ public:
+ ArgParser();
+ ~ArgParser();
+ int parseArguments(int argc, char *argv[]);
+
+ void printVersion(void);
+ void printUsage(void);
+ int parseAdvertEntry(char *str, struct in_addr *addr, u32 *pref);
+ int atoICMPType(char *opt, u8 *type);
+ int atoICMPCode(char *opt, u8 *code);
+ int atoARPOpCode(char *opt, u16 *code);
+ int atoEtherType(char *opt, u16 *type);
+ int parseICMPTimestamp(char *optarg, u32 *dst);
+
+}; /* End of class ArgParser*/
+#endif // NPING_ARGPARSER_H
diff --git a/nping/Crypto.cc b/nping/Crypto.cc
new file mode 100644
index 0000000..ab41175
--- /dev/null
+++ b/nping/Crypto.cc
@@ -0,0 +1,279 @@
+
+/***************************************************************************
+ * Crypto.cc -- The Crypto Class contains miscellaneous methods and helpers*
+ * that may be used to provide properties such as authentication, integrity*
+ * or confidentiality. *
+ * *
+ ***********************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 "Crypto.h"
+#include "output.h"
+#include "NpingOps.h"
+
+#ifdef HAVE_OPENSSL
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
+#define HAVE_OPAQUE_EVP_PKEY 1
+#else
+#define EVP_MD_CTX_new EVP_MD_CTX_create
+#define EVP_MD_CTX_free EVP_MD_CTX_destroy
+#define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_cleanup
+#endif
+
+#endif /* HAVE_OPENSSL */
+
+extern NpingOps o;
+
+Crypto::Crypto(){
+ this->reset();
+} /* End of Crypto constructor */
+
+
+Crypto::~Crypto(){
+
+} /* End of Crypto destructor */
+
+
+/** Sets every attribute to its default value. */
+void Crypto::reset() {
+
+} /* End of reset() */
+
+
+int Crypto::hmac_sha256(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len){
+
+ #ifdef HAVE_OPENSSL
+ if( o.doCrypto() ){
+ u8 result[EVP_MAX_MD_SIZE];
+ memset(result, 0, EVP_MAX_MD_SIZE);
+ unsigned int result_len;
+ HMAC(EVP_sha256(), key, (int)key_len, inbuff, (int)inlen, result, &result_len);
+ memcpy(dst_buff, result, 256/8);
+ return OP_SUCCESS;
+ }
+ #endif
+ /* Set a bogus sum: all zero */
+ memset(dst_buff, 0, HMAC_SHA256_CODE_LEN);
+ return OP_SUCCESS;
+} /* End of hmac_sha256() */
+
+
+int Crypto::aes128_cbc_encrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len, u8 *iv){
+ nping_print(DBG_4, "%s(%p, %lu, %p, %p, %lu, %p)", __func__, inbuff, (unsigned long)inlen, dst_buff, key, (unsigned long)key_len, iv);
+ if(inbuff==NULL || dst_buff==NULL || key==NULL || iv==NULL)
+ return OP_FAILURE;
+ if( ((inlen%AES_BLOCK_SIZE)!=0) || key_len<AES_KEY_SIZE)
+ return OP_FAILURE;
+
+ #ifdef HAVE_OPENSSL
+ if( o.doCrypto() ){
+ int flen=0, flen2=0;
+ #if HAVE_OPAQUE_EVP_PKEY
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ #else
+ EVP_CIPHER_CTX stack_ctx;
+ EVP_CIPHER_CTX *ctx = &stack_ctx;
+ EVP_CIPHER_CTX_init(ctx);
+ #endif
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ int result=OP_SUCCESS;
+ if( EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){
+ nping_print(DBG_4, "EVP_EncryptInit() failed");
+ result=OP_FAILURE;
+ }else if( EVP_EncryptUpdate(ctx, dst_buff, &flen, inbuff, (int)inlen)==0 ){
+ nping_print(DBG_4, "EVP_EncryptUpdate() failed");
+ result=OP_FAILURE;
+ }else if( EVP_EncryptFinal(ctx, dst_buff+flen, &flen2)==0 ){
+ nping_print(DBG_4, "EVP_EncryptFinal() failed");
+ result=OP_FAILURE;
+ }
+ EVP_CIPHER_CTX_free(ctx);
+ return result;
+ }
+ #endif
+ /* Do not encrypt, just set the plaintext */
+ for(size_t i=0; i<inlen; i++)
+ dst_buff[i]=inbuff[i];
+ return OP_SUCCESS;
+} /* End of aes128_cbc_encrypt() */
+
+
+int Crypto::aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len, u8 *iv){
+ nping_print(DBG_4, "%s(%p, %lu, %p, %p, %lu, %p)", __func__, inbuff, (unsigned long)inlen, dst_buff, key, (unsigned long)key_len, iv);
+ if(inbuff==NULL || dst_buff==NULL || key==NULL || iv==NULL)
+ return OP_FAILURE;
+ if( ((inlen%AES_BLOCK_SIZE)!=0) || key_len<AES_KEY_SIZE)
+ return OP_FAILURE;
+
+ #ifdef HAVE_OPENSSL
+ if( o.doCrypto() ){
+ int flen1=0, flen2=0;
+ #if HAVE_OPAQUE_EVP_PKEY
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ #else
+ EVP_CIPHER_CTX stack_ctx;
+ EVP_CIPHER_CTX *ctx = &stack_ctx;
+ EVP_CIPHER_CTX_init(ctx);
+ #endif
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
+ int result=OP_SUCCESS;
+ if( EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){
+ nping_print(DBG_4, "EVP_DecryptInit() failed");
+ result=OP_FAILURE;
+ }else if( EVP_DecryptUpdate(ctx, dst_buff, &flen1, inbuff, (int)inlen)==0 ){
+ nping_print(DBG_4, "EVP_DecryptUpdate() failed");
+ result=OP_FAILURE;
+ }else if( EVP_DecryptFinal(ctx, dst_buff+flen1, &flen2)==0 ){
+ nping_print(DBG_4, "OpenSSL bug: it says EVP_DecryptFinal() failed when it didn't (%s).",
+ ERR_error_string(ERR_peek_last_error(), NULL));
+ /* We do not return OP_FAILURE in this case because the
+ * EVP_DecryptFinal() function seems to be buggy and fails when it shouldn't.
+ * We are passing a buffer whose length is multiple of the AES block
+ * size, we've disable padding, and still, the call fails.
+ * The call to EVP_DecryptUpdate() says we've decrypted all blocks but
+ * the last one and then EVP_DecryptFinal says we have decrypted nothing.
+ * However I've tested this for hours and everything works fine. The
+ * full buffer is decrypted correctly, from the first to the last byte,
+ * so we return OP_SUCCESS even if OpenSSL says the opposite. */
+
+ /* NOTE for developers debugging memory issues with Valgrind:
+ * None of these seems to free OpenSSL's internal error structures.
+ * Valgrind currently reports things like:
+ ==12849== 592 bytes in 1 blocks are still reachable in loss record 7 of 9
+ ==12849== at 0x4C284A8: malloc (vg_replace_malloc.c:236)
+ ==12849== by 0x531BF21: CRYPTO_malloc (in /lib/libcrypto.so.0.9.8)
+ ==12849== by 0x537F25D: ERR_get_state (in /lib/libcrypto.so.0.9.8)
+ ==12849== by 0x537E7BE: ERR_put_error (in /lib/libcrypto.so.0.9.8)
+ ==12849== by 0x5381EB0: EVP_DecryptFinal_ex (in /lib/libcrypto.so.0.9.8)
+ ==12849== by 0x429A49: Crypto::aes128_cbc_decrypt(unsigned char*...
+ ==12849== by 0x41ABBA: EchoHeader::decrypt(unsigned char*, unsign...
+ */
+ //ERR_clear_error();
+ //ERR_free_strings();
+ //ERR_pop_to_mark();
+ }
+ EVP_CIPHER_CTX_free(ctx);
+ return result;
+ }
+ #endif
+ /* Do not decrypt, just leave the ciphertext */
+ for(size_t i=0; i<inlen; i++)
+ dst_buff[i]=inbuff[i];
+ return OP_SUCCESS;
+} /* End of aes128_cbc_decrypt() */
+
+
+int Crypto::generateNonce(u8 *dst_buff, size_t bufflen){
+ nping_print(DBG_4, "%s()", __func__);
+ if(dst_buff==NULL || bufflen<=0)
+ return OP_FAILURE;
+ #ifdef HAVE_OPENSSL
+ // Get cryptographically secure random data from OpenSSL
+ // @todo TODO finish this.
+ get_random_bytes(dst_buff, bufflen); /* Provided by nbase */
+ #else
+ get_random_bytes(dst_buff, bufflen); /* Provided by nbase */
+ #endif
+ return OP_SUCCESS;
+} /* End of generateNonce() */
+
+
+#define TIMES_KEY_DERIVATION 1000
+u8 *Crypto::deriveKey(const u8 *from, size_t fromlen, size_t *final_len){
+ nping_print(DBG_4, "%s()", __func__);
+ if(from==NULL || fromlen==0)
+ return NULL;
+
+ #ifdef HAVE_OPENSSL
+ if( o.doCrypto() ){
+ static u8 hash[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)];
+ static u8 next[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)];
+ unsigned int lastlen;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+
+ if( EVP_MD_size(EVP_sha256()) != SHA256_HASH_LEN )
+ nping_fatal(QT_2, "OpenSSL is broken. SHA256 len is %d\n", EVP_MD_size(EVP_sha256()) );
+
+ /* Compute the SHA256 hash of the supplied buffer */
+ EVP_DigestInit(ctx, EVP_sha256());
+ EVP_DigestUpdate(ctx, from, fromlen);
+ EVP_DigestFinal(ctx, hash, &lastlen);
+
+ /* Now compute the 1000th hash of that hash */
+ for(int i=0; i<TIMES_KEY_DERIVATION; i++){
+ EVP_MD_CTX_init(ctx);
+ EVP_DigestInit(ctx, EVP_sha256());
+ EVP_DigestUpdate(ctx, hash, SHA256_HASH_LEN);
+ EVP_DigestFinal(ctx, next, &lastlen);
+ memcpy(hash, next, SHA256_HASH_LEN);
+ }
+ if(final_len!=NULL)
+ *final_len=SHA256_HASH_LEN;
+
+ EVP_MD_CTX_free(ctx);
+ return hash;
+ }
+ #endif
+ static u8 zerohash[SHA256_HASH_LEN];
+ memset(zerohash, 0, SHA256_HASH_LEN);
+ if(final_len!=NULL)
+ *final_len=SHA256_HASH_LEN;
+ return zerohash;
+
+} /* End of deriveKey() */
diff --git a/nping/Crypto.h b/nping/Crypto.h
new file mode 100644
index 0000000..3245fdd
--- /dev/null
+++ b/nping/Crypto.h
@@ -0,0 +1,86 @@
+
+/***************************************************************************
+ * Crypto.h -- The Crypto Class contains miscellaneous methods and helpers *
+ * that may be used to provide properties such as authentication, integrity*
+ * or confidentiality. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__ 1
+#include "nping.h"
+
+#define HMAC_SHA256_CODE_LEN 32
+#define AES_BLOCK_SIZE 16
+#define AES_KEY_SIZE 16
+#define SHA256_HASH_LEN 32
+
+class Crypto {
+
+ public:
+
+ Crypto();
+ ~Crypto();
+ void reset();
+
+ static int hmac_sha256(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len);
+ static int aes128_cbc_encrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len, u8 *iv);
+ static int aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key, size_t key_len, u8 *iv);
+ static int generateNonce(u8 *dst_buff, size_t bufflen);
+ static u8 *deriveKey(const u8 *from, size_t fromlen, size_t *final_len);
+};
+
+#endif /* __CRYPTO_H__ */
diff --git a/nping/EchoClient.cc b/nping/EchoClient.cc
new file mode 100644
index 0000000..549f592
--- /dev/null
+++ b/nping/EchoClient.cc
@@ -0,0 +1,1098 @@
+
+/***************************************************************************
+ * EchoClient.cc -- *
+ * *
+ ***********************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 "EchoClient.h"
+#include "EchoHeader.h"
+#include "output.h"
+#include "NEPContext.h"
+#include "NpingOps.h"
+#include "nsock.h"
+#include "Crypto.h"
+
+extern NpingOps o;
+extern EchoClient ec;
+
+
+EchoClient::EchoClient() {
+ this->reset();
+} /* End of EchoClient constructor */
+
+
+EchoClient::~EchoClient() {
+ this->reset();
+} /* End of EchoClient destructor */
+
+
+/** Sets every attribute to its default value- */
+void EchoClient::reset() {
+ memset(&this->srvaddr4, 0, sizeof(struct sockaddr_in));
+ memset(&this->srvaddr6, 0, sizeof(struct sockaddr_in6));
+ memset(this->lasthdr, 0, MAX_NEP_PACKET_LENGTH);
+ this->readbytes=0;
+ this->af=AF_INET;
+} /* End of reset() */
+
+
+/** Closes current connection and destroys Nsock handlers */
+int EchoClient::cleanup(){
+ this->probe.cleanup();
+ return OP_SUCCESS;
+} /* End of cleanup() */
+
+
+/** This is the main method, the boss of it all. It sets up nsock, establishes
+ * a TCP connection with the server, performs the NEP authentication handshake,
+ * sends the appropriate packet specs and handles raw packet transmission and
+ * NEP_ECHO reception and display. */
+int EchoClient::start(NpingTarget *target, u16 port){
+ nping_print(DBG_4, "%s(%p, %u)", __func__, target, port);
+
+ /* Init Nsock in the probe engine */
+ if( this->probe.init_nsock() != OP_SUCCESS ){
+ nping_warning(QT_2, "Couldn't initialize Nsock.");
+ return OP_FAILURE;
+ }else{
+ /* Extract the nsock pool handler and store it here */
+ this->nsp=this->probe.getNsockPool();
+ this->nsi=nsock_iod_new(this->nsp, NULL);
+ }
+
+ /* Schedule a TCP connection attempt */
+ if( this->nep_connect(target, port) != OP_SUCCESS ){
+ nping_warning(QT_2, "Connection failed.");
+ return OP_FAILURE;
+ }
+
+ /* Perform NEP authentication handshake */
+ if( this->nep_handshake() != OP_SUCCESS ){
+ nping_warning(QT_2, "Handshake failed.");
+ return OP_FAILURE;
+ }
+
+ /* Send packet specification */
+ if( this->nep_send_packet_spec() != OP_SUCCESS ){
+ nping_warning(QT_2, "Couldn't send packet specification.");
+ return OP_FAILURE;
+ }
+
+ /* Wait for confirmation */
+ if( this->nep_recv_ready() != OP_SUCCESS ){
+ nping_warning(QT_2, "Didn't receive server's OK.");
+ return OP_FAILURE;
+ }
+
+ /* Schedule read of the first 16 bytes to determine the full packet length */
+ nsock_readbytes(this->nsp, this->nsi, recv_std_header_handler, NSOCK_INFINITE, NULL, STD_NEP_HEADER_LEN);
+
+ /* Start the probe mode engine */
+ probe.start();
+
+ return OP_SUCCESS;
+} /* End of start() */
+
+
+/** Attempts to establish a TCP connection to "target:port". On success it
+ * returns OP_SUCCESS. OP_FAILURE is returned when it was impossible to
+ * connect to the remote host (this can be because the server rejected the
+ * connection or because the connect() timed out). */
+int EchoClient::nep_connect(NpingTarget *target, u16 port){
+ nping_print(DBG_4, "%s(%p, %u)", __func__, target, port);
+ struct sockaddr_storage ss;
+ struct sockaddr_storage src;
+ size_t ss_len;
+ struct sockaddr_in *s4=(struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ss;
+ enum nsock_loopstatus loopstatus;
+
+ if(target==NULL)
+ nping_fatal(QT_3, "nep_connect(): NULL parameter supplied.");
+ else
+ target->getTargetSockAddr(&ss, &ss_len);
+
+ /* AF_INET6 */
+ if( s6->sin6_family==AF_INET6 ){
+ this->af=AF_INET6;
+ this->srvaddr6.sin6_family = AF_INET6;
+ this->srvaddr6.sin6_port = htons(port);
+ this->srvaddr6.sin6_addr = s6->sin6_addr;
+ this->srvaddr6.sin6_flowinfo = 0;
+ #ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
+ this->srvaddr6.sin6_len = sizeof(struct sockaddr_in6);
+ #endif
+
+ /* Try to bind the IOD to the IP address supplied by the user */
+ nsock_iod_set_localaddr(this->nsi, o.getSourceSockAddr(&src), sizeof(sockaddr_in6));
+
+ /* Schedule a connect event */
+ nsock_connect_tcp(this->nsp, this->nsi, connect_done_handler, ECHO_CONNECT_TIMEOUT,
+ NULL, (struct sockaddr *) &this->srvaddr6, sizeof(this->srvaddr6), port);
+
+ /* AF_INET */
+ }else{
+ this->af=AF_INET;
+ this->srvaddr4.sin_family = AF_INET;
+ this->srvaddr4.sin_port = htons(port);
+ this->srvaddr4.sin_addr = s4->sin_addr;
+#ifdef HAVE_SOCKADDR_IN_SIN_LEN
+ this->srvaddr4.sin_len = sizeof(struct sockaddr_in);
+#endif
+
+ /* Try to bind the IOD to the IP address supplied by the user */
+ nsock_iod_set_localaddr(this->nsi, o.getSourceSockAddr(&src), sizeof(sockaddr_in));
+
+ /* Schedule a connect event */
+ nsock_connect_tcp(this->nsp, this->nsi, connect_done_handler, ECHO_CONNECT_TIMEOUT,
+ NULL, (struct sockaddr *) &this->srvaddr4, sizeof(this->srvaddr4), port);
+
+ }
+ /* Try to connect or timeout */
+ loopstatus=nsock_loop(this->nsp, ECHO_CONNECT_TIMEOUT-1);
+ /* If nsock tells us that the handler asked to quit the loop, then the connect was successful */
+ return (loopstatus==NSOCK_LOOP_QUIT) ? OP_SUCCESS : OP_FAILURE;
+} /* End of nep_connect() */
+
+
+/** Attempts to perform the NEP authentication handshake with the server.
+ * Returns OP_SUCCESS if the authentication went well and OP_FAILURE otherwise */
+int EchoClient::nep_handshake(){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nsock_loopstatus loopstatus;
+ EchoHeader h;
+
+ /* Receive NEP_HANDSHAKE_SERVER message */
+ nsock_readbytes(this->nsp, this->nsi, recv_hs_server_handler, ECHO_READ_TIMEOUT, NULL, NEP_HANDSHAKE_SERVER_LEN);
+ loopstatus=nsock_loop(this->nsp, ECHO_READ_TIMEOUT-1);
+ if(loopstatus!=NSOCK_LOOP_QUIT)
+ return OP_FAILURE;
+
+ /* Generate client nonces and the session cryptographic keys*/
+ this->ctx.generateInitialClientSequence();
+ this->ctx.generateClientNonce();
+ this->ctx.generateCipherKeyC2S();
+ this->ctx.generateCipherKeyS2C();
+ this->ctx.generateMacKeyC2S();
+ this->ctx.generateMacKeyS2C();
+
+ nping_print(DBG_4,"Session Key MAC_C2S:"); print_hexdump(DBG_4,ctx.getMacKeyC2S(), MAC_KEY_LEN);
+ nping_print(DBG_4,"Session Key MAC_S2C:"); print_hexdump(DBG_4,ctx.getMacKeyS2C(), MAC_KEY_LEN);
+ nping_print(DBG_4,"Session Key CIPHER_C2S:"); print_hexdump(DBG_4,ctx.getCipherKeyC2S(), MAC_KEY_LEN);
+ nping_print(DBG_4,"Session Key CIPHER_S2C:"); print_hexdump(DBG_4,ctx.getCipherKeyS2C(), MAC_KEY_LEN);
+
+
+ /* Send NEP_HANDSHAKE_CLIENT message */
+ if( this->generate_hs_client(&h)!=OP_SUCCESS )
+ return OP_FAILURE;
+ nsock_write(this->nsp, this->nsi, write_done_handler, ECHO_WRITE_TIMEOUT, NULL, (char *)h.getBinaryBuffer(), h.getLen());
+ loopstatus=nsock_loop(this->nsp, ECHO_WRITE_TIMEOUT-1);
+ if(loopstatus!=NSOCK_LOOP_QUIT)
+ return OP_FAILURE;
+
+ /* Receive NEP_HANDSHAKE_FINAL message */
+ nsock_readbytes(this->nsp, this->nsi, recv_hs_final_handler, ECHO_READ_TIMEOUT, NULL, NEP_HANDSHAKE_FINAL_LEN);
+ loopstatus=nsock_loop(this->nsp, ECHO_READ_TIMEOUT-1);
+ if(loopstatus!=NSOCK_LOOP_QUIT)
+ return OP_FAILURE;
+
+ nping_print(DBG_1, "===NEP Handshake completed successfully===");
+ return OP_SUCCESS;
+} /* End of nep_handshake() */
+
+
+/** Sends the appropriate NEP_PACKET_SPEC message to the server. Returns
+ * OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoClient::nep_send_packet_spec(){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nsock_loopstatus loopstatus;
+ EchoHeader h;
+
+ if (this->generate_packet_spec(&h)!=OP_SUCCESS)
+ return OP_FAILURE;
+
+ /* Send NEP_PACKET_SPEC message */
+ nsock_write(this->nsp, this->nsi, write_done_handler, ECHO_WRITE_TIMEOUT, NULL, (const char*)h.getBinaryBuffer(), h.getLen());
+ loopstatus=nsock_loop(this->nsp, ECHO_WRITE_TIMEOUT-1);
+ if(loopstatus!=NSOCK_LOOP_QUIT)
+ return OP_FAILURE;
+ else
+ return OP_SUCCESS;
+} /* End of nep_send_packetspec() */
+
+
+/** Receives and parses a NEP_READY message from the server. Returns OP_SUCCESS
+ * on success and OP_FAILURE in case of error. */
+int EchoClient::nep_recv_ready(){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nsock_loopstatus loopstatus;
+ /* Receive NEP_READY message */
+ nsock_readbytes(this->nsp, this->nsi, recv_ready_handler, ECHO_READ_TIMEOUT, NULL, NEP_READY_LEN);
+ loopstatus=nsock_loop(this->nsp, ECHO_READ_TIMEOUT-1);
+ if(loopstatus!=NSOCK_LOOP_QUIT)
+ return OP_FAILURE;
+ else
+ return OP_SUCCESS;
+} /* End of nep_recv_ready(){ */
+
+
+/** Reads and parses a NEP_ECHO message from the server. Returns OP_SUCCESS
+ * on success and OP_FAILURE in case of error. */
+int EchoClient::nep_recv_echo(u8 *packet, size_t packetlen){
+ nping_print(DBG_4, "%s(%p, %lu)", __func__, packet, (unsigned long)packetlen);
+ EchoHeader pkt_in;
+ char *delayedstr=NULL;
+ nsock_event_id ev_id;
+ u8 *pkt=NULL;
+ u16 pktlen=0;
+ u8 pktinfobuffer[512+1];
+ struct timeval *t = (struct timeval *)nsock_gettimeofday();
+ memset(pktinfobuffer, 0, sizeof(pktinfobuffer));
+
+ /* Verify the received packet (this covers authentication etc) */
+ if(this->parse_echo(packet, packetlen)!=OP_SUCCESS){
+ return OP_FAILURE;
+ }
+
+ /* Once we have authenticated the received message, extract the echoed packet */
+ if(pkt_in.storeRecvData(packet, packetlen)==OP_FAILURE){
+ nping_print(VB_0, "Unexpected error dealing with the NEP_ECHO message,");
+ return OP_FAILURE;
+ }
+ if((pkt=pkt_in.getEchoedPacket(&pktlen))==NULL){
+ nping_print(VB_0, "Error displaying received NEP_ECHO message)");
+ return OP_FAILURE;
+ }
+ o.stats.addEchoedPacket(pktlen);
+
+ /* Guess the time the packet was captured. We do this computing the RTT
+ * between the last sent packet and the received echo packet. We assume
+ * the packet was captured RTT/2 seconds ago. */
+ struct timeval tmp=o.getLastPacketSentTime();
+ float sent_time = o.stats.elapsedRuntime(&tmp);
+ float now_time = o.stats.elapsedRuntime(t);
+ float rtt = now_time - sent_time;
+ float final_time = sent_time + rtt/2;
+
+ /* @todo: compute the link layer offset from the DLT type and discard
+ * link layer headers */
+ getPacketStrInfo("IP", pkt, pktlen, pktinfobuffer, 512);
+ nping_print(VB_0,"CAPT (%.4fs) %s", final_time, pktinfobuffer );
+ if( o.getVerbosity() >= VB_3)
+ luis_hdump((char*)pkt, pktlen);
+
+ /* Check if there is a delayed RCVD string that is waiting to be printed */
+ if( (delayedstr=o.getDelayedRcvd(&ev_id))!=NULL ){
+ printf("%s", delayedstr);
+ free(delayedstr);
+ nsock_event_cancel(this->nsp, ev_id, 0);
+ }
+ return OP_SUCCESS;
+} /* End of nep_recv_echo() */
+
+
+/** Processes and validates a received NEP_HANDSHAKE_SERVER message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoClient::parse_hs_server(u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader h;
+ if(pkt==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen!=NEP_HANDSHAKE_SERVER_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_HANDSHAKE_SERVER){
+ nping_print(DBG_1, "Expected NEP_HANDSHAKE_SERVER but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_HANDSHAKE_SERVER timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+ /* Ensure message length is correct */
+ if( h.getTotalLength()!=(NEP_HANDSHAKE_SERVER_LEN/4)){
+ nping_print(DBG_1, "Received NEP_HANDSHAKE_SERVER specifies an incorrect length (%u)", h.getTotalLength()*4 );
+ return OP_FAILURE;
+ }
+
+ /* Check the authenticity of the received message */
+ this->ctx.setServerNonce(h.getServerNonce());
+ this->ctx.generateMacKeyS2CInitial();
+ if( h.verifyMessageAuthenticationCode(this->ctx.getMacKeyS2C(), MAC_KEY_LEN )!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_HANDSHAKE_SERVER authentication failed" );
+ return OP_FAILURE;
+ }
+ this->ctx.setLastServerSequence( h.getSequenceNumber() );
+ return OP_SUCCESS;
+} /* End of parse_hs_server() */
+
+
+/** Processes and validates a received NEP_HANDSHAKE_FINAL message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoClient::parse_hs_final(u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader h;
+ u8 *next_iv=NULL;
+ if(pkt==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen!=NEP_HANDSHAKE_FINAL_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_HANDSHAKE_FINAL){
+ nping_print(DBG_1, "Expected NEP_HANDSHAKE_FINAL but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received sequence number is the previous+1 */
+ if( h.getSequenceNumber()!=(this->ctx.getLastServerSequence()+1)){
+ nping_print(DBG_1, "Expected sequence number %d but received %d", this->ctx.getLastServerSequence()+1, h.getSequenceNumber() );
+ return OP_FAILURE;
+ }else{
+ /* Increment next expected sequence number*/
+ this->ctx.getNextServerSequence();
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_HANDSHAKE_FINAL timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+ /* Ensure message length is correct */
+ if( h.getTotalLength()!=(NEP_HANDSHAKE_FINAL_LEN/4)){
+ nping_print(DBG_1, "Received NEP_HANDSHAKE_FINAL specifies an incorrect length (%u)", h.getTotalLength()*4 );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the server echoed the nonce we sent in our NEP_HANDSHAKE_CLIENT */
+ if( memcmp(h.getClientNonce(), this->ctx.getClientNonce(), NONCE_LEN)!=0 ){
+ nping_print(DBG_1, "Echoed nonce in NEP_HANDSHAKE_FINAL message does not match client generate nonce");
+ return OP_FAILURE;
+ }
+
+ /* Decrypt the encrypted part of the message before validating the MAC */
+ if((next_iv=h.decrypt(this->ctx.getCipherKeyS2C(), CIPHER_KEY_LEN, this->ctx.getServerNonce(), TYPE_NEP_HANDSHAKE_FINAL))==NULL){
+ nping_print(DBG_1, "Failed to decrypt NEP_HANDSHAKE_FINAL data." );
+ return OP_FAILURE;
+ }
+ this->ctx.setNextDecryptionIV(next_iv);
+
+ /* Check the authenticity of the received message */
+ if( h.verifyMessageAuthenticationCode(this->ctx.getMacKeyS2C(), MAC_KEY_LEN )!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_HANDSHAKE_FINAL authentication failed" );
+ return OP_FAILURE;
+ }
+
+ return OP_SUCCESS;
+} /* End of parse_hs_final() */
+
+
+/** Processes and validates a received NEP_READY message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoClient::parse_ready(u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader h;
+ u8 *next_iv=NULL;
+ if(pkt==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen!=NEP_READY_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Decrypt message */
+ if((next_iv=h.decrypt(this->ctx.getCipherKeyS2C(), CIPHER_KEY_LEN, this->ctx.getNextDecryptionIV(), TYPE_NEP_READY))==NULL){
+ nping_print(DBG_1, "Failed to decrypt NEP_READY data." );
+ return OP_FAILURE;
+ }
+ this->ctx.setNextDecryptionIV(next_iv);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_READY){
+ nping_print(DBG_1, "Expected NEP_READY but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received sequence number is the previous+1 */
+ if( h.getSequenceNumber()!=(this->ctx.getLastServerSequence()+1)){
+ nping_print(DBG_1, "Expected sequence number %d but received %d", this->ctx.getLastServerSequence()+1, h.getSequenceNumber() );
+ return OP_FAILURE;
+ }else{
+ /* Increment next expected sequence number*/
+ this->ctx.getNextServerSequence();
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_READY timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+ /* Ensure message length is correct */
+ if( h.getTotalLength()!=(NEP_READY_LEN/4)){
+ nping_print(DBG_1, "Received NEP_READY specifies an incorrect length (%u)", h.getTotalLength()*4 );
+ return OP_FAILURE;
+ }
+
+ /* Check the authenticity of the received message */
+ if( h.verifyMessageAuthenticationCode(this->ctx.getMacKeyS2C(), MAC_KEY_LEN )!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_READY authentication failed" );
+ return OP_FAILURE;
+ }
+
+ return OP_SUCCESS;
+} /* End of parse_hs_final() */
+
+
+/** Processes and validates a received NEP_ECHO message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoClient::parse_echo(u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader h;
+ u8 *next_iv=NULL;
+ if(pkt==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen<NEP_ECHO_MIN_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Decrypt message */
+ if((next_iv=h.decrypt(this->ctx.getCipherKeyS2C(), CIPHER_KEY_LEN, this->ctx.getNextDecryptionIV(), TYPE_NEP_ECHO))==NULL){
+ nping_print(DBG_1, "Failed to decrypt NEP_ECHO data." );
+ return OP_FAILURE;
+ }
+ this->ctx.setNextDecryptionIV(next_iv);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_ECHO){
+ nping_print(DBG_1, "Expected NEP_ECHO but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received sequence number is the previous+1 */
+ if( h.getSequenceNumber()!=(this->ctx.getLastServerSequence()+1)){
+ nping_print(DBG_1, "Expected sequence number %d but received %d", this->ctx.getLastServerSequence()+1, h.getSequenceNumber() );
+ return OP_FAILURE;
+ }else{
+ /* Increment next expected sequence number*/
+ this->ctx.getNextServerSequence();
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_ECHO timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+// /* Ensure message length is correct */
+// if( h.getTotalLength()!=(pktlen/4)){
+// nping_print(DBG_1, "Received NEP_ECHO specifies an incorrect length (%u)", h.getTotalLength()*4 );
+// return OP_FAILURE;
+// }
+
+ /* Fix the object's internal state, since the ECHO message was not created
+ * by the object but from received data. */
+ h.updateEchoInternals();
+
+ /* Check the authenticity of the received message */
+ if( h.verifyMessageAuthenticationCode(this->ctx.getMacKeyS2C(), MAC_KEY_LEN )!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_ECHO authentication failed" );
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_1, "Received NEP_ECHO was authenticated successfully");
+ }
+
+ /* Overwrite the received buffer with the decrypted data */
+ h.dumpToBinaryBuffer(pkt, pktlen);
+
+ return OP_SUCCESS;
+} /* End of parse_hs_final() */
+
+
+/** Processes and validates a received NEP_ERROR message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoClient::parse_error(u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s()", __func__);
+ return OP_SUCCESS;
+} /* End of parse_hs_final() */
+
+
+/** Generates a NEP_HANDSHAKE_CLIENT message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error. */
+int EchoClient::generate_hs_client(EchoHeader *h){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *next_iv=NULL;
+ if(h==NULL)
+ return OP_FAILURE;
+
+ /* Craft NEP_HANDSHAKE_CLIENT message */
+ h->setMessageType(TYPE_NEP_HANDSHAKE_CLIENT);
+ h->setSequenceNumber( this->ctx.getLastClientSequence() );
+ h->setTimestamp();
+ h->setServerNonce( this->ctx.getServerNonce() );
+ h->setClientNonce( this->ctx.getClientNonce() );
+ if(this->af==AF_INET6){
+ h->setPartnerAddress(this->srvaddr6.sin6_addr);
+ }else{
+ h->setPartnerAddress(this->srvaddr4.sin_addr);
+ }
+ h->setTotalLength();
+ h->setMessageAuthenticationCode( this->ctx.getMacKeyC2S(), MAC_KEY_LEN);
+
+ if( (next_iv=h->encrypt(this->ctx.getCipherKeyC2S(), CIPHER_KEY_LEN, this->ctx.getClientNonce()))==NULL )
+ return OP_FAILURE;
+ this->ctx.setNextEncryptionIV(next_iv);
+
+ return OP_SUCCESS;
+} /* End of generate_hs_client() */
+
+/** Generates a NEP_PACKET_SPEC message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error. */
+int EchoClient::generate_packet_spec(EchoHeader *h){
+ nping_print(DBG_4, "%s()", __func__);
+ int ports=-1;
+ u8 nxthdr=0;
+ u8 aux8=0;
+ u16 aux16=0;
+ u16 *p16=NULL;
+ u32 aux32=0;
+ u8 *next_iv=NULL;
+
+ if(h==NULL)
+ return OP_FAILURE;
+
+ h->setMessageType(TYPE_NEP_PACKET_SPEC);
+ h->setSequenceNumber( this->ctx.getNextClientSequence() );
+ h->setTimestamp();
+ h->setIPVersion( o.getIPVersion()==AF_INET6 ? 0x06: 0x04 );
+ h->setPacketCount( (o.getPacketCount()>0xFFFF) ? 0xFFFF : o.getPacketCount() );
+
+ /** Insert packet field specifiers */
+ if(o.ipv6()){ /* AF_INET6 */
+ /* Traffic class */
+ aux8=o.getTrafficClass();
+ h->addFieldSpec(PSPEC_IPv6_TCLASS, (u8*)&aux8);
+ /* Flow label */
+ aux32=htonl(o.getFlowLabel());
+ h->addFieldSpec(PSPEC_IPv6_FLOW, (u8*)&aux32);
+ }else{ /* AF_INET */
+ /* IP Identification */
+ aux16=htons(o.getIdentification());
+ h->addFieldSpec(PSPEC_IPv4_ID, (u8*)&aux16);
+ /* Type of Service */
+ aux8=o.getTOS();
+ h->addFieldSpec(PSPEC_IPv4_TOS, (u8*)&aux8);
+ /* Fragment Offset */
+ /** @todo Implement this. Nping does not currently offer --fragoff */
+ }
+
+ switch( o.getMode() ){
+
+ case TCP:
+ nxthdr=6;
+ h->setProtocol(PSPEC_PROTO_TCP);
+ /* Source TCP Port */
+ aux16=htons(o.getSourcePort());
+ h->addFieldSpec(PSPEC_TCP_SPORT, (u8*)&aux16);
+ /* Destination TCP Port */
+ if( (p16=o.getTargetPorts(&ports))!=NULL && ports==1 ){
+ aux16=htons(*p16);
+ h->addFieldSpec(PSPEC_TCP_DPORT, (u8*)&aux16);
+ }
+ /* Sequence number */
+ aux32=htonl(o.getTCPSequence());
+ h->addFieldSpec(PSPEC_TCP_SEQ, (u8*)&aux32);
+ /* Acknowledgment */
+ aux32=htonl(o.getTCPAck());
+ h->addFieldSpec(PSPEC_TCP_ACK, (u8*)&aux32);
+ /* Flags */
+ aux8=o.getTCPFlags();
+ h->addFieldSpec(PSPEC_TCP_FLAGS, (u8*)&aux8);
+ /* Window size */
+ aux16=htons(o.getTCPWindow());
+ h->addFieldSpec(PSPEC_TCP_WIN, (u8*)&aux16);
+ /* Urgent pointer */
+ /** @todo Implement this. Nping does not currently offer --urp */
+ break;
+
+ case UDP:
+ nxthdr=17;
+ h->setProtocol(PSPEC_PROTO_UDP);
+ /* Source UDP Port */
+ aux16=htons(o.getSourcePort());
+ h->addFieldSpec(PSPEC_UDP_SPORT, (u8*)&aux16);
+ /* Destination TCP Port */
+ if( (p16=o.getTargetPorts(&ports))!=NULL && ports==1 ){
+ aux16=htons(*p16);
+ h->addFieldSpec(PSPEC_UDP_DPORT, (u8*)&aux16);
+ }
+ /* Packet length */
+ aux16=htons(8+o.getPayloadLen());
+ h->addFieldSpec(PSPEC_UDP_LEN, (u8*)&aux16);
+ break;
+
+ case ICMP:
+ nxthdr=1;
+ h->setProtocol(PSPEC_PROTO_ICMP);
+ aux8=o.getICMPType();
+ h->addFieldSpec(PSPEC_ICMP_TYPE, (u8*)&aux8);
+ aux8=o.getICMPCode();
+ h->addFieldSpec(PSPEC_ICMP_CODE, (u8*)&aux8);
+ break;
+
+ case UDP_UNPRIV:
+ case TCP_CONNECT:
+ case ARP:
+ default:
+ nping_fatal(QT_3, "%s packets are not supported in Echo Mode", o.mode2Ascii(o.getMode()) );
+ break;
+ }
+ /* Next protocol number */
+ if(o.ipv4())
+ h->addFieldSpec(PSPEC_IPv4_PROTO, (u8*)&nxthdr);
+ else
+ h->addFieldSpec(PSPEC_IPv6_NHDR, (u8*)&nxthdr);
+
+ if( o.issetPayloadBuffer() && o.getPayloadLen()>0){
+ h->addFieldSpec(PSPEC_PAYLOAD_MAGIC, (u8*)o.getPayloadBuffer(), MIN(o.getPayloadLen(), NEP_PAYLOADMAGIC_MAX_BYTES));
+ }
+ /* Done inserting packet field specifiers, now finish the packet */
+ h->setTotalLength();
+ h->setMessageAuthenticationCode(this->ctx.getMacKeyC2S(), MAC_KEY_LEN);
+
+ /* Encrypt message */
+ if( (next_iv=h->encrypt(this->ctx.getCipherKeyC2S(), CIPHER_KEY_LEN, this->ctx.getNextEncryptionIV()))==NULL )
+ return OP_FAILURE;
+ this->ctx.setNextEncryptionIV(next_iv);
+
+ return OP_SUCCESS;
+} /* End of generate_packet_spec() */
+
+
+/** Handles reception of a full NEP message. (the common NEP header). Basically
+ * it stores received data in the internal buffer and passes the control to
+ * the nep_recv_echo() method, which is the one in charge of processing
+ * NEP_ECHO packets */
+int EchoClient::nep_echoed_packet_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader pkt_in;
+ u8 *recvbuff=NULL;
+ int recvbytes=0;
+ u8 aux[128];
+ u8 *pkt_start=this->lasthdr;
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ if(status!=NSE_STATUS_KILL){
+ nping_warning(QT_2, "===========================================================================");
+ nping_warning(QT_2, "ERROR: Server closed the connection. No more CAPT packets will be received.");
+ nping_warning(QT_2, "===========================================================================");
+ }
+ return OP_FAILURE;
+ }
+
+ /* Read the remaining data */
+ if( (recvbuff=(u8 *)nse_readbuf(nse, &recvbytes))==NULL ){
+ nping_print(DBG_4,"nep_echoed_packet_handler(): nse_readbuf failed!\n");
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_4, "%s() Received %d bytes", __func__, recvbytes);
+ }
+
+ /* When we get here we'll have part of the packet stored in this->lasthdr and
+ * part of it (and possible more packets) stored in recvbuff. */
+ while(recvbytes>0){
+
+ /* Determine if we received the expected number of bytes or we received more
+ * than that. For that we need to decrypt the first 16 bytes so we can have
+ * a look at packet length */
+ Crypto::aes128_cbc_decrypt(pkt_start, 16, aux, this->ctx.getCipherKeyS2C(), CIPHER_KEY_LEN, this->ctx.getNextDecryptionIV());
+ pkt_in.storeRecvData(aux, 16);
+ int plen=pkt_in.getTotalLength()*4;
+ nping_print(DBG_4, "%s() Packet claims to have a length of %d bytes", __func__, plen);
+
+ /* If the packet is bigger than the maximum NEP packet, discard it. */
+ if(plen>MAX_NEP_PACKET_LENGTH){
+ nping_warning(DBG_1,"Warning. Received NEP packet (%dB) is bigger than %d bytes.", plen, MAX_NEP_PACKET_LENGTH);
+ return OP_FAILURE;
+ }
+
+ /* If we have read the whole packet, give it to nep_recv_echo for processing */
+ if (plen==((int)this->readbytes+recvbytes)){
+ memcpy(this->lasthdr+this->readbytes, recvbuff, recvbytes);
+ this->readbytes+=recvbytes;
+ nping_print(DBG_4,"%s(): Received exact length (%d).", __func__, recvbytes);
+ this->nep_recv_echo(this->lasthdr, this->readbytes);
+ nsock_readbytes(this->nsp, this->nsi, recv_std_header_handler, NSOCK_INFINITE, NULL, STD_NEP_HEADER_LEN);
+ return OP_SUCCESS;
+
+ /* This one can't happen in the first iteration since we scheduled the
+ * event with the exact amount of bytes, but may happen after that if we
+ * received more data and one of the packets is incomplete */
+ }else if(recvbytes<plen){
+ memcpy(this->lasthdr, recvbuff, recvbytes);
+ this->readbytes=recvbytes;
+ nping_print(DBG_4,"%s(): Missing %d bytes. Scheduled read operation for remaining bytes", __func__, plen-recvbytes);
+ nsock_readbytes(nsp, nsi, echoed_packet_handler, NSOCK_INFINITE, NULL, plen-recvbytes);
+ return OP_SUCCESS;
+
+ }else{ /* Received more than one packet */
+ nping_print(DBG_4,"%s(): Received more than one packet", __func__);
+ memcpy(this->lasthdr+this->readbytes, recvbuff, plen-this->readbytes);
+ this->nep_recv_echo(this->lasthdr, plen);
+ recvbuff+=plen-this->readbytes;
+ recvbytes-=plen-this->readbytes;
+ this->readbytes=0;
+ pkt_start=recvbuff;
+ }
+
+ }
+ return OP_SUCCESS;
+} /* End of nep_echoed_packet_handler() */
+
+
+/** Handles reception of the first 16 bytes (the common NEP header). Basically
+ * it checks the Total Length field of the header to determine how many bytes
+ * are left to read to get the entire packet. If there are more bytes to be
+ * receives, a read event is scheduled. However, we may have read them all when
+ * this handler is called (due to nsock behaviour) so in that case we just pass
+ * control to nep_recv_echo(), which is the one in charge of processing
+ * NEP_ECHO packets */
+int EchoClient::nep_recv_std_header_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ EchoHeader pkt_in;
+ u8 *recvbuff=NULL;
+ int recvbytes=0;
+ u8 aux[128];
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ if(status!=NSE_STATUS_KILL){
+ nping_warning(QT_2, "===========================================================================");
+ nping_warning(QT_2, "ERROR: Server closed the connection. No more CAPT packets will be received.");
+ nping_warning(QT_2, "===========================================================================");
+ }
+ return OP_FAILURE;
+ }
+ /* Read data */
+ if( (recvbuff=(u8 *)nse_readbuf(nse, &recvbytes))==NULL ){
+ nping_print(DBG_4,"%s(): nse_readbuf failed.", __func__);
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_4, "%s() Received %d bytes", __func__, recvbytes);
+ }
+
+ /* Here there are different possibilities. We may have received exactly one
+ * packet, we may have received more than one packet (as there is no way to
+ * make Nsock return an exact amount of bytes), or we may have received
+ * less than one packet. In the last case, we determine the number of bytes
+ * left and schedule another read event. */
+ while(recvbytes>0){
+
+ /* Decrypt the first 16 bytes so we can have a look at packet length */
+ Crypto::aes128_cbc_decrypt(recvbuff, 16, aux, this->ctx.getCipherKeyS2C(), CIPHER_KEY_LEN, this->ctx.getNextDecryptionIV());
+ pkt_in.storeRecvData(aux, 16);
+ int plen=pkt_in.getTotalLength()*4;
+
+ /* If the packet is bigger than the maximum NEP packet, discard it. */
+ if(plen>MAX_NEP_PACKET_LENGTH){
+ nping_warning(DBG_1,"Warning. Received NEP packet (%dB) is bigger than %d bytes.", plen, MAX_NEP_PACKET_LENGTH);
+ return OP_FAILURE;
+ }
+
+ /* If we have read the whole packet, give it to nep_recv_echo for processing */
+ if (plen==recvbytes){
+ nping_print(DBG_4,"%s(): Received exact length (%d).", __func__, recvbytes);
+ this->nep_recv_echo(recvbuff, recvbytes);
+ nsock_readbytes(this->nsp, this->nsi, recv_std_header_handler, NSOCK_INFINITE, NULL, STD_NEP_HEADER_LEN);
+ return OP_SUCCESS;
+
+ }else if(recvbytes<plen){
+ memcpy(this->lasthdr, recvbuff, recvbytes);
+ this->readbytes=recvbytes;
+ nping_print(DBG_4,"%s(): Missing %d bytes. Scheduled read operation for remaining bytes", __func__, plen-recvbytes);
+ nsock_readbytes(nsp, nsi, echoed_packet_handler, NSOCK_INFINITE, NULL, plen-recvbytes);
+ return OP_SUCCESS;
+
+ }else{ /* Received more than one packet */
+ nping_print(DBG_4,"%s(): Received more than one packet", __func__);
+ this->nep_recv_echo(recvbuff, plen);
+ recvbuff+=plen;
+ recvbytes-=plen;
+ }
+
+ }
+
+ /* Schedule another read event for the next echo packet */
+ nsock_readbytes(this->nsp, this->nsi, recv_std_header_handler, NSOCK_INFINITE, NULL, STD_NEP_HEADER_LEN);
+
+ return OP_SUCCESS;
+} /* End of nep_recv_std_header_handler() */
+
+
+/** Handles reception of NEP_HANDSHAKE_SERVER message. It handles the received
+ * data provided by nsock and passes it to the parse_hs_server() which is the
+ * one in charge of validating NEP_HANDSHAKE_SERVER packets and updating
+ * the internal context accordingly. Returns OP_SUCCESS on success and
+ * OP_FAILURE in case of error. */
+int EchoClient::nep_recv_hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *inbuff=NULL;
+ int inlen=0;
+ /* Ask nsock to provide received data */
+ if( (inbuff=(u8 *)nse_readbuf(nse, &inlen))==NULL )
+ return OP_FAILURE;
+ /* Process the NEP_HANDSHAKE_SERVER message */
+ if ( this->parse_hs_server(inbuff, (size_t)inlen)!=OP_SUCCESS ){
+ return OP_FAILURE;
+ }
+ return OP_SUCCESS;
+} /* End of nep_recv_hs_server_handler() */
+
+
+/** Handles reception of NEP_HANDSHAKE_FINAL message. It handles the received
+ * data provided by nsock and passes it to the parse_hs_final() which is the
+ * one in charge of validating NEP_HANDSHAKE_FINAL packets and updating
+ * the internal context accordingly. Returns OP_SUCCESS on success and
+ * OP_FAILURE in case of error. */
+int EchoClient::nep_recv_hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *inbuff=NULL;
+ int inlen=0;
+ /* Ask nsock to provide received data */
+ if( (inbuff=(u8 *)nse_readbuf(nse, &inlen))==NULL )
+ return OP_FAILURE;
+ /* Process the NEP_HANDSHAKE_SERVER message */
+ if ( this->parse_hs_final(inbuff, (size_t)inlen)!=OP_SUCCESS ){
+ return OP_FAILURE;
+ }
+ return OP_SUCCESS;
+} /* End of nep_recv_hs_final_handler() */
+
+
+/** Handles reception of NEP_READY message. It handles the received
+ * data provided by nsock and passes it to the parse_ready() which is the
+ * one in charge of validating NEP_HANDSHAKE_FINAL packets and updating
+ * the internal context accordingly. Returns OP_SUCCESS on success and
+ * OP_FAILURE in case of error. */
+int EchoClient::nep_recv_ready_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *inbuff=NULL;
+ int inlen=0;
+ /* Ask nsock to provide received data */
+ if( (inbuff=(u8 *)nse_readbuf(nse, &inlen))==NULL )
+ return OP_FAILURE;
+ /* Process the NEP_HANDSHAKE_SERVER message */
+ if ( this->parse_ready(inbuff, (size_t)inlen)!=OP_SUCCESS ){
+ return OP_FAILURE;
+ }
+ return OP_SUCCESS;
+} /* End of nep_recv_ready_handler() */
+
+
+
+/******************************************************************************/
+/**** HANDLER WRAPPERS ********************************************************/
+/******************************************************************************/
+
+/** This handler is a wrapper for the EchoClient::nep_echoed_packet_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void echoed_packet_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ec.nep_echoed_packet_handler(nsp, nse, arg);
+ return;
+} /* End of echoed_packet_handler() */
+
+
+/** This handler is a wrapper for the EchoClient::nep_recv_std_header_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void recv_std_header_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ec.nep_recv_std_header_handler(nsp, nse, arg);
+ return;
+} /* End of recv_std_header_handler() */
+
+
+/** Simple wrapper for TCP connection establishment. In this case we don't need
+ * to do anything special, just detect it the connection was successful. If
+ * it was, we call nsock_loop_quit(), which indicates the success to
+ * the method that scheduled the event and called nsock_loop() */
+void connect_done_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_4, "%s(): Failed to connect.", __func__);
+ }else{
+ nsock_loop_quit(nsp);
+ }
+ return;
+} /* End of connect_done_handler() */
+
+
+/** Really simple wrapper for write calls where we don't need to perform any
+ * special operations. It just checks if the write even was successful and
+ * in that case it calls nsock_loop_quit(), which indicates the success to
+ * the method that scheduled the event and called nsock_loop() */
+void write_done_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_4, "%s(): Write operation failed.", __func__);
+ }else{
+ nsock_loop_quit(nsp);
+ }
+ return;
+} /* End of connect_done_handler() */
+
+
+/** This handler is a wrapper for the EchoClient::recv_hs_server_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void recv_hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_4, "%s(): Read operation failed.", __func__);
+ }else if(ec.nep_recv_hs_server_handler(nsp, nse, arg)==OP_SUCCESS){
+ nsock_loop_quit(nsp);
+ }
+ return;
+} /* End of recv_hs_server_handler() */
+
+
+/** This handler is a wrapper for the EchoClient::recv_hs_final_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void recv_hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_4, "%s(): Read operation failed.", __func__);
+ }else if(ec.nep_recv_hs_final_handler(nsp, nse, arg)==OP_SUCCESS){
+ nsock_loop_quit(nsp);
+ }
+ return;
+} /* End of recv_hs_server_handler() */
+
+
+
+/** This handler is a wrapper for the EchoClient::nep_recv_ready_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void recv_ready_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_4, "%s(): Read operation failed.", __func__);
+ }else if(ec.nep_recv_ready_handler(nsp, nse, arg)==OP_SUCCESS){
+ nsock_loop_quit(nsp);
+ }
+ return;
+} /* End of recv_hs_server_handler() */
+
diff --git a/nping/EchoClient.h b/nping/EchoClient.h
new file mode 100644
index 0000000..7b27594
--- /dev/null
+++ b/nping/EchoClient.h
@@ -0,0 +1,131 @@
+
+/***************************************************************************
+ * EchoClient.h -- *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+#ifndef __ECHOCLIENT_H__
+#define __ECHOCLIENT_H__ 1
+
+#include "nping.h"
+#include "NpingTarget.h"
+#include "NEPContext.h"
+#include "ProbeMode.h"
+
+#define ECHO_CONNECT_TIMEOUT (10*1000) /* 10 Seconds */
+#define ECHO_READ_TIMEOUT (10*1000)
+#define ECHO_WRITE_TIMEOUT (10*1000)
+
+/* Max number of bytes that are supplied as data for the PAYLOAD_MAGIC specifier */
+#define NEP_PAYLOADMAGIC_MAX_BYTES 8
+
+
+class EchoClient {
+
+ private:
+
+ /* Attributes */
+ nsock_pool nsp; /**< Nsock pool (shared with ProbeMode) */
+ nsock_iod nsi; /**< IOD for the side-channel tcp socket*/
+ struct sockaddr_in srvaddr4; /**< Server's IPv4 address */
+ struct sockaddr_in6 srvaddr6; /**< Server's IPv6 address */
+ int af; /**< Address family (AF_INET or AF_INET6)*/
+ NEPContext ctx;
+ ProbeMode probe;
+ u8 lasthdr[MAX_NEP_PACKET_LENGTH];
+ size_t readbytes;
+
+ /* Methods */
+ int nep_connect(NpingTarget *target, u16 port);
+ int nep_handshake();
+ int nep_send_packet_spec();
+ int nep_recv_ready();
+ int nep_recv_echo(u8 *packet, size_t packetlen);
+
+ int parse_hs_server(u8 *pkt, size_t pktlen);
+ int parse_hs_final(u8 *pkt, size_t pktlen);
+ int parse_ready(u8 *pkt, size_t pktlen);
+ int parse_echo(u8 *pkt, size_t pktlen);
+ int parse_error(u8 *pkt, size_t pktlen);
+
+ int generate_hs_client(EchoHeader *h);
+ int generate_packet_spec(EchoHeader *h);
+
+ public:
+
+ EchoClient();
+ ~EchoClient();
+ void reset();
+ int start(NpingTarget *target, u16 port);
+ int cleanup();
+ int nep_echoed_packet_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ int nep_recv_std_header_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ int nep_recv_hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ int nep_recv_hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ int nep_recv_ready_handler(nsock_pool nsp, nsock_event nse, void *arg);
+
+}; /* End of class EchoClient */
+
+
+/* Handler wrappers */
+void echoed_packet_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void recv_std_header_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void connect_done_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void write_done_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void recv_hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void recv_hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void recv_ready_handler(nsock_pool nsp, nsock_event nse, void *arg);
+
+#endif /* __ECHOCLIENT_H__ */
diff --git a/nping/EchoHeader.cc b/nping/EchoHeader.cc
new file mode 100644
index 0000000..06d3dbe
--- /dev/null
+++ b/nping/EchoHeader.cc
@@ -0,0 +1,970 @@
+
+/***************************************************************************
+ * EchoHeader.cc -- The EchoHeader Class represents packets of the Nping *
+ * Echo Protocol. It contains the appropriate methods to set/get all *
+ * header fields. In general these methods do error checking and perform *
+ * byte order conversions. *
+ * *
+ ***********************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 "EchoHeader.h"
+#include "nping.h"
+#include "output.h"
+#include <time.h>
+#include <assert.h>
+#include "Crypto.h"
+
+EchoHeader::EchoHeader(){
+ this->reset();
+} /* End of EchoHeader constructor */
+
+
+EchoHeader::~EchoHeader(){
+
+} /* End of EchoHeader destructor */
+
+
+/** Sets every attribute to its default value. */
+void EchoHeader::reset() {
+ memset(&this->h, 0, sizeof(echohdr_t) );
+ this->data_hsserv=(nep_hs_serv_data_t *)this->h.data;
+ this->data_hsclnt=(nep_hs_clnt_data_t *)this->h.data;
+ this->data_hsfinal=(nep_hs_final_data_t *)this->h.data;
+ this->data_pspec=(nep_packet_spec_data_t *)this->h.data;
+ this->data_ready=(nep_ready_data_t *)this->h.data;
+ this->data_echo=(nep_echo_data_t *)this->h.data;
+ this->data_error=(nep_error_data_t *)this->h.data;
+ this->fs_off=(u8 *)this->data_pspec->packetspec;
+ this->fs_bytes=0;
+ this->echo_mac=(u8 *)this->data_echo->payload_and_mac;
+ this->echo_bytes=0;
+
+ /* Some safe initializations */
+ this->setVersion(ECHO_CURRENT_PROTO_VER);
+ this->setTotalLength(STD_NEP_HEADER_LEN + MAC_LENGTH);
+ this->length=STD_NEP_HEADER_LEN + MAC_LENGTH; /* Sets length in PacketElement superclass */
+} /* End of reset() */
+
+
+/** @warning This method is essential for the superclass getBinaryBuffer()
+ * method to work. Do NOT change a thing unless you know what you're doing. */
+u8 * EchoHeader::getBufferPointer(){
+ return (u8*)(&h);
+} /* End of getBufferPointer() */
+
+
+/** Stores supplied packet in the internal buffer so the information
+ * can be accessed using the standard get & set methods. */
+int EchoHeader::storeRecvData(const u8 *buf, size_t len){
+ if(buf==NULL || len>(STD_NEP_HEADER_LEN+MAX_DATA_LEN)){
+ return OP_FAILURE;
+ }else{
+ this->reset(); /* Re-init the object, just in case the caller had used it already */
+ this->length=len;
+ memcpy(&(this->h), buf, len);
+ }
+ return OP_SUCCESS;
+} /* End of storeRecvData() */
+
+
+/* Returns a protocol identifier. This is used by packet parsing functions
+ * that return linked lists of PacketElement objects, to determine the protocol
+ * the object represents. */
+int EchoHeader::protocol_id() const {
+ return HEADER_TYPE_NEP;
+} /* End of protocol_id() */
+
+
+/** Sets Version.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setVersion(u8 val){
+ this->h.echo_ver=val;
+ return OP_SUCCESS;
+} /* End of setVersion() */
+
+
+/** Returns value of attribute h.echo_ver */
+u8 EchoHeader::getVersion(){
+ return this->h.echo_ver;
+} /* End of getVersion() */
+
+
+/** Sets MessageType.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setMessageType(u8 val){
+ this->h.echo_mtype=val;
+ return OP_SUCCESS;
+} /* End of setMessageType() */
+
+
+/** Returns value of attribute h.echo_mtype */
+u8 EchoHeader::getMessageType(){
+ return this->h.echo_mtype;
+} /* End of getsetMessageType() */
+
+
+/** Sets Total Length.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error.
+ * @warning the length is expressed in 32bit words. */
+int EchoHeader::setTotalLength(u16 val){
+ this->h.echo_tlen=htons(val);
+ this->length=val*4; /* Also, set superclass length attribute */
+ return OP_SUCCESS;
+} /* End of setTotalLength() */
+
+
+/** Sets Total Length.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setTotalLength(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_SERVER:
+ this->setTotalLength(NEP_HANDSHAKE_SERVER_LEN/4);
+ break;
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ this->setTotalLength(NEP_HANDSHAKE_CLIENT_LEN/4);
+ break;
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ this->setTotalLength(NEP_HANDSHAKE_FINAL_LEN/4);
+ break;
+ case TYPE_NEP_PACKET_SPEC:
+ this->setTotalLength(NEP_PACKETSPEC_LEN/4);
+ break;
+ case TYPE_NEP_READY:
+ this->setTotalLength(NEP_READY_LEN/4);
+ break;
+ case TYPE_NEP_ECHO:
+ this->setTotalLength( (STD_NEP_HEADER_LEN + 4 + MAC_LENGTH + this->echo_bytes)/4 );
+ break;
+ case TYPE_NEP_ERROR:
+ this->setTotalLength(NEP_ERROR_LEN/4);
+ break;
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of setTotalLength() */
+
+
+/** Returns value of attribute h.echo_tlen
+ * @warning Returned length is expressed in 32bit words. To get a byte count
+ * it must be multiplied by four */
+u16 EchoHeader::getTotalLength(){
+ return ntohs(this->h.echo_tlen);
+} /* End of getTotalLength() */
+
+
+/** Sets SequenceNumber.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setSequenceNumber(u32 val){
+ this->h.echo_seq=htonl(val);
+ return OP_SUCCESS;
+} /* End of setSequenceNumber() */
+
+
+/** Returns value of attribute h.echo_seq */
+u32 EchoHeader::getSequenceNumber(){
+ return ntohl(this->h.echo_seq);
+} /* End of getSequenceNumber() */
+
+
+/** Sets Timestamp.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setTimestamp(u32 val){
+ this->h.echo_ts=htonl(val);
+ return OP_SUCCESS;
+} /* End of setTimestamp() */
+
+
+/** Sets Timestamp.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setTimestamp(){
+ u32 t=(u32)time(NULL); /* TODO: Make sure this does not cause problems */
+ this->h.echo_ts=htonl(t);
+ return OP_SUCCESS;
+} /* End of setTimestamp() */
+
+
+/** Returns value of attribute h.echo_ts*/
+u32 EchoHeader::getTimestamp(){
+ return ntohl(this->h.echo_ts);
+} /* End of getTimestamp() */
+
+
+/** Sets Reserved.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int EchoHeader::setReserved(u32 val){
+ this->h.echo_res=htonl(val);
+ return OP_SUCCESS;
+} /* End of setReserved() */
+
+
+/** Returns value of attribute h.echo_res */
+u32 EchoHeader::getReserved(){
+ return this->h.echo_res;
+} /* End of getReserved() */
+
+
+int EchoHeader::setMessageAuthenticationCode(u8 *key, size_t keylen){
+ u8 *macpnt=NULL;
+ u8 *from=(u8 *)&(this->h);
+ size_t bytes=0;
+
+ /* Determine where the MAC field is and the length of the data that needs
+ * to be authenticated, based on message type. */
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_SERVER:
+ macpnt=this->data_hsserv->mac;
+ bytes=NEP_HANDSHAKE_SERVER_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ macpnt=this->data_hsclnt->mac;
+ bytes=NEP_HANDSHAKE_CLIENT_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ macpnt=this->data_hsfinal->mac;
+ bytes=NEP_HANDSHAKE_FINAL_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_PACKET_SPEC:
+ macpnt=this->data_pspec->mac;
+ bytes=NEP_PACKETSPEC_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_READY:
+ macpnt=this->data_ready->mac;
+ bytes=NEP_READY_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_ECHO:
+ macpnt=this->echo_mac;
+ bytes=STD_NEP_HEADER_LEN + 4 + this->echo_bytes;
+ break;
+ case TYPE_NEP_ERROR:
+ macpnt=this->data_error->mac;
+ bytes=NEP_ERROR_LEN-MAC_LENGTH;
+ break;
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ /* Compute the code */
+ Crypto::hmac_sha256(from, bytes, macpnt, key, keylen);
+ return OP_SUCCESS;
+} /* End of setMessageAuthenticationCode() */
+
+
+u8 *EchoHeader::getMessageAuthenticationCode(){
+switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_SERVER:
+ return this->data_hsserv->mac;
+ break;
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ return this->data_hsclnt->mac;
+ break;
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ return this->data_hsfinal->mac;
+ break;
+ case TYPE_NEP_PACKET_SPEC:
+ return this->data_pspec->mac;
+ break;
+ case TYPE_NEP_READY:
+ return this->data_ready->mac;
+ break;
+ case TYPE_NEP_ECHO:
+ this->updateEchoInternals();
+ return this->echo_mac;
+ break;
+ case TYPE_NEP_ERROR:
+ return this->data_error->mac;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+ return NULL;
+} /* End of getMessageAuthenticationCode() */
+
+
+
+int EchoHeader::verifyMessageAuthenticationCode(u8 *key, size_t keylen){
+ u8 mac_backup[MAC_LENGTH];
+ u8 *aux;
+
+ /* Make a copy of the current MAC */
+ if( (aux=this->getMessageAuthenticationCode())==NULL )
+ return OP_FAILURE;
+ memcpy(mac_backup, aux, MAC_LENGTH);
+
+ /* Recompute the MAC */
+ memset(aux, 0, MAC_LENGTH);
+ this->setMessageAuthenticationCode(key, keylen);
+
+ /* Try to match both MACs*/
+ if( (aux=this->getMessageAuthenticationCode())==NULL )
+ return OP_FAILURE;
+ if( memcmp(mac_backup, aux, MAC_LENGTH)==0 ){
+ return OP_SUCCESS;
+ }else{
+ /* Restore original MAC */
+ memcpy(aux, mac_backup, MAC_LENGTH);
+ return OP_FAILURE;
+ }
+} /* End of verifyMessageAuthenticationCode() */
+
+/******************************************************************************/
+/* NEP_HANDSHAKE methods */
+/******************************************************************************/
+
+int EchoHeader::setServerNonce(u8 *nonce){
+ assert(nonce);
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_SERVER:
+ memcpy(this->data_hsserv->server_nonce, nonce, NONCE_LEN);
+ break;
+
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memcpy(this->data_hsclnt->server_nonce, nonce, NONCE_LEN);
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of getServerNonce() */
+
+
+u8 *EchoHeader::getServerNonce(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_SERVER:
+ return this->data_hsserv->server_nonce;
+ break;
+
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ return this->data_hsclnt->server_nonce;
+ break;
+
+ default:
+ return NULL;
+ break;
+ }
+} /* End of getServerNonce() */
+
+
+int EchoHeader::setClientNonce(u8 *nonce){
+ assert(nonce);
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memcpy(this->data_hsclnt->client_nonce, nonce, NONCE_LEN);
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ memcpy(this->data_hsfinal->client_nonce , nonce, NONCE_LEN);
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of getClientNonce() */
+
+
+u8 *EchoHeader::getClientNonce(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ return this->data_hsclnt->client_nonce;
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ return this->data_hsfinal->client_nonce;
+ break;
+
+ default:
+ return NULL;
+ break;
+ }
+} /* End of getClientNonce() */
+
+
+int EchoHeader::setPartnerAddress(struct in_addr val){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memset(this->data_hsclnt->partner_ip, 0, 16);
+ memcpy(this->data_hsclnt->partner_ip , &val, sizeof(struct in_addr));
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ memset(this->data_hsfinal->partner_ip, 0, 16);
+ memcpy(this->data_hsfinal->partner_ip , &val, sizeof(struct in_addr));
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ this->setIPVersion(0x04);
+ return OP_SUCCESS;
+} /* End of setPartnerAddress() */
+
+
+int EchoHeader::setPartnerAddress(struct in6_addr val){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memset(this->data_hsclnt->partner_ip, 0, 16);
+ memcpy(this->data_hsclnt->partner_ip , &val, sizeof(struct in6_addr));
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ memset(this->data_hsfinal->partner_ip, 0, 16);
+ memcpy(this->data_hsfinal->partner_ip , &val, sizeof(struct in6_addr));
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ this->setIPVersion(0x06);
+ return OP_SUCCESS;
+} /* End of setPartnerAddress() */
+
+
+int EchoHeader::getPartnerAddress(struct in_addr *dst){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memcpy(dst, this->data_hsclnt->partner_ip,sizeof(struct in_addr));
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ memcpy(dst, this->data_hsfinal->partner_ip,sizeof(struct in_addr));
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of getPartnerAddress() */
+
+
+int EchoHeader::getPartnerAddress(struct in6_addr *dst){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ memcpy(dst, this->data_hsclnt->partner_ip,sizeof(struct in6_addr));
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ memcpy(dst, this->data_hsfinal->partner_ip,sizeof(struct in6_addr));
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of getPartnerAddress() */
+
+
+/* On failure, it returns 0xAB */
+u8 EchoHeader::getIPVersion(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ return this->data_hsclnt->ip_version;
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ return this->data_hsfinal->ip_version;
+ break;
+
+ case TYPE_NEP_PACKET_SPEC:
+ return this->data_pspec->ip_version;
+ break;
+
+ default:
+ return 0xAB;
+ break;
+ }
+} /* End of getIPVersion() */
+
+
+int EchoHeader::setIPVersion(u8 ver){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ this->data_hsclnt->ip_version=ver;
+ break;
+
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ this->data_hsfinal->ip_version=ver;
+ break;
+
+ case TYPE_NEP_PACKET_SPEC:
+ this->data_pspec->ip_version=ver;
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of setIPVersion() */
+
+
+
+/******************************************************************************/
+/* NEP_PACKET_SPEC methods */
+/******************************************************************************/
+
+int EchoHeader::setProtocol(u8 proto){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_PACKET_SPEC:
+ this->data_pspec->protocol=proto;
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of setProtocol() */
+
+
+/* On failure, it returns 0xAB */
+u8 EchoHeader::getProtocol(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_PACKET_SPEC:
+ return this->data_pspec->protocol;
+ break;
+
+ default:
+ return 0xAB;
+ break;
+ }
+} /* End of setProtocol() */
+
+
+int EchoHeader::setPacketCount(u16 c){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_PACKET_SPEC:
+ this->data_pspec->packet_count=htons(c);
+ break;
+
+ default:
+ return OP_FAILURE;
+ break;
+ }
+ return OP_SUCCESS;
+} /* End of setPacketCount() */
+
+
+/* On failure, it returns 0 */
+u16 EchoHeader::getPacketCount(){
+ switch( this->getMessageType() ){
+ case TYPE_NEP_PACKET_SPEC:
+ return ntohs(this->data_pspec->packet_count);
+ break;
+
+ default:
+ return 0;
+ break;
+ }
+} /* End of getPacketCount() */
+
+
+int EchoHeader::getFieldLength(u8 field){
+ switch(field){
+ /* 8bit fields */
+ case PSPEC_IPv4_TOS:
+ case PSPEC_IPv4_PROTO:
+ case PSPEC_IPv6_FLOW:
+ case PSPEC_IPv6_NHDR:
+ case PSPEC_TCP_FLAGS:
+ case PSPEC_ICMP_TYPE:
+ case PSPEC_ICMP_CODE:
+ return 1;
+ break;
+
+ /* 16bit fields */
+ case PSPEC_IPv4_ID:
+ case PSPEC_IPv4_FRAGOFF:
+ case PSPEC_TCP_SPORT:
+ case PSPEC_TCP_DPORT:
+ case PSPEC_TCP_WIN:
+ case PSPEC_TCP_URP:
+ case PSPEC_UDP_SPORT:
+ case PSPEC_UDP_DPORT:
+ case PSPEC_UDP_LEN:
+ return 2;
+ break;
+
+ /* 24bit fields */
+ case PSPEC_IPv6_TCLASS:
+ return 3;
+ break;
+
+ /* 32bit fields */
+ case PSPEC_TCP_SEQ:
+ case PSPEC_TCP_ACK:
+ return 4;
+ break;
+
+ /* Error */
+ case PSPEC_PAYLOAD_MAGIC:
+ default:
+ return -1;
+ break;
+ }
+} /* End of getFieldLength() */
+
+
+int EchoHeader::addFieldSpec(u8 field, u8 *val){
+ int flen;
+ /* Determine the length of the field */
+ if( (flen=this->getFieldLength(field))==-1 || val==NULL )
+ return OP_FAILURE;
+ else{
+ return this->addFieldSpec(field, val, flen);
+ }
+} /* End of addFieldSpec() */
+
+
+int EchoHeader::addFieldSpec(u8 field, u8 *val, size_t flen){
+ if( val==NULL ){
+ return OP_FAILURE;
+ }else{
+ /* Store the field spec and update internal pointers and counts */
+ if( (this->fs_bytes+flen) < PACKETSPEC_FIELD_LEN ){
+ *(this->fs_off)=field;
+ if(field==PSPEC_PAYLOAD_MAGIC){
+ /* Check length again since this field requires an extra byte */
+ if(this->fs_bytes+flen+1 < PACKETSPEC_FIELD_LEN){
+ *(this->fs_off+1)=flen;
+ memcpy(this->fs_off+2, val, flen);
+ this->fs_off+=(flen+2);
+ this->fs_bytes+=(flen+2);
+ }else{
+ return OP_FAILURE;
+ }
+ }else{
+ memcpy(this->fs_off+1, val, flen);
+ this->fs_off+=(flen+1);
+ this->fs_bytes+=(flen+1);
+ }
+ }else{
+ return OP_FAILURE;
+ }
+ }
+ return OP_SUCCESS;
+} /* End of addFieldSpec() */
+
+
+int EchoHeader::rewindFieldSpecCounters(){
+ this->fs_off=(u8 *)this->data_pspec->packetspec;
+ this->fs_bytes=0;
+ return OP_SUCCESS;
+} /* rewindFieldSpecCounters */
+
+/** @warning dst_buff must be able to hold at least (PACKETSPEC_FIELD_LEN-2) bytes. */
+int EchoHeader::getNextFieldSpec(u8 *field, u8 *dst_buff, size_t *final_len){
+ u8 nfield=0;
+ int nlen=0;
+ if(field==NULL || dst_buff==NULL || this->fs_bytes>=PACKETSPEC_FIELD_LEN)
+ return OP_FAILURE;
+ /* Determine which is the next field specifier */
+ nfield=*(this->fs_off);
+ if(nfield==PSPEC_PAYLOAD_MAGIC){
+ nlen=(int)*(this->fs_off+1); /* Read length from the packet */
+ if(nlen<=0 || nlen>(PACKETSPEC_FIELD_LEN-2) )
+ return OP_FAILURE;
+ else if( this->fs_bytes+2+nlen>PACKETSPEC_FIELD_LEN)
+ return OP_FAILURE;
+ else
+ memcpy(dst_buff, this->fs_off+2, nlen);
+ this->fs_off+=(nlen+2);
+ this->fs_bytes+=(nlen+2);
+ }else{
+ if((nlen=this->getFieldLength(nfield))<=0) /* Determine field length */
+ return OP_FAILURE;
+ else if(this->fs_bytes+1+nlen>PACKETSPEC_FIELD_LEN)
+ return OP_FAILURE;
+ else
+ memcpy(dst_buff, this->fs_off+1, nlen);
+ this->fs_off+=(nlen+1);
+ this->fs_bytes+=(nlen+2);
+ }
+ /* Store data */
+ *field=nfield;
+ if(final_len!=NULL)
+ *final_len=nlen;
+ return OP_SUCCESS;
+} /* End of getNextFieldSpec() */
+
+
+/******************************************************************************/
+/* NEP_PACKET_ECHO methods */
+/******************************************************************************/
+int EchoHeader::setDLT(u16 dlt){
+ this->data_echo->dlt_type=htons(dlt);
+ return OP_SUCCESS;
+} /* End of setDLT() */
+
+
+u16 EchoHeader::getDLT(){
+ return ntohs(this->data_echo->dlt_type);
+} /* End of getDLT() */
+
+
+int EchoHeader::setPacketLength(u16 len){
+ this->data_echo->packet_len=htons(len);
+ return OP_SUCCESS;
+} /* End of setPacketLength() */
+
+
+u16 EchoHeader::getPacketLength(){
+ return ntohs(this->data_echo->packet_len);
+} /* End of setPacketLength() */
+
+
+int EchoHeader::setEchoedPacket(const u8 *pkt, size_t pktlen){
+ int padding=0;
+ if(pkt==NULL)
+ return OP_FAILURE;
+ if(pktlen>MAX_ECHOED_PACKET_LEN){
+ pktlen=MAX_ECHOED_PACKET_LEN;
+ }
+ memcpy(this->data_echo->payload_and_mac, pkt, pktlen);
+ if((pktlen+4)%16!=0){
+ padding=16-((pktlen+4)%16);
+ memset(this->data_echo->payload_and_mac+pktlen, 0, padding);
+ }
+ this->echo_bytes=pktlen+padding;
+ this->echo_mac+=pktlen+padding;
+ /* Set the packet length field automatically */
+ this->setPacketLength((u16)pktlen);
+ this->length = STD_NEP_HEADER_LEN + 4 + this->echo_bytes + MAC_LENGTH;
+ assert(this->length%16==0);
+ return OP_SUCCESS;
+} /* End of setEchoedPacket() */
+
+
+/* @warning value stored in final_len is not exactly the actual length of the
+ * returned buffer but the value stored in the "Packet Length" field of the
+ * NEP_ECHO message. The caller is supposed to validate received packets before
+ * trusting that length */
+u8 *EchoHeader::getEchoedPacket(u16 *final_len){
+ if(final_len!=NULL)
+ *final_len=this->getPacketLength();
+ return this->data_echo->payload_and_mac;
+} /* End of getEchoedPacket() */
+
+
+u8 *EchoHeader::getEchoedPacket(){
+ return this->getEchoedPacket(NULL);
+} /* End of getEchoedPacket() */
+
+
+/** This method tries to update the object's internal counters for a NEP_ECHO
+ * packet. This should be used when storing a received NEP_ECHO message in
+ * the object. In that case, the internal pointers will not be set up
+ * correctly, as the object did not construct the message. Calling this method
+ * should fix the internal state of the object and make things like
+ * verifyMessageAuthenticationCode() work. */
+int EchoHeader::updateEchoInternals(){
+ if( this->getMessageType()!=TYPE_NEP_ECHO )
+ return OP_FAILURE;
+
+ /* Fix echo bytes length */
+ this->echo_bytes=this->getPacketLength();
+ if((this->echo_bytes+4)%16!=0){
+ this->echo_bytes+=16-((this->echo_bytes+4)%16);
+ }
+ /* Fix MAC offset */
+ this->echo_mac=((u8 *)this->data_echo->payload_and_mac)+this->echo_bytes;
+ return OP_SUCCESS;
+} /* End of updateEchoInternals() */
+
+
+/******************************************************************************/
+/* NEP_ERROR methods */
+/******************************************************************************/
+
+/** @warning error strings longer than MAX_NEP_ERROR_MSG_LEN-1 will be truncated */
+int EchoHeader::setErrorMessage(const char *err){
+ if(err==NULL){
+ return OP_FAILURE;
+ }else{
+ strncpy((char *)this->data_error->errmsg, err, ERROR_MSG_LEN);
+ this->data_error->errmsg[ERROR_MSG_LEN-1]='\0';
+ }
+ return OP_SUCCESS;
+} /* End of setErrorMessage() */
+
+/* @warning Returned pointer, points to the start of the "Error Message" field
+ * of the NEP_ERROR message. When receiving this kind of messages, there is no
+ * guarantee that the field contains printable characters, or that it is NULL
+ * terminated. The caller should validate it's contents. It is safe to read
+ * MAX_NEP_ERROR_MSG_LEN bytes from the start of the returned buffer pointer. */
+char *EchoHeader::getErrorMessage(){
+ return (char *)this->data_error->errmsg;
+} /* End of getErrorMessage() */
+
+
+/******************************************************************************/
+/* CRYPTOGRAPHY */
+/******************************************************************************/
+
+
+
+u8 *EchoHeader::getCiphertextBounds(size_t *final_len){
+ return this->getCiphertextBounds(final_len, this->getMessageType());
+}
+
+
+u8 *EchoHeader::getCiphertextBounds(size_t *final_len, int message_type){
+ u8 *start=NULL;
+ size_t len=0;
+
+ switch( message_type ){
+ case TYPE_NEP_HANDSHAKE_SERVER: /* this msg is never transmitted encrypted */
+ len=0;
+ start=(u8 *)&this->h;
+ break;
+ case TYPE_NEP_HANDSHAKE_CLIENT:
+ start=this->data_hsclnt->partner_ip;
+ len=32;
+ break;
+ case TYPE_NEP_HANDSHAKE_FINAL:
+ start=this->data_hsfinal->partner_ip;
+ len=32;
+ break;
+ case TYPE_NEP_PACKET_SPEC:
+ start=(u8 *)(&this->h);
+ len=NEP_PACKETSPEC_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_READY:
+ start=(u8 *)(&this->h);
+ len=NEP_READY_LEN-MAC_LENGTH;
+ break;
+ case TYPE_NEP_ECHO:
+ start=(u8 *)(&this->h);
+ len=this->length-MAC_LENGTH;
+ break;
+ case TYPE_NEP_ERROR:
+ start=(u8 *)(&this->h);
+ len=NEP_ERROR_LEN-MAC_LENGTH;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ if(final_len!=NULL)
+ *final_len=len;
+ return start;
+} /* End of getCiphertextBounds() */
+
+
+
+/** Encrypts the NEP message using the supplied key and initialization vector.
+ * On success it returns a pointer to the beginning of the last ciphertext
+ * block. This should be stored by the caller and used as the IV for the
+ * next encrypted data. It returns NULL in case of error. */
+u8 *EchoHeader::encrypt(u8 *key, size_t key_len, u8 *iv){
+ nping_print(DBG_4, "%s(%p, %lu, %p)", __func__, key, (long unsigned)key_len, iv);
+ u8 *start=NULL;
+ size_t len=0;
+
+ if(key==NULL || key_len==0 || iv==NULL)
+ return NULL;
+
+ if((start=this->getCiphertextBounds(&len))==NULL)
+ return NULL;
+
+ if(len>=CIPHER_BLOCK_SIZE){
+ if( Crypto::aes128_cbc_encrypt(start, len, (u8 *)(&this->h_tmp), key, key_len, iv) != OP_SUCCESS )
+ return NULL;
+ else{
+ memcpy(start, &this->h_tmp, len);
+ return (start+(len-CIPHER_BLOCK_SIZE));
+ }
+ }else{
+ return NULL;
+ }
+} /* End of encrypt() */
+
+
+u8 *EchoHeader::decrypt(u8 *key, size_t key_len, u8 *iv, int message_type){
+ nping_print(DBG_4, "%s(%p, %lu, %p)", __func__, key, (long unsigned)key_len, iv);
+ u8 *start=NULL;
+ size_t len=0;
+ static u8 lastblock[CIPHER_BLOCK_SIZE];
+
+ if(key==NULL || key_len==0 || iv==NULL)
+ return NULL;
+
+ if((start=this->getCiphertextBounds(&len, message_type))==NULL)
+ return NULL;
+
+ if(len>=CIPHER_BLOCK_SIZE){
+ /* Keep a copy of the last ciphertext block */
+ memcpy(lastblock, start+len-CIPHER_BLOCK_SIZE, CIPHER_BLOCK_SIZE);
+ if( Crypto::aes128_cbc_decrypt(start, len, (u8 *)(&this->h_tmp), key, key_len, iv) != OP_SUCCESS )
+ return NULL;
+ else{
+ memcpy(start, &this->h_tmp, len);
+ return lastblock;
+ }
+ }else{
+ return NULL;
+ }
+} /* End of decrypt() */
diff --git a/nping/EchoHeader.h b/nping/EchoHeader.h
new file mode 100644
index 0000000..4f7f7e4
--- /dev/null
+++ b/nping/EchoHeader.h
@@ -0,0 +1,331 @@
+
+/***************************************************************************
+ * EchoHeader.h -- The EchoHeader Class represents packets of the Nping *
+ * Echo Protocol. It contains the appropriate methods to set/get all *
+ * header fields. In general these methods do error checking and perform *
+ * byte order conversions. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef __ECHOHEADER_H__
+#define __ECHOHEADER_H__ 1
+
+#include "nping.h"
+
+#define ECHO_CURRENT_PROTO_VER 0x01
+
+/* Lengths */
+#define STD_NEP_HEADER_LEN 16 /* Common NEP header length */
+#define MAC_LENGTH 32 /* Length of message authentication codes */
+#define NONCE_LEN 32 /* Length of client/server nonces */
+#define PARTNER_IP_LEN 16 /* Length of Partner IP field */
+#define PACKETSPEC_FIELD_LEN 108 /* Length of the packet specification */
+#define ERROR_MSG_LEN 80 /* Length of NEP_ERROR message strings */
+
+#define NEP_HANDSHAKE_SERVER_LEN 96
+#define NEP_HANDSHAKE_CLIENT_LEN 144
+#define NEP_HANDSHAKE_FINAL_LEN 112
+#define NEP_PACKETSPEC_LEN 160
+#define NEP_READY_LEN 48
+#define NEP_ERROR_LEN 128
+
+#define ECHOED_PKT_HEADER_LEN 4 /* Length of {DLT Type, Packet Length} */
+#define MAX_ECHOED_PACKET_LEN 9212 /* Max length for echoed packets */
+#define MAX_DATA_LEN (ECHOED_PKT_HEADER_LEN + MAX_ECHOED_PACKET_LEN + MAC_LENGTH)
+#define NEP_ECHO_MIN_LEN 64
+#define NEP_ECHO_MAX_LEN ( STD_NEP_HEADER_LEN + MAX_DATA_LEN )
+#define MAX_NEP_PACKET_LENGTH ( STD_NEP_HEADER_LEN + MAX_DATA_LEN )
+
+/* Message types */
+#define TYPE_NEP_HANDSHAKE_SERVER 0x01
+#define TYPE_NEP_HANDSHAKE_CLIENT 0x02
+#define TYPE_NEP_HANDSHAKE_FINAL 0x03
+#define TYPE_NEP_PACKET_SPEC 0x04
+#define TYPE_NEP_READY 0x05
+#define TYPE_NEP_ECHO 0x06
+#define TYPE_NEP_ERROR 0x07
+
+/* Field specifiers */
+#define PSPEC_IPv4_TOS 0xA0
+#define PSPEC_IPv4_ID 0xA1
+#define PSPEC_IPv4_FRAGOFF 0xA2
+#define PSPEC_IPv4_PROTO 0xA3
+#define PSPEC_IPv6_TCLASS 0xB0
+#define PSPEC_IPv6_FLOW 0xB1
+#define PSPEC_IPv6_NHDR 0xB2
+#define PSPEC_TCP_SPORT 0xC0
+#define PSPEC_TCP_DPORT 0xC1
+#define PSPEC_TCP_SEQ 0xC2
+#define PSPEC_TCP_ACK 0xC3
+#define PSPEC_TCP_FLAGS 0xC4
+#define PSPEC_TCP_WIN 0xC5
+#define PSPEC_TCP_URP 0xC6
+#define PSPEC_ICMP_TYPE 0xD0
+#define PSPEC_ICMP_CODE 0xD1
+#define PSPEC_UDP_SPORT 0xE0
+#define PSPEC_UDP_DPORT 0xE1
+#define PSPEC_UDP_LEN 0xE2
+#define PSPEC_PAYLOAD_MAGIC 0xFF
+
+/* Protocol identifiers for NEP_PACKET_SPEC */
+#define PSPEC_PROTO_TCP 0x06
+#define PSPEC_PROTO_UDP 0x11
+#define PSPEC_PROTO_ICMP 0x01
+
+#define DLT_NODATALINKHEADERINCLUDED 0x0000
+
+/* GENERAL FORMAT:
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . DATA .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Message Authentication Code .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ */
+
+
+class EchoHeader : public ApplicationLayerElement {
+
+ private:
+
+ /* Common NEP packet header */
+ struct nep_hdr{
+ u8 echo_ver; /**< Protocol Version */
+ u8 echo_mtype; /**< Message Type */
+ u16 echo_tlen; /**< Total Length */
+ u32 echo_seq; /**< Sequence Number */
+ u32 echo_ts; /**< Timestamp */
+ u32 echo_res; /**< Reserved */
+ u8 data[MAX_DATA_LEN];
+ }__attribute__((__packed__));
+ typedef struct nep_hdr echohdr_t;
+
+ /* NEP_HANDSHAKE_SERVER data */
+ struct nep_hs_serv_data{
+ u8 server_nonce[NONCE_LEN];
+ u8 reserved[16];
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_hs_serv_data nep_hs_serv_data_t;
+
+ /* NEP_HANDSHAKE_CLIENT data */
+ struct nep_hs_clnt_data{
+ u8 server_nonce[NONCE_LEN];
+ u8 client_nonce[NONCE_LEN];
+ u8 partner_ip[PARTNER_IP_LEN];
+ u8 ip_version;
+ u8 reserved[15];
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_hs_clnt_data nep_hs_clnt_data_t;
+
+ /* NEP_HANDSHAKE_FINAL data */
+ struct nep_hs_final_data{
+ u8 client_nonce[NONCE_LEN];
+ u8 partner_ip[PARTNER_IP_LEN];
+ u8 ip_version;
+ u8 reserved[15];
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_hs_final_data nep_hs_final_data_t;
+
+ /* NEP_PACKET_SPEC data */
+ struct nep_packet_spec_data{
+ u8 ip_version;
+ u8 protocol;
+ u16 packet_count;
+ u8 packetspec[PACKETSPEC_FIELD_LEN];
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_packet_spec_data nep_packet_spec_data_t;
+
+ /* NEP_READY data */
+ struct nep_ready_data{
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_ready_data nep_ready_data_t;
+
+ /* NEP_ECHO data */
+ struct nep_echo_data{
+ u16 dlt_type;
+ u16 packet_len;
+ u8 payload_and_mac[MAX_ECHOED_PACKET_LEN + MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_echo_data nep_echo_data_t;
+
+ /* NEP_ERROR data */
+ struct nep_error_data{
+ u8 errmsg[ERROR_MSG_LEN];
+ u8 mac[MAC_LENGTH];
+ }__attribute__((__packed__));
+ typedef struct nep_error_data nep_error_data_t;
+
+ /* Attributes */
+ echohdr_t h;
+ echohdr_t h_tmp;
+ nep_hs_serv_data_t *data_hsserv;
+ nep_hs_clnt_data_t *data_hsclnt;
+ nep_hs_final_data_t *data_hsfinal;
+ nep_packet_spec_data_t *data_pspec;
+ nep_ready_data_t *data_ready;
+ nep_echo_data_t *data_echo;
+ u8 *echo_mac;
+ int echo_bytes;
+ nep_error_data_t *data_error;
+ u8 *fs_off; /**< Current field spec offset */
+ int fs_bytes; /**< Current field spec byte count */
+
+ private:
+ int getFieldLength(u8 field);
+
+ public:
+
+ EchoHeader();
+ ~EchoHeader();
+ void reset();
+ u8 *getBufferPointer();
+ int storeRecvData(const u8 *buf, size_t len);
+ int protocol_id() const;
+
+ int setVersion(u8 val);
+ u8 getVersion();
+
+ int setMessageType(u8 val);
+ u8 getMessageType();
+
+ int setTotalLength(u16 val);
+ int setTotalLength();
+ u16 getTotalLength();
+
+ int setSequenceNumber(u32 val);
+ u32 getSequenceNumber();
+
+ int setTimestamp(u32 val);
+ int setTimestamp();
+ u32 getTimestamp();
+
+ int setReserved(u32 val);
+ u32 getReserved();
+
+ int setMessageAuthenticationCode(u8 *key, size_t keylen);
+ u8 *getMessageAuthenticationCode();
+ int verifyMessageAuthenticationCode(u8 *key, size_t keylen);
+
+ int setServerNonce(u8 *nonce);
+ u8 *getServerNonce();
+
+ int setClientNonce(u8 *nonce);
+ u8 *getClientNonce();
+
+ int setPartnerAddress(struct in_addr val);
+ int setPartnerAddress(struct in6_addr val);
+ int getPartnerAddress(struct in_addr *dst);
+ int getPartnerAddress(struct in6_addr *dst);
+ int setIPVersion(u8 ver);
+ u8 getIPVersion();
+
+ int setProtocol(u8 proto);
+ u8 getProtocol();
+
+ int setPacketCount(u16 c);
+ u16 getPacketCount();
+
+ int addFieldSpec(u8 field, u8 *val);
+ int addFieldSpec(u8 field, u8 *val, size_t flen);
+ int getNextFieldSpec(u8 *field, u8 *dst_buff, size_t *final_len);
+ int rewindFieldSpecCounters();
+
+ int setDLT(u16 dlt);
+ u16 getDLT();
+
+ int setPacketLength(u16 len);
+ u16 getPacketLength();
+
+ int setEchoedPacket(const u8 *pkt, size_t pktlen);
+ u8 *getEchoedPacket(u16 *final_len);
+ u8 *getEchoedPacket();
+
+ int updateEchoInternals();
+
+ int setErrorMessage(const char *err);
+ char *getErrorMessage();
+
+ u8 *getCiphertextBounds(size_t *len);
+ u8 *getCiphertextBounds(size_t *final_len, int message_type);
+ u8 *encrypt(u8 *key, size_t key_len, u8 *iv);
+ u8 *decrypt(u8 *key, size_t key_len, u8 *iv, int message_type);
+};
+
+#endif /* __ECHOHEADER_H__ */
diff --git a/nping/EchoServer.cc b/nping/EchoServer.cc
new file mode 100644
index 0000000..b30a8fb
--- /dev/null
+++ b/nping/EchoServer.cc
@@ -0,0 +1,1567 @@
+
+/***************************************************************************
+ * EchoServer.cc -- *
+ * *
+ ***********************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 "EchoServer.h"
+#include "EchoHeader.h"
+#include "NEPContext.h"
+#include <vector>
+#include "nsock.h"
+#include "output.h"
+#include "NpingOps.h"
+#include "ProbeMode.h"
+#include <signal.h>
+
+extern NpingOps o;
+extern EchoServer es;
+
+EchoServer::EchoServer() {
+ this->reset();
+} /* End of EchoServer constructor */
+
+
+EchoServer::~EchoServer() {
+} /* End of EchoServer destructor */
+
+
+/** Sets every attribute to its default value- */
+void EchoServer::reset() {
+ this->client_ctx.clear();
+ this->client_id_count=-1;
+} /* End of reset() */
+
+
+/** Adds a new client context object to the server context list */
+int EchoServer::addClientContext(NEPContext ctx){
+ nping_print(DBG_4, "%s(ctx->id=%d)", __func__, ctx.getIdentifier());
+ this->client_ctx.push_back(ctx);
+ return OP_SUCCESS;
+} /* End of addClientContext() */
+
+
+/** Looks up the context of a given client, based on the supplied client ID.
+ * On success, it returns a pointer to the client's context object. NULL is
+ * returned when no context could be found. */
+NEPContext *EchoServer::getClientContext(clientid_t clnt){
+ nping_print(DBG_4, "%s(%d) %lu", __func__, clnt, (unsigned long)this->client_ctx.size());
+ for(unsigned int i=0; i<this->client_ctx.size(); i++){
+ if(this->client_ctx[i].getIdentifier() == clnt ){
+ nping_print(DBG_3, "Found client with ID #%d at p%d. Total clients %lu", clnt, i, (unsigned long)this->client_ctx.size());
+ return &(this->client_ctx[i]);
+ }
+ }
+ nping_print(DBG_3, "No client with ID #%d was found. Total clients %lu", clnt, (unsigned long)this->client_ctx.size());
+ return NULL;
+} /* End of getClientContext() */
+
+
+/** Looks up the context of a given client, based on the supplied nsock IOD.
+ * On success, it returns a pointer to the client's context object. NULL is
+ * returned when no context could be found. */
+NEPContext *EchoServer::getClientContext(nsock_iod iod){
+ nping_print(DBG_4, "%s()", __func__);
+ clientid_t *id=NULL;
+ if( (id=(clientid_t *)nsock_iod_get_udata(iod))==NULL )
+ return NULL;
+ else
+ return this->getClientContext(*id);
+} /* End of getClientContext() */
+
+
+/** Deletes context information associated with a given client. Returns
+ * OP_SUCCESS if the context object was successfully deleted or OP_FAILURE if
+ * the context could not be found. */
+int EchoServer::destroyClientContext(clientid_t clnt){
+ bool deleted=false;
+ std::vector<NEPContext>::iterator it;
+ /* Iterate through the context array and delete the one that belongs to clnt */
+ for ( it=this->client_ctx.begin(); it<this->client_ctx.end(); it++){
+ if(it->getIdentifier()==clnt){
+ this->client_ctx.erase(it);
+ deleted=true;
+ break;
+ }
+ }
+ return (deleted) ? OP_SUCCESS : OP_FAILURE;
+} /* End of destroyClientContext() */
+
+
+/** Returns the Nsock IOD associated with a given client ID. */
+nsock_iod EchoServer::getClientNsockIOD(clientid_t clnt){
+ nping_print(DBG_4, "%s(%d)", __func__, clnt);
+ NEPContext *ctx;
+ if((ctx=this->getClientContext(clnt))==NULL )
+ return NULL;
+ else
+ return ctx->getNsockIOD();
+} /* End of getClientNsockIOD() */
+
+
+/** Generates a new client identifier. This is used internally by the echo
+ * server, but this value is never sent over the wire (it has nothing to do
+ * with the NEP protocol). Each call to getNewClientID() generates a new
+ * identifier, so it should only be called once per client session.
+ * Warning: This code checks for an overflow and wraps the client id count back
+ * to zero if necessary. A given execution of a server should be able to handle
+ * 4,294,967,296 client sessions. Practically there is no way to achieve that
+ * number (it would be something like receiving one client session per second
+ * for 136 years, so relax!) However, it should be noted that this
+ * implementation makes no effort to handle re-used client identifiers, so
+ * there is a tiny chance that after the 4,294,967,296th client, the assigned
+ * number conflicts with an active session ;-) */
+clientid_t EchoServer::getNewClientID(){
+ nping_print(DBG_4, "%s()", __func__);
+ if(this->client_id_count==0xFFFF) /* Wrap back to zero. */
+ this->client_id_count=0;
+ else
+ this->client_id_count++;
+ return this->client_id_count;
+} /* End of getNewClientID() */
+
+
+/** Returns a socket suitable to be passed to accept() */
+int EchoServer::nep_listen_socket(){
+ nping_print(DBG_4, "%s()", __func__);
+ int one=1; /**< Dummy var for setsockopt() call */
+ int master_sd=-1; /**< Master socket. Server listens on it */
+ struct sockaddr_in server_addr4; /**< For our own IPv4 address */
+ struct sockaddr_in6 server_addr6; /**< For our own IPv6 address */
+ int port = o.getEchoPort();
+
+ /* Ignore SIGPIPE signal, received when a client disconnects suddenly and
+ *data is sent to it before noticing. */
+ #ifndef WIN32
+ signal(SIGPIPE, SIG_IGN);
+ #endif
+
+ /* AF_INET6 */
+ if( o.ipv6() ){
+
+ /* Obtain a regular TCP socket for IPv6 */
+ if( (master_sd=socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP))<0 )
+ nping_fatal(QT_3, "Could not obtain AF_INET/SOCK_STREAM/IPPROTO_TCP socket");
+
+ /* Set SO_REUSEADDR on socket so the bind does not fail if we had used
+ * this port in a previous execution, not long ago. */
+ if( setsockopt(master_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int))!=0 )
+ nping_warning(QT_3, "Failed to set SO_REUSEADDR on master socket.");
+
+ memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
+ server_addr6.sin6_addr = (o.spoofSource()) ? o.getIPv6SourceAddress() : in6addr_any;
+ server_addr6.sin6_family = AF_INET6;
+ server_addr6.sin6_port = htons(port);
+ server_addr6.sin6_flowinfo = 0;
+ #ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
+ server_addr6.sin6_len = sizeof(struct sockaddr_in6);
+ #endif
+ /* Bind to local address and the specified port */
+ if( bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){
+ nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr6.sin6_addr), port);
+ /* If the bind failed for the supplied address, just try again with in6addr_any */
+ if( o.spoofSource() ){
+ server_addr6.sin6_addr = in6addr_any;
+ if( bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){
+ nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno));
+ }else{
+ nping_print(VB_1, "Server bound to port %d", port);
+ }
+ }
+ }else{
+ nping_print(VB_1, "Server bound to %s:%d", IPtoa(server_addr6.sin6_addr), port);
+ }
+
+
+ /* AF_INET */
+ }else{
+
+ /* Obtain a regular TCP socket for IPv4 */
+ if( (master_sd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0 )
+ nping_fatal(QT_3, "Could not obtain AF_INET/SOCK_STREAM/IPPROTO_TCP socket");
+
+ /* Set SO_REUSEADDR on socket so the bind does not fail if we had used
+ * this port in a previous execution, not long ago. */
+ if( setsockopt(master_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int))!=0 )
+ nping_warning(QT_3, "Failed to set SO_REUSEADDR on master socket.");
+
+
+ memset(&server_addr4, 0, sizeof(struct sockaddr_in));
+ server_addr4.sin_family = AF_INET;
+ server_addr4.sin_port = htons(port);
+ server_addr4.sin_addr.s_addr = (o.spoofSource()) ? o.getIPv4SourceAddress().s_addr : INADDR_ANY;
+#ifdef HAVE_SOCKADDR_IN_SIN_LEN
+ server_addr4.sin_len = sizeof(struct sockaddr_in);
+#endif
+
+ /* Bind to local address and the specified port */
+ if( bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){
+ nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr4.sin_addr), port);
+ /* If the bind failed for the supplied address, just try again with in6addr_any */
+ if( o.spoofSource() ){
+ server_addr4.sin_addr.s_addr=INADDR_ANY;
+ if( bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){
+ nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno));
+ }else{
+ nping_print(VB_1, "Server bound to port %d", port);
+ }
+ }
+ }else{
+ nping_print(VB_1, "Server bound to %s:%d", IPtoa(server_addr4.sin_addr), port);
+ }
+
+ }
+
+ /* Listen for incoming TCP connections... */
+ if( listen(master_sd, LISTEN_QUEUE_SIZE) != 0 ){
+ nping_fatal(QT_3, "[E] Failed to listen() on port %d (%s)", port, strerror(errno));
+ }
+ return master_sd;
+} /* End of nep_listen() */
+
+
+
+/* Weighting factors */
+#define FACTOR_IPv4_TOS 1.0
+#define FACTOR_IPv4_PROTO 0.9
+#define FACTOR_IPv4_ID 2.5
+#define FACTOR_IPv4_FRAGOFF 1.0
+#define FACTOR_IPv6_TCLASS 1.0
+#define FACTOR_IPv6_FLOW 2.5
+#define FACTOR_IPv6_NHDR 0.9
+#define FACTOR_TCP_SPORT 1.5
+#define FACTOR_TCP_DPORT 1.0
+#define FACTOR_TCP_SEQ 2.0
+#define FACTOR_TCP_ACK 1.0
+#define FACTOR_TCP_FLAGS 1.0
+#define FACTOR_TCP_WIN 1.0
+#define FACTOR_TCP_URP 1.0
+#define FACTOR_ICMP_TYPE 1.0
+#define FACTOR_ICMP_CODE 1.0
+#define FACTOR_UDP_SPORT 1.0
+#define FACTOR_UDP_DPORT 1.0
+#define FACTOR_UDP_LEN 1.0
+#define FACTOR_PAYLOAD_MAGIC 1.0
+
+#define ZERO_PENALTY 0.3
+
+#define MIN_ACCEPTABLE_SCORE_TCP 10.0
+#define MIN_ACCEPTABLE_SCORE_UDP 8.0
+#define MIN_ACCEPTABLE_SCORE_ICMP 6.0
+
+clientid_t EchoServer::nep_match_headers(IPv4Header *ip4, IPv6Header *ip6, TCPHeader *tcp, UDPHeader *udp, ICMPv4Header *icmp4, RawData *payload){
+ nping_print(DBG_4, "%s(%p,%p,%p,%p,%p,%p)", __func__, ip4, ip6, tcp, udp, icmp4, payload);
+ unsigned int i=0, k=0;
+ u8 *buff=NULL;
+ int bufflen=-1;
+ NEPContext *ctx;
+ fspec_t *fspec;
+ float current_score=0;
+ float candidate_score=-1;
+ float minimum_score=0;
+ clientid_t candidate=-1;
+
+ /* Iterate through the list of connected clients */
+ for(i=0; i<this->client_ctx.size(); i++ ){
+ current_score=0;
+ ctx=&(this->client_ctx[i]);
+ nping_print(DBG_2, "%s() Trying to match packet against client #%d", __func__, ctx->getIdentifier());
+ if( ctx->ready() ){
+ /* Iterate through client's list of packet field specifiers */
+ for(k=0; (fspec=ctx->getClientFieldSpec(k))!=NULL; k++){
+ switch(fspec->field){
+ case PSPEC_IPv4_TOS:
+ if(ip4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IP TOS", __func__);
+ if( ip4->getTOS()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] IP TOS=%02x", ip4->getTOS());
+ current_score += 1 * FACTOR_IPv4_TOS * ((ip4->getTOS()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_IPv4_PROTO:
+ if(ip4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IP Next Protocol", __func__);
+ if( ip4->getNextProto()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] IP Proto=%02x", ip4->getNextProto());
+ current_score += 1 * FACTOR_IPv4_PROTO;
+ }
+ break;
+ case PSPEC_IPv4_ID:
+ if(ip4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IP Identification", __func__);
+ if( ip4->getIdentification()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] IP Id=%u", ip4->getIdentification());
+ current_score += 2 * FACTOR_IPv4_ID;
+ }
+ break;
+ case PSPEC_IPv4_FRAGOFF:
+ if(ip4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IP Fragment offset", __func__);
+ if( ip4->getFragOffset()==ntohs( *((u16 *)fspec->value)) ){
+ nping_print(DBG_3, "[Match] IP FragOff=%u", ip4->getFragOffset() );
+ current_score += 2 * FACTOR_IPv4_FRAGOFF * ((ip4->getFragOffset()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+
+ case PSPEC_IPv6_TCLASS:
+ if(ip6==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IPv6 Traffic Class", __func__);
+ if( ip6->getTrafficClass()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] IPv6 TClass=%u", ip6->getTrafficClass() );
+ current_score += 1 * FACTOR_IPv6_TCLASS * ((ip6->getTrafficClass()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_IPv6_FLOW:
+ if(ip6==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IPv6 Flow Label", __func__);
+ if( ip6->getFlowLabel()==ntohl( *((u32 *)fspec->value)) ){
+ nping_print(DBG_3, "[Match] IPv6 Flow=%lu", (long unsigned)ip6->getFlowLabel() );
+ current_score += 3 * FACTOR_IPv6_FLOW * ((ip6->getFlowLabel()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_IPv6_NHDR:
+ if(ip6==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match IPv6 Next Header", __func__);
+ if( ip6->getNextHeader()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] IPv6 NextHdr=%02x", ip6->getNextHeader());
+ current_score += 1 * FACTOR_IPv6_NHDR;
+ }
+ break;
+ case PSPEC_TCP_SPORT:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Source Port", __func__);
+ if( tcp->getSourcePort()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Src=%u", tcp->getSourcePort());
+ current_score += 2 * FACTOR_TCP_SPORT;
+ }
+ break;
+ case PSPEC_TCP_DPORT:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Destination Port", __func__);
+ if( tcp->getDestinationPort()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Dst=%u", tcp->getDestinationPort());
+ current_score += 2 * FACTOR_TCP_DPORT;
+ }
+ break;
+ case PSPEC_TCP_SEQ:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Sequence Number", __func__);
+ if( tcp->getSeq()==ntohl( *((u32 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Seq=%u", tcp->getSeq());
+ current_score += 4 * FACTOR_TCP_SEQ * ((tcp->getSeq()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_TCP_ACK:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Acknowledgment", __func__);
+ if( tcp->getAck()==ntohl( *((u32 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Ack=%u", tcp->getAck());
+ current_score += 4 * FACTOR_TCP_ACK * ((tcp->getAck()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_TCP_FLAGS:
+ if(tcp==NULL)break;
+ if( tcp->getFlags()==fspec->value[0] ){
+ nping_print(DBG_3, "%s() Trying to match TCP Flags", __func__);
+ nping_print(DBG_3, "[Match] TCP Flags=%02x", tcp->getFlags());
+ current_score += 1 * FACTOR_TCP_FLAGS;
+ }
+ break;
+ case PSPEC_TCP_WIN:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Window", __func__);
+ if( tcp->getWindow()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Win=%u", tcp->getWindow());
+ current_score += 2 * FACTOR_TCP_WIN * ((tcp->getWindow()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_TCP_URP:
+ if(tcp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match TCP Urgent Pointer", __func__);
+ if( tcp->getUrgPointer()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] TCP Win=%u", tcp->getUrgPointer());
+ current_score += 2 * FACTOR_TCP_URP * ((tcp->getUrgPointer()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_ICMP_TYPE:
+ if(icmp4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match ICMPv4 Type", __func__);
+ if( icmp4->getType()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] ICMPv4 Type=%02x", icmp4->getType());
+ current_score += 1 * FACTOR_ICMP_TYPE;
+ }
+ break;
+ case PSPEC_ICMP_CODE:
+ if(icmp4==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match ICMPv4 Code", __func__);
+ if( icmp4->getCode()==fspec->value[0] ){
+ nping_print(DBG_3, "[Match] ICMPv4 Code=%02x", icmp4->getCode());
+ current_score += 1 * FACTOR_ICMP_CODE * ((icmp4->getCode()==0) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_UDP_SPORT:
+ if(udp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match UDP Source Port", __func__);
+ if( udp->getSourcePort()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] UDP Src=%u", udp->getSourcePort());
+ current_score += 2 * FACTOR_UDP_SPORT;
+ }
+ break;
+ case PSPEC_UDP_DPORT:
+ if(udp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match UDP Destination Port", __func__);
+ if( udp->getDestinationPort()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] UDP Dst=%u", udp->getDestinationPort());
+ current_score += 2 * FACTOR_UDP_DPORT;
+ }
+ break;
+ case PSPEC_UDP_LEN:
+ if(udp==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match UDP Length", __func__);
+ if( udp->getTotalLength()==ntohs( *((u16 *)fspec->value) ) ){
+ nping_print(DBG_3, "[Match] UDP Len=%u", udp->getTotalLength());
+ current_score += 2 * FACTOR_UDP_LEN * ((udp->getTotalLength()==8) ? ZERO_PENALTY : 1);
+ }
+ break;
+ case PSPEC_PAYLOAD_MAGIC:
+ if(payload==NULL)break;
+ nping_print(DBG_3, "%s() Trying to match Payload Magic value", __func__);
+ buff=payload->getBinaryBuffer(&bufflen);
+ if(buff==NULL || bufflen<=0 || fspec->len>bufflen)
+ break;
+ if( memcmp(buff, fspec->value, fspec->len)==0 ){
+ nping_print(DBG_3|NO_NEWLINE, "[Match] Payload magic=0x");
+ for(unsigned int i=0; i<fspec->len; i++)
+ nping_print(DBG_3|NO_NEWLINE,"%02x", fspec->value[i]);
+ nping_print(DBG_3, ";");
+ /* The payload magic may affect the score only between
+ * zero and 4 bytes. This is done to prevent long
+ * common strings like "GET / HTTP/1.1\r\n"
+ * increasing the score a lot and cause problems for
+ * the matching logic. */
+ current_score+= MIN(4, fspec->len)*FACTOR_PAYLOAD_MAGIC;
+ }
+ break;
+
+ default:
+ nping_warning(QT_2, "Bogus field specifier found in client #%d context. Please report a bug", ctx->getIdentifier());
+ break;
+ }
+ } /* End of field specifiers loop */
+
+ nping_print(DBG_3, "%s() current_score=%.02f candidate_score=%.02f", __func__, current_score, candidate_score);
+ if( (current_score>0) && (current_score>=candidate_score)){
+ candidate_score=current_score;
+ candidate=ctx->getIdentifier();
+ nping_print(DBG_3, "%s() Found better candidate (client #%d; score=%.02f)", __func__, candidate, candidate_score);
+ }
+ }
+ } /* End of connected clients loop */
+
+ if( tcp!=NULL )
+ minimum_score=MIN_ACCEPTABLE_SCORE_TCP;
+ else if (udp!=NULL)
+ minimum_score=MIN_ACCEPTABLE_SCORE_UDP;
+ else if(icmp4!=NULL)
+ minimum_score=MIN_ACCEPTABLE_SCORE_ICMP;
+ else
+ minimum_score=10000;
+
+ /* Check if we managed to match packet and client */
+ if (candidate>=0 && candidate_score>=minimum_score){
+ nping_print(DBG_2, "%s() Packet matched successfully with client #%d", __func__, candidate);
+ return candidate;
+ }else{
+ if(candidate<0)
+ nping_print(DBG_2, "%s() Couldn't match packet with any client.", __func__);
+ else
+ nping_print(DBG_2, "%s() Found matching client but score is too low. Discarded.", __func__);
+ return CLIENT_NOT_FOUND;
+ }
+ return CLIENT_NOT_FOUND;
+} /* End of nep_match_ipv4() */
+
+
+clientid_t EchoServer::nep_match_packet(const u8 *pkt, size_t pktlen){
+ nping_print(DBG_4, "%s(%p, %lu)", __func__, pkt, (long unsigned)pktlen);
+ int iplen=0, ip6len=0, tcplen=0, udplen=0;
+ bool payload_included=false;
+ IPv4Header ip4;
+ IPv6Header ip6;
+ TCPHeader tcp;
+ UDPHeader udp;
+ ICMPv4Header icmp4;
+ RawData payload;
+
+ if(this->client_id_count<0){
+ nping_print(DBG_1, "Error trying to match the packet. No clients connected.");
+ return CLIENT_NOT_FOUND;
+ }else if(pktlen<IP_HEADER_LEN){
+ nping_print(DBG_1, "Error trying to match the packet. Bogus packet received (too short)");
+ return CLIENT_NOT_FOUND;
+ }
+
+ /* Determine IP version */
+ if (ip4.storeRecvData(pkt, pktlen)==OP_FAILURE)
+ return CLIENT_NOT_FOUND;
+
+ if(ip4.getVersion()==0x04){
+
+ nping_print(DBG_2, "Recv packet is IPv4. Trying to find a matching client.");
+ if( (iplen=ip4.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ switch( ip4.getNextProto() ){
+ case 1: // ICMP
+ if( icmp4.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE )
+ return CLIENT_NOT_FOUND;
+ else
+ return this->nep_match_headers(&ip4, NULL, NULL, NULL, &icmp4, NULL);
+ break;
+
+ case 6: // TCP
+ if( tcp.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (tcplen=tcp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (iplen+tcplen) ){
+ if( payload.storeRecvData(pkt+iplen+tcplen, pktlen-iplen-tcplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, NULL, &tcp, NULL, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, NULL, &tcp, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ case 17: // UDP
+ if( udp.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (udplen=udp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (iplen+udplen) ){
+ if( payload.storeRecvData(pkt+iplen+udplen, pktlen-iplen-udplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, NULL, NULL, &udp, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, NULL, NULL, &udp, NULL, NULL);
+ }
+ }
+ break;
+
+ case 41: /* IPv6 encapsulated in the IPv4 datagram! */
+ if( ip6.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (ip6len=ip6.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ switch( ip6.getNextHeader() ){
+ case 58: // ICMPv6
+ nping_print(DBG_4, "Encapsulated IPv4{ IPv6{ ICMPv6 } } received. Not supported.");
+ return CLIENT_NOT_FOUND;
+ break;
+
+ case 6: // TCP
+ if( tcp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (tcplen=tcp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+iplen+tcplen) ){
+ if( payload.storeRecvData(pkt+ip6len+iplen+tcplen, pktlen-ip6len-iplen-tcplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ case 17: // UDP
+ if( udp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (udplen=udp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+iplen+udplen) ){
+ if( payload.storeRecvData(pkt+ip6len+iplen+udplen, pktlen-ip6len-iplen-udplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, NULL);
+ }
+ }
+ break;
+
+ default:
+ return CLIENT_NOT_FOUND;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ return CLIENT_NOT_FOUND;
+ break;
+ }
+ }
+ }else if(ip4.getVersion()==0x06){
+
+ nping_print(DBG_2, "Recv packet is IPv6. Trying to find a matching client.");
+ if (ip6.storeRecvData(pkt, pktlen)==OP_FAILURE)
+ return CLIENT_NOT_FOUND;
+
+ if( (ip6len=ip6.validate())==OP_FAILURE )
+ return CLIENT_NOT_FOUND;
+
+ switch( ip6.getNextHeader() ){
+ case 58: // ICMPv6
+ nping_print(DBG_4, "Received ICMPv6 packet. Not yet supported.");
+ return CLIENT_NOT_FOUND;
+ break;
+
+ case 6: // TCP
+ if( tcp.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (tcplen=tcp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+tcplen) ){
+ if( payload.storeRecvData(pkt+ip6len+tcplen, pktlen-ip6len-tcplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(NULL, &ip6, &tcp, NULL, NULL, &payload);
+ else
+ return this->nep_match_headers(NULL, &ip6, &tcp, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ case 17: // UDP
+ if( udp.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (udplen=udp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+udplen) ){
+ if( payload.storeRecvData(pkt+ip6len+udplen, pktlen-ip6len-udplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(NULL, &ip6, NULL, &udp, NULL, &payload);
+ else
+ return this->nep_match_headers(NULL, &ip6, NULL, &udp, NULL, NULL);
+ }
+ }
+ break;
+
+ case 4: /* IPv4 encapsulated in the IPv6 datagram */
+ if( ip4.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (iplen=ip4.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ switch( ip4.getNextProto() ){
+ case 1: // ICMP
+ if( icmp4.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE )
+ return CLIENT_NOT_FOUND;
+ else
+ return this->nep_match_headers(&ip4, &ip6, NULL, NULL, &icmp4, NULL);
+ break;
+
+ case 6: // TCP
+ if( tcp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (tcplen=tcp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+iplen+tcplen) ){
+ if( payload.storeRecvData(pkt+ip6len+iplen+tcplen, pktlen-ip6len-iplen-tcplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ case 17: // UDP
+ if( udp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (udplen=udp.validate())==OP_FAILURE){
+ return CLIENT_NOT_FOUND;
+ }else{
+ if( (int)pktlen > (ip6len+iplen+udplen) ){
+ if( payload.storeRecvData(pkt+ip6len+iplen+udplen, pktlen-ip6len-iplen-udplen)!=OP_FAILURE)
+ payload_included=true;
+ }
+ if(payload_included)
+ return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, &payload);
+ else
+ return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, NULL);
+ }
+ }
+ break;
+
+ default:
+ return CLIENT_NOT_FOUND;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ return CLIENT_NOT_FOUND;
+ break;
+ }
+ }else{
+ nping_print(DBG_2, "Received packet is not IP: Discarded.");
+ return CLIENT_NOT_FOUND;
+ }
+ return CLIENT_NOT_FOUND;
+} /* End of nep_match_packet() */
+
+
+int EchoServer::nep_capture_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ clientid_t clnt=CLIENT_NOT_FOUND;
+ const unsigned char *packet=NULL;
+ const unsigned char *link=NULL;
+ nsock_iod nsi = nse_iod(nse);
+ struct timeval pcaptime;
+ nsock_iod clnt_iod=NULL;
+ NEPContext *ctx=NULL;
+ EchoHeader pkt_out;
+ size_t linklen=0;
+ size_t packetlen=0;
+ handler_arg_t arg;
+ arg.me=this;
+ arg.param=NULL;
+
+ /* If there are connected clients, schedule another packet capture event */
+ if(this->client_ctx.size()>0){
+ nsock_pcap_read_packet(nsp, nsi, capture_handler, NSOCK_INFINITE, &arg);
+ nping_print(DBG_3, "Scheduled next capture event");
+ }
+
+ /* Get the actual captured packet */
+ nse_readpcap(nse, &link, &linklen, &packet, &packetlen, NULL, &pcaptime);
+ nping_print(DBG_3, "Captured %lu bytes", (unsigned long)packetlen);
+
+ /* Update Rx stats */
+ o.stats.addRecvPacket(packetlen);
+
+ /* Try to match received packet with a connected client. */
+ if( (clnt=this->nep_match_packet(packet, packetlen)) == CLIENT_NOT_FOUND ){
+ nping_print(DBG_3, "Couldn't match captured packet with a client");
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_4, "Captured packet belongs to client #%d", clnt);
+ }
+
+ /* Fetch client context */
+ if( (ctx=this->getClientContext(clnt)) == NULL ){
+ nping_print(DBG_2, "Error: no context found for client #%d", clnt);
+ return OP_FAILURE;
+ }
+
+ /* Lookup client's IOD */
+ if( (clnt_iod=ctx->getNsockIOD()) == NULL ){
+ nping_print(DBG_2, "Error: no IOD found for client #%d", clnt);
+ return OP_FAILURE;
+ }
+
+ if( ctx->ready() ){
+ this->generate_echo(&pkt_out, packet, packetlen, ctx);
+ nsock_write(nsp, clnt_iod, echo_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
+ o.stats.addEchoedPacket(packetlen);
+ }
+ return OP_SUCCESS;
+} /* End of nep_capture_handler() */
+
+
+int EchoServer::nep_echo_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_1, "Couldn't send NEP_ECHO. Terminating client session\n");
+ this->nep_session_ended_handler(nsp, nse, param);
+ }else{
+ nping_print(DBG_1, "SENT: NEP_ECHO");
+ }
+ return OP_SUCCESS;
+} /* End of nep_echo_handler() */
+
+
+int EchoServer::nep_hs_server_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ NEPContext *ctx=NULL;
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_1, "Couldn't send NEP_HANDSHAKE_SERVER. Terminating client session\n");
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+ /* Lookup client context and schedule a read operation to receive a
+ * NEP_HANDSHAKE_CLIENT message */
+ if( (ctx=this->getClientContext(nsi))!=NULL ){
+ ctx->setState(STATE_HS_SERVER_SENT);
+ nping_print(DBG_1, "SENT: NEP_HANDSHAKE_SERVER to %s", IPtoa(ctx->getAddress()));
+ nsock_readbytes(nsp, nsi, hs_client_handler, NSOCK_INFINITE, NULL, NEP_HANDSHAKE_CLIENT_LEN);
+ }
+ return OP_SUCCESS;
+} /* End of nep_hs_server_handler() */
+
+
+int EchoServer::nep_hs_client_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ NEPContext *ctx=NULL;
+ EchoHeader pkt_out;
+ u8 *inbuff=NULL;
+ int inlen=0;
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_1, "Failed to receive NEP_HANDSHAKE_CLIENT. Terminating client session");
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_1, "RCVD: NEP_HANDSHAKE_CLIENT");
+ }
+
+ /* Lookup client context */
+ if( (ctx=this->getClientContext(nsi))==NULL ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+
+ /* Ask nsock to provide received data */
+ if( (inbuff=(u8 *)nse_readbuf(nse, &inlen))==NULL ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+
+ /* Validate received NEP_HANDSHAKE_CLIENT */
+ if( this->parse_hs_client(inbuff, inlen, ctx)!=OP_SUCCESS ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+ ctx->setState(STATE_HS_FINAL_SENT);
+
+ /* Craft a NEP_HANDSHAKE_FINAL message and send it to the client */
+ if( this->generate_hs_final(&pkt_out, ctx)!=OP_SUCCESS ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+ nsock_write(nsp, nsi, hs_final_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
+ return OP_SUCCESS;
+} /* End of nep_hs_client_handler() */
+
+
+int EchoServer::nep_hs_final_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ nping_print(DBG_1, "SENT: NEP_HANDSHAKE_FINAL");
+ /* Receive NEP_PACKETSPEC */
+ nsock_readbytes(nsp, nsi, packetspec_handler, NSOCK_INFINITE, NULL, NEP_PACKETSPEC_LEN);
+ return OP_SUCCESS;
+} /* End of nep_hs_final_handler() */
+
+
+int EchoServer::nep_packetspec_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ EchoHeader pkt_in;
+ EchoHeader pkt_out;
+ NEPContext *ctx=NULL;
+ u8 *recvbuff=NULL;
+ int recvbytes=0;
+ enum nse_status status=nse_status(nse);
+ if (status!=NSE_STATUS_SUCCESS){
+ nping_print(DBG_1, "Failed to receive NEP_PACKET_SPEC message. Terminating client session\n");
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }else{
+ nping_print(DBG_1, "RCVD: NEP_PACKETSPEC");
+ }
+
+ /* Lookup client context */
+ if( (ctx=this->getClientContext(nsi))==NULL ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+
+ /* Ask nsock to provide received data */
+ if( (recvbuff=(u8 *)nse_readbuf(nse, &recvbytes))==NULL ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ return OP_FAILURE;
+ }
+
+ /* Validate received NEP_PACKET_SPEC message */
+ if( this->parse_packet_spec(recvbuff, recvbytes, ctx)!=OP_SUCCESS ){
+ this->nep_session_ended_handler(nsp, nse, param);
+ nping_print(VB_1, "[%lu] Couldn't establish NEP session with client #%d (%s:%d).", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
+ return OP_FAILURE;
+ }
+ ctx->setState(STATE_READY_SENT);
+ nping_print(VB_1, "[%lu] NEP handshake with client #%d (%s:%d) was performed successfully", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
+
+ /* Craft response and send it */
+ this->generate_ready(&pkt_out, ctx);
+ nsock_write(nsp, nsi, ready_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
+
+ /* From this point, the client is not supposed to send anything to the server
+ * through the side channel. However, we now schedule a read operation so
+ * we detect when the client disconnects (because Nsock will tell us). */
+ nsock_readbytes(nsp, nsi, session_ended_handler, NSOCK_INFINITE, NULL, 65535);
+
+ /* At this point, we consider the NEP session fully established and therefore
+ * we update the count of served clients */
+ o.stats.addEchoClientServed();
+
+ return OP_SUCCESS;
+} /* End of nep_packetspec_handler() */
+
+
+int EchoServer::nep_ready_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nping_print(DBG_1, "SENT: NEP_READY");
+ return OP_SUCCESS;
+} /* End of nep_ready_handler() */
+
+
+int EchoServer::nep_session_ended_handler(nsock_pool nsp, nsock_event nse, void *param){
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_iod nsi = nse_iod(nse);
+ clientid_t clnt;
+ NEPContext *ctx=NULL;
+
+ /* Lookup client context */
+ if( (ctx=this->getClientContext(nsi))!=NULL ){
+ nping_print(VB_0, "[%lu] Client #%d (%s:%d) disconnected", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
+ clnt=ctx->getIdentifier();
+ if(this->destroyClientContext(clnt)!=OP_SUCCESS)
+ nping_print(DBG_2, "Client #%d disconnected but no context found. This may be a bug.", clnt);
+ else
+ nping_print(DBG_2, "Deleted client #%d context.", clnt);
+ }
+ nsock_iod_delete(nsi, NSOCK_PENDING_SILENT);
+
+ /* Exit the server if --once has been set */
+ if(o.once()){
+ o.displayStatistics();
+ o.displayNpingDoneMsg();
+ o.cleanup();
+ exit(EXIT_SUCCESS);
+ }
+ return OP_SUCCESS;
+} /* End of nep_session_ended_handler() */
+
+
+
+/** Processes and validates a received NEP_HANDSHAKE_CLIENT message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoServer::parse_hs_client(u8 *pkt, size_t pktlen, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *next_iv=NULL;
+ EchoHeader h;
+ if(pkt==NULL || ctx==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen!=NEP_HANDSHAKE_CLIENT_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_HANDSHAKE_CLIENT){
+ nping_print(DBG_1, "Expected NEP_HANDSHAKE_CLIENT but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_HANDSHAKE_CLIENT timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+ /* Ensure message length is correct */
+ if( h.getTotalLength()!=(NEP_HANDSHAKE_CLIENT_LEN/4)){
+ nping_print(DBG_1, "Received NEP_HANDSHAKE_CLIENT specifies an incorrect length (%u)", h.getTotalLength()*4 );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the client echoed the nonce we sent in our NEP_HANDSHAKE_SERVER */
+ if( memcmp(h.getServerNonce(), ctx->getServerNonce(), NONCE_LEN)!=0 ){
+ nping_print(DBG_1, "Echoed nonce in NEP_HANDSHAKE_CLIENT message does not match client generate nonce");
+ return OP_FAILURE;
+ }
+ /* Store the received nonce */
+ ctx->setClientNonce(h.getClientNonce());
+
+ /* Store client's sequence number */
+ ctx->setLastClientSequence( h.getSequenceNumber() );
+
+ /* Generate all session keys */
+ ctx->generateCipherKeyC2S();
+ ctx->generateCipherKeyS2C();
+ ctx->generateMacKeyC2S();
+ ctx->generateMacKeyS2C();
+
+ nping_print(DBG_3,"Session Key MAC_C2S:"); print_hexdump(DBG_3,ctx->getMacKeyC2S(), MAC_KEY_LEN);
+ nping_print(DBG_3,"Session Key MAC_S2C:"); print_hexdump(DBG_3,ctx->getMacKeyS2C(), MAC_KEY_LEN);
+ nping_print(DBG_3,"Session Key CIPHER_C2S:"); print_hexdump(DBG_3,ctx->getCipherKeyC2S(), MAC_KEY_LEN);
+ nping_print(DBG_3,"Session Key CIPHER_S2C:"); print_hexdump(DBG_3,ctx->getCipherKeyS2C(), MAC_KEY_LEN);
+
+
+ /* Decrypt the encrypted part of the message before validating the MAC */
+ if((next_iv=h.decrypt(ctx->getCipherKeyC2S(), CIPHER_KEY_LEN, ctx->getClientNonce(), TYPE_NEP_HANDSHAKE_CLIENT))==NULL){
+ nping_print(DBG_1, "Failed to decrypt NEP_HANDSHAKE_CLIENT data." );
+ return OP_FAILURE;
+ }
+ ctx->setNextDecryptionIV(next_iv);
+
+ /* Check the authenticity of the received message */
+ if( h.verifyMessageAuthenticationCode( ctx->getMacKeyC2S(), MAC_KEY_LEN)!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_HANDSHAKE_CLIENT authentication failed" );
+ return OP_FAILURE;
+ }
+
+ return OP_SUCCESS;
+} /* End of parse_hs_client() */
+
+
+/** Processes and validates a received NEP_PACKET_SPEC message. On success
+ * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
+ * is not valid. */
+int EchoServer::parse_packet_spec(u8 *pkt, size_t pktlen, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ EchoHeader h;
+ int recvspecs=0;
+ bool id_received=false;
+ u8 field=0;
+ size_t len=0;
+ u8 *next_iv=NULL;
+ u8 specbuff[PACKETSPEC_FIELD_LEN];
+ if(pkt==NULL){
+ nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ if(pktlen!=NEP_PACKETSPEC_LEN){
+ nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
+ return OP_FAILURE;
+ }
+ h.storeRecvData(pkt, pktlen);
+
+ /* Decrypt message */
+ if((next_iv=h.decrypt(ctx->getCipherKeyC2S(), CIPHER_KEY_LEN, ctx->getNextDecryptionIV(), TYPE_NEP_PACKET_SPEC))==NULL){
+ nping_print(DBG_1, "Failed to decrypt NEP_PACKET_SPEC data." );
+ return OP_FAILURE;
+ }
+ ctx->setNextDecryptionIV(next_iv);
+
+ /* Validate version number */
+ if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
+ nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the expected message type was received */
+ if(h.getMessageType()!=TYPE_NEP_PACKET_SPEC){
+ nping_print(DBG_1, "Expected NEP_PACKET_SPEC but received %02X", h.getMessageType() );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received timestamp falls into the allowed time window */
+ //if( h.verifyTimestamp()!=OP_SUCCESS ){
+ // nping_print(DBG_1, "NEP_PACKET_SPEC timestamp is too old", h.getMessageType() );
+ // return OP_FAILURE;
+ //}
+
+ /* Ensure message length is correct */
+ if( h.getTotalLength()!=(NEP_PACKETSPEC_LEN/4)){
+ nping_print(DBG_1, "Received NEP_PACKET_SPEC specifies an incorrect length (%u)", h.getTotalLength()*4 );
+ return OP_FAILURE;
+ }
+
+ /* Ensure the received sequence number is the previous+1 */
+ if( h.getSequenceNumber()!=(ctx->getLastClientSequence()+1)){
+ nping_print(DBG_1, "Expected sequence number %d but received %d", ctx->getLastClientSequence()+1, h.getSequenceNumber() );
+ return OP_FAILURE;
+ }else{
+ /* Increment next expected sequence number*/
+ ctx->getNextClientSequence();
+ }
+
+ /* Check the authenticity of the received message */
+ if( h.verifyMessageAuthenticationCode( ctx->getMacKeyC2S(), MAC_KEY_LEN)!=OP_SUCCESS ){
+ nping_print(DBG_1, "NEP_PACKET_SPEC authentication failed" );
+ return OP_FAILURE;
+ }
+
+ /* Now that we have verified the authenticity of the message, let's process
+ * the field specifiers */
+ while(1){
+ if( h.getNextFieldSpec(&field, specbuff, &len)==OP_FAILURE ){
+ break;
+ }else{
+
+ /* Ensure the field spec is unique. Malicious users could try to supply
+ * the same spec more than once in order to get higher packet scores. */
+ if( ctx->isDuplicateFieldSpec(field) ){
+ nping_print(DBG_1, "Detected duplicate field specs in NEP_PACKET_SPEC message" );
+ return OP_FAILURE;
+ }else{
+ ctx->addClientFieldSpec(field, len, specbuff);
+ recvspecs++;
+ }
+ /* Set a flag to indicate that mandatory IPv4 ID or IPv6 Flow has been
+ * supplied by the client */
+ if(h.getIPVersion()==0x04 && field==PSPEC_IPv4_ID)
+ id_received=true;
+ else if(h.getIPVersion()==0x06 && field==PSPEC_IPv6_FLOW)
+ id_received=true;
+ nping_print(DBG_3|NO_NEWLINE,"RCVD FieldSpec: Type=%02X Len=%02x Data=0x", field, (u8)len);
+ for(unsigned int i=0; i<len; i++)
+ nping_print(DBG_3|NO_NEWLINE,"%02x", specbuff[i]);
+ nping_print(DBG_3, ";");
+ }
+ }
+ /* Check client provided mandatory IP ID (or Flow) spec and at least one other spec */
+ if(id_received && recvspecs>=4){
+ nping_print(VB_2, "[%lu] Good packet specification received from client #%d (Specs=%d,IP=%d,Proto=%d,Cnt=%d)",
+ (unsigned long)time(NULL), ctx->getIdentifier(), recvspecs, h.getIPVersion(), h.getProtocol(), h.getPacketCount()
+ );
+ return OP_SUCCESS;
+ }else{
+ return OP_FAILURE;
+ }
+} /* End of parse_packet_spec() */
+
+
+/** Generates a NEP_HANDSHAKE_SERVER message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error.
+ * @warning the caller must ensure that the supplied context object
+ * already contains an initial sequence number and a server nonce. */
+int EchoServer::generate_hs_server(EchoHeader *h, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ if(h==NULL || ctx==NULL)
+ return OP_FAILURE;
+
+ /* Craft NEP_HANDSHAKE_SERVER message */
+ h->setMessageType(TYPE_NEP_HANDSHAKE_SERVER);
+ h->setSequenceNumber( ctx->getLastServerSequence() );
+ h->setTimestamp();
+ h->setServerNonce( ctx->getServerNonce() );
+ h->setTotalLength();
+ h->setMessageAuthenticationCode( ctx->getMacKeyS2C(), MAC_KEY_LEN);
+ return OP_SUCCESS;
+} /* End of generate_hs_server() */
+
+
+/** Generates a NEP_HANDSHAKE_FINAL message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error. */
+int EchoServer::generate_hs_final(EchoHeader *h, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ struct sockaddr_storage ss;
+ u8 *next_iv=NULL;
+ if(h==NULL || ctx==NULL)
+ return OP_FAILURE;
+
+ /* Craft NEP_HANDSHAKE_CLIENT message */
+ h->setMessageType(TYPE_NEP_HANDSHAKE_FINAL);
+ h->setSequenceNumber(ctx->getNextServerSequence() );
+ h->setTimestamp();
+ h->setClientNonce( ctx->getClientNonce() );
+ ss=ctx->getAddress();
+ if(ss.ss_family==AF_INET6){
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ss;
+ h->setPartnerAddress(s6->sin6_addr);
+ }else{
+ struct sockaddr_in *s4=(struct sockaddr_in *)&ss;
+ h->setPartnerAddress(s4->sin_addr);
+ }
+ h->setTotalLength();
+ h->setMessageAuthenticationCode( ctx->getMacKeyS2C(), MAC_KEY_LEN);
+
+ /* Encrypt message */
+ if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getServerNonce()))==NULL )
+ return OP_FAILURE;
+ ctx->setNextEncryptionIV(next_iv);
+
+
+ return OP_SUCCESS;
+} /* End of generate_hs_final() */
+
+
+/** Generates a NEP_READY message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error. */
+int EchoServer::generate_ready(EchoHeader *h, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *next_iv=NULL;
+ if(h==NULL || ctx==NULL)
+ return OP_FAILURE;
+
+ /* Craft NEP_READY message */
+ h->setMessageType(TYPE_NEP_READY);
+ h->setSequenceNumber( ctx->getNextServerSequence() );
+ h->setTimestamp();
+ h->setTotalLength();
+ h->setMessageAuthenticationCode(ctx->getMacKeyS2C(), MAC_KEY_LEN);
+
+ /* Encrypt message */
+ if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getNextEncryptionIV()))==NULL )
+ return OP_FAILURE;
+ ctx->setNextEncryptionIV(next_iv);
+
+ return OP_SUCCESS;
+} /* End of generate_ready() */
+
+
+/** Generates a NEP_ECHO message. On success it returns OP_SUCCESS.
+ * OP_FAILURE is returned in case of error. */
+int EchoServer::generate_echo(EchoHeader *h, const u8 *pkt, size_t pktlen, NEPContext *ctx){
+ nping_print(DBG_4, "%s()", __func__);
+ u8 *next_iv=NULL;
+ if(h==NULL || ctx==NULL || pkt==NULL || pktlen==0)
+ return OP_FAILURE;
+
+ /* Craft NEP_ECHO message */
+ h->setMessageType(TYPE_NEP_ECHO);
+ h->setSequenceNumber( ctx->getNextServerSequence() );
+ h->setTimestamp();
+ h->setDLT(DLT_NODATALINKHEADERINCLUDED);
+
+ /* If allowed, echo the whole packet, including any application layer data */
+ if( o.echoPayload() ){
+ h->setEchoedPacket(pkt, pktlen);
+ /* Otherwise, find if the packet contains application layer data and erase it */
+ }else{
+ /* Determine where the application data starts */
+ int offset=PacketParser::payload_offset(pkt, pktlen, false);
+
+ /* If the packet does not have application data, don't touch it */
+ if(offset==0){
+ nping_print(DBG_3, "No payload found. Echoing the whole packet\n");
+ h->setEchoedPacket(pkt, pktlen);
+ /* If we found application data, zero it */
+ }else{
+ nping_print(DBG_3, "Erasing %d payload bytes\n", (int)pktlen-offset);
+ /* Allocate a new buffer, big enough to hold the packet */
+ u8 *new_pkt=(u8 *)safe_zalloc(pktlen);
+ /* Copy the initial header, and leave the rest as 0x00 bytes */
+ if(offset>0 && offset<(int)pktlen){
+ memcpy(new_pkt, pkt, offset);
+ /* If there was some error trying to find application data, include a
+ * default amount of data */
+ }else{
+ memcpy(new_pkt, pkt, MIN(pktlen, PAYLOAD_ECHO_BYTES_IN_DOUBT));
+ }
+ h->setEchoedPacket(new_pkt, pktlen);
+ free(new_pkt);
+ }
+ }
+
+ h->setTotalLength();
+ h->setMessageAuthenticationCode(ctx->getMacKeyS2C(), MAC_KEY_LEN);
+
+ if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getNextEncryptionIV()))==NULL )
+ return OP_FAILURE;
+ ctx->setNextEncryptionIV(next_iv);
+
+ return OP_SUCCESS;
+} /* End of generate_echo() */
+
+
+/** This is the server's main method. It sets up nsock and pcap, waits for
+ * client connections and handles all the events of the client sessions. */
+int EchoServer::start() {
+ nping_print(DBG_4, "%s()", __func__);
+ nsock_pool nsp; /**< Nsock pool */
+ enum nsock_loopstatus loopret; /**< Stores nsock_loop returned status */
+ nsock_iod client_nsi; /**< Stores connected client IOD */
+ nsock_iod pcap_nsi; /**< Stores Pcap IOD */
+ char pcapdev[128]; /**< Device name passed to pcap_open_live */
+ struct timeval now; /**< For timestamps */
+ struct sockaddr_storage ss; /**< New client socket address */
+ socklen_t sslen=sizeof(ss); /**< New client socket address len */
+ int listen_sd=-1; /**< Socket descriptor for listening */
+ int client_sd=-1; /**< Socket descriptor for new clients */
+ clientid_t *idpnt=NULL; /**< For new client assigned identifiers */
+ NEPContext ctx; /**< Context for the new client */
+ EchoHeader h;
+ int rc;
+
+ /* Create a new nsock pool */
+ if ((nsp = nsock_pool_new(NULL)) == NULL)
+ nping_fatal(QT_3, "Failed to create new pool. QUITTING.\n");
+
+ /* Set nsock trace level */
+ gettimeofday(&now, NULL);
+ if( o.getDebugging() == DBG_5 )
+ nsock_set_loglevel(NSOCK_LOG_INFO);
+ else if( o.getDebugging() > DBG_5 )
+ nsock_set_loglevel(NSOCK_LOG_DBG_ALL);
+
+ /* Create new IOD for pcap */
+ if ((pcap_nsi = nsock_iod_new(nsp, NULL)) == NULL)
+ nping_fatal(QT_3, "Failed to create new nsock_iod. QUITTING.\n");
+
+ /* Open pcap */
+ nping_print(DBG_2,"Opening pcap device %s", o.getDevice());
+ Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
+ rc = nsock_pcap_open(nsp, pcap_nsi, pcapdev, MAX_ECHOED_PACKET_LEN, 1,
+ ProbeMode::getBPFFilterString());
+ if (rc)
+ nping_fatal(QT_3, "Error opening capture device %s\n", o.getDevice());
+ else
+ nping_print(VB_0,"Packet capture will be performed using network interface %s.", o.getDevice());
+ nping_print(VB_0,"Waiting for connections...");
+
+ /* Get a socket suitable for an accept() call */
+ listen_sd=this->nep_listen_socket();
+
+ while(1){
+ /* If --once is enabled, just allow the first client */
+ if(o.once()==false || this->client_id_count==-1){
+ /* Check if we have received a connection*/
+ unblock_socket(listen_sd);
+ if ((client_sd=accept(listen_sd, (struct sockaddr *)&ss, &sslen)) >= 0){
+ nping_print(VB_0, "[%lu] Connection received from %s:%d", (unsigned long)time(NULL), IPtoa(&ss), sockaddr2port(&ss));
+ /* Assign a new client identifier. The ID is bound to the IOD */
+ if( (idpnt=(clientid_t *)calloc(1, sizeof(clientid_t)))==NULL ){
+ nping_warning(QT_2, "Not enough memory for new clients.");
+ return OP_FAILURE;
+ }
+ *idpnt=this->getNewClientID();
+ if( (client_nsi=nsock_iod_new2(nsp, client_sd, idpnt))==NULL ){
+ nping_warning(QT_2, "Not enough memory for new clients.");
+ return OP_FAILURE;
+ }else{
+ close(client_sd); /* nsock_iod_new2() dups the socket */
+ }
+
+ /* Stop listening if --once is enabled */
+ if(o.once()==true)
+ close(listen_sd);
+
+ /* Create a new client context object */
+ ctx.setIdentifier(*idpnt);
+ ctx.setAddress(ss);
+ ctx.setNsockIOD(client_nsi);
+ ctx.generateServerNonce();
+ ctx.generateInitialServerSequence();
+ ctx.generateMacKeyS2CInitial();
+ nping_print(DBG_3,"Session Key MAC_S2C_INITIAL:"); print_hexdump(DBG_3,ctx.getMacKeyS2C(), MAC_KEY_LEN);
+
+ /* Craft NEP_HANDSHAKE_SERVER message */
+ if( this->generate_hs_server(&h, &ctx)!=OP_SUCCESS)
+ return OP_FAILURE;
+ else
+ this->addClientContext(ctx);
+
+ /* Schedule send operation */
+ nsock_write(nsp, client_nsi, hs_server_handler, NSOCK_INFINITE, NULL, (const char *)h.getBufferPointer(), h.getLen() );
+
+ /* For every client we schedule a packet capture event. */
+ nsock_pcap_read_packet(nsp, pcap_nsi, capture_handler, NSOCK_INFINITE, NULL);
+
+ }
+ block_socket(listen_sd);
+ }
+ /* Sleep for a second until we check again for incoming connection requests */
+ nsock_timer_create(nsp, empty_handler, 1000, NULL);
+ loopret=nsock_loop(nsp, 1000);
+ //If something went wrong in nsock_loop, let's just bail out.
+ if (loopret == NSOCK_LOOP_ERROR) {
+ nping_warning(QT_3, "Unexpected nsock_loop error.\n");
+ return OP_FAILURE;
+ }
+ }
+ return OP_SUCCESS;
+} /* End of start() */
+
+
+/** Performs cleanup functions */
+int EchoServer::cleanup(){
+ // For the moment there is nothing to cleanup
+ return OP_SUCCESS;
+} /* End of cleanup() */
+
+/******************************************************************************/
+/**** HANDLER WRAPPERS ********************************************************/
+/******************************************************************************/
+
+/* This handler is a wrapper for the EchoServer::nep_read_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void capture_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_capture_handler(nsp, nse, arg);
+ return;
+} /* End of capture_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_echo_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void echo_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_echo_handler(nsp, nse, arg);
+ return;
+} /* End of echo_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_hs_server_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_hs_server_handler(nsp, nse, arg);
+ return;
+} /* End of hs_server_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_hs_client_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void hs_client_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_hs_client_handler(nsp, nse, arg);
+ return;
+} /* End of hs_client_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_hs_final_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_hs_final_handler(nsp, nse, arg);
+ return;
+} /* End of hs_final_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_packetspec_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void packetspec_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_packetspec_handler(nsp, nse, arg);
+ return;
+} /* End of packetspec_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_ready_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void ready_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_ready_handler(nsp, nse, arg);
+ return;
+} /* End of ready_handler() */
+
+
+/* This handler is a wrapper for the EchoServer::nep_ready_handler() method. We
+ * need this because C++ does not allow to use class methods as callback
+ * functions for things like signal() or the Nsock lib. */
+void session_ended_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ es.nep_session_ended_handler(nsp, nse, arg);
+ return;
+} /* End of ready_handler() */
+
+
+/* Void handler that does nothing */
+void empty_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ return;
+} /* End of capture_handler() */
diff --git a/nping/EchoServer.h b/nping/EchoServer.h
new file mode 100644
index 0000000..c31771e
--- /dev/null
+++ b/nping/EchoServer.h
@@ -0,0 +1,131 @@
+
+/***************************************************************************
+ * EchoServer.h -- *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+#ifndef __ECHOSERVER_H__
+#define __ECHOSERVER_H__ 1
+
+
+
+#include "nping.h"
+#include "nsock.h"
+#include <vector>
+#include "NEPContext.h"
+
+#define LISTEN_QUEUE_SIZE 10
+
+class EchoServer {
+
+ private:
+ /* Attributes */
+ std::vector<NEPContext> client_ctx;
+ clientid_t client_id_count;
+
+ /* Methods */
+ int nep_listen_socket();
+ int addClientContext(NEPContext ctx);
+ NEPContext *getClientContext(clientid_t clnt);
+ NEPContext *getClientContext(nsock_iod iod);
+ int destroyClientContext(clientid_t clnt);
+ nsock_iod getClientNsockIOD(clientid_t clnt);
+ clientid_t getNewClientID();
+ clientid_t nep_match_packet(const u8 *pkt, size_t pktlen);
+ clientid_t nep_match_headers(IPv4Header *ip4, IPv6Header *ip6, TCPHeader *tcp, UDPHeader *udp, ICMPv4Header *icmp4, RawData *payload);
+ int parse_hs_client(u8 *pkt, size_t pktlen, NEPContext *ctx);
+ int parse_packet_spec(u8 *pkt, size_t pktlen, NEPContext *ctx);
+
+ int generate_hs_server(EchoHeader *h, NEPContext *ctx);
+ int generate_hs_final(EchoHeader *h, NEPContext *ctx);
+ int generate_ready(EchoHeader *h, NEPContext *ctx);
+ int generate_echo(EchoHeader *h, const u8 *pkt, size_t pktlen, NEPContext *ctx);
+
+ public:
+
+ EchoServer();
+ ~EchoServer();
+ void reset();
+ int start();
+ int cleanup();
+
+ int nep_capture_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_echo_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_hs_server_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_hs_client_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_hs_final_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_packetspec_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_ready_handler(nsock_pool nsp, nsock_event nse, void *param);
+ int nep_session_ended_handler(nsock_pool nsp, nsock_event nse, void *param);
+
+}; /* End of class EchoServer */
+
+typedef struct handler_arg{
+ EchoServer *me;
+ void *param;
+} handler_arg_t;
+
+/* Handler wrappers */
+void capture_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void echo_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void hs_client_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void packetspec_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void ready_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void empty_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void session_ended_handler(nsock_pool nsp, nsock_event nse, void *arg);
+
+#endif /* __ECHOSERVER_H__ */
diff --git a/nping/LICENSE b/nping/LICENSE
new file mode 100644
index 0000000..0cf2649
--- /dev/null
+++ b/nping/LICENSE
@@ -0,0 +1,3 @@
+Nping is distributed under the same license terms as Nmap. See the
+LICENSE file in the Nmap tarball, the man page legal section, or
+https://nmap.org/man/man-legal.html .
diff --git a/nping/Makefile.in b/nping/Makefile.in
new file mode 100644
index 0000000..3cf9c55
--- /dev/null
+++ b/nping/Makefile.in
@@ -0,0 +1,167 @@
+# Extract the version string from nping.h.
+export NPING_VERSION := $(shell grep '^\#[ \t]*define[ \t]\+NPING_VERSION' nping.h | sed -e 's/.*"\(.*\)".*/\1/' -e 'q')
+NPING_NAME= Nping
+NPING_URL= https://nmap.org/nping
+NPING_PLATFORM=@host@
+prefix = @prefix@
+datarootdir = @datarootdir@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+mandir = @mandir@
+srcdir = @srcdir@
+npingdatadir = @datadir@/nping
+NPINGDEVDIR=~/nping-private-dev
+WIN32STUFFDIR=mswin32
+NPINGWEBDIR=../../../web/nmap/nping
+NPINGWININSTDIR=mswin32/nsis
+export RELEASE_DATE := $(shell date +"%b %d, %Y")
+
+
+export NBASEDIR=../nbase
+export NSOCKDIR=../nsock
+
+export NDIR=$(shell pwd)
+
+
+CC = @CC@
+CXX = @CXX@
+CCOPT =
+DBGFLAGS =
+STRIP = @STRIP@
+LIBPCAPDIR = @libpcapdir@
+export LIBDNETDIR = @LIBDNETDIR@
+
+
+DEFS = @DEFS@ -DNPING_NAME=\"$(NPING_NAME)\" -DNPING_URL=\"$(NPING_URL)\" -DNPING_PLATFORM=\"$(NPING_PLATFORM)\"
+# With GCC, add extra security checks to source code.
+# http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html
+# Level 1 only makes changes that don't affect "conforming" programs,
+# while level 2 enforces additional restrictions.
+DEFS += -D_FORTIFY_SOURCE=2
+# For mtrace debugging -- see MTRACE define in main.cc for instructions
+# Should only be enabled during debugging and not in any real release.
+# DEFS += -DMTRACE=1
+CXXFLAGS = @CXXFLAGS@ $(DBGFLAGS) $(CCOPT) $(DEFS)
+CPPFLAGS = @CPPFLAGS@ -I$(NBASEDIR) -I$(NSOCKDIR)/include
+export CFLAGS = $(CXXFLAGS)
+# CFLAGS = $(DEFS) $(INCLS)
+STATIC =
+LDFLAGS = @LDFLAGS@ $(DBGFLAGS) $(STATIC)
+OPENSSL_LIBS = @OPENSSL_LIBS@
+LIBS = $(NSOCKDIR)/src/libnsock.a $(NBASEDIR)/libnbase.a ../libnetutil/libnetutil.a $(OPENSSL_LIBS) @LIBPCAP_LIBS@ @LIBDNET_LIBS@ @LIBS@
+# LIBS = -lefence @LIBS@
+# LIBS = -lrmalloc @LIBS@
+INSTALL = @INSTALL@
+# MAKEDEPEND = @MAKEDEPEND@
+export RPMTDIR=$(HOME)/rpm
+
+
+# DESTDIR is used by some package maintainers to install Nping under
+# its usual directory structure into a different tree. See the
+# CHANGELOG for more info.
+DESTDIR =
+
+TARGET = nping
+
+
+export SRCS = ArgParser.cc common.cc common_modified.cc nping.cc NpingOps.cc utils.cc utils_net.cc output.cc stats.cc NpingTargets.cc NpingTarget.cc EchoHeader.cc EchoServer.cc EchoClient.cc ProbeMode.cc NEPContext.cc Crypto.cc
+
+export HDRS = ArgParser.h nping_config.h common.h common_modified.h nping.h NpingOps.h global_structures.h output.h utils.h utils_net.h stats.h NpingTargets.h NpingTarget.h EchoHeader.h EchoServer.h EchoClient.h ProbeMode.h NEPContext.h Crypto.h
+
+OBJS = ArgParser.o common.o common_modified.o nping.o NpingOps.o utils.o utils_net.o output.o stats.o NpingTargets.o NpingTarget.o EchoHeader.o EchoServer.o EchoClient.o ProbeMode.o NEPContext.o Crypto.o
+
+export DOCS2DIST = leet-nping-ascii-art.txt nping.1 nping-man.html
+
+export MISC2DIST = config.guess config.sub configure configure.ac Makefile.in TODO nping_config.h.in CHANGELOG LICENSE
+
+
+# %.o : %.cc -- nope this is a GNU extension
+.cc.o:
+ $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+all:
+ $(MAKE) $(TARGET)
+
+$(TARGET): $(NBASEDIR)/libnbase.a $(NSOCKDIR)/src/libnsock.a ../libnetutil/libnetutil.a $(OBJS)
+ @echo Compiling nping
+ rm -f $@
+ $(CXX) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+ @echo Nping compiled successfully!
+
+
+# Make a statically compiled binary for portability between distributions
+static:
+ $(MAKE) STATIC=-static
+
+debug:
+ $(MAKE) DBGFLAGS="-O0 -g -pg -ftest-coverage -fprofile-arcs"
+
+# CALL THIS FROM ONE COMPUTER AND CHECK IN RESULTS BEFORE DOING ANYONE
+# DOES A MAKE RELEASE
+prerelease:
+ cd $(NPINGDEVDIR) && $(MAKE) prerelease
+
+# Generate the Nping distribution tarball
+generate-tarball:
+ cd nping-priv && ./create_tarballs.sh
+
+# Update the web site. WARNING: "make generate-tarball" must have been called first.
+web:
+ cd nping-priv && ./update_web.sh
+
+clean:
+ rm -f $(OBJS) $(TARGET)
+# Who generates dependencies.mk? If it is generated by ./configure and
+# not by make it should be moved to distclean
+ rm -f dependencies.mk
+
+debugclean:
+ rm -f *.gcov *.gcda *.gcno gmon.out
+
+distclean: clean
+ rm -f Makefile Makefile.bak makefile.dep nping_config.h stamp-h \
+ stamp-h.in config.cache config.log config.status
+
+install-nping: $(TARGET)
+ $(INSTALL) -d $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+ $(INSTALL) -c -m 755 nping $(DESTDIR)$(bindir)/nping
+# Use strip -x to avoid stripping dynamically loaded NSE functions. See
+# http://seclists.org/nmap-dev/2007/q4/0272.html.
+ $(STRIP) -x $(DESTDIR)$(bindir)/nping
+ $(INSTALL) -c -m 644 docs/$(TARGET).1 $(DESTDIR)$(mandir)/man1/
+
+
+
+install: install-nping
+ @echo "NPING SUCCESSFULLY INSTALLED"
+
+uninstall: uninstall-nping
+
+uninstall-nping:
+ rm -f $(DESTDIR)$(bindir)/$(TARGET)
+ rm -f $(DESTDIR)$(mandir)/man1/$(TARGET).1
+
+${srcdir}/configure: configure.ac
+ cd ${srcdir} && autoconf
+
+## autoheader might not change config.h.in, so touch a stamp file.
+#${srcdir}/config.h.in: stamp-h.in
+#${srcdir}/stamp-h.in: configure.ac acconfig.h \
+# config.h.top config.h.bot
+# cd ${srcdir} && autoheader
+# echo timestamp > ${srcdir}/stamp-h.in
+#
+#config.h: stamp-h
+#stamp-h: config.h.in config.status
+# ./config.status
+
+Makefile: Makefile.in config.status
+ ./config.status
+
+config.status: configure
+ ./config.status --recheck
+
+makefile.dep:
+ $(CXX) -MM $(CPPFLAGS) $(SRCS) > $@
+-include makefile.dep
diff --git a/nping/NEPContext.cc b/nping/NEPContext.cc
new file mode 100644
index 0000000..2368234
--- /dev/null
+++ b/nping/NEPContext.cc
@@ -0,0 +1,552 @@
+
+/***************************************************************************
+ * NEPContext.cc -- *
+ * *
+ ***********************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 "NEPContext.h"
+#include "Crypto.h"
+#include "EchoHeader.h"
+#include "nbase.h"
+#include "NpingOps.h"
+
+extern NpingOps o;
+
+NEPContext::NEPContext() {
+ this->reset();
+} /* End of NEPContext constructor */
+
+
+NEPContext::~NEPContext() {
+} /* End of NEPContext destructor */
+
+
+/** Sets every attribute to its default value- */
+void NEPContext::reset() {
+ this->id=CLIENT_NOT_FOUND;
+ this->nsi=NULL;
+ this->state=STATE_LISTEN;
+ this->last_seq_client=0;
+ this->last_seq_server=0;
+ memset(this->next_iv_enc, 0, CIPHER_BLOCK_SIZE);
+ memset(this->next_iv_dec, 0, CIPHER_BLOCK_SIZE);
+ memset(this->nep_key_mac_c2s, 0, MAC_KEY_LEN);
+ memset(this->nep_key_mac_s2c, 0, MAC_KEY_LEN);
+ memset(this->nep_key_ciphertext_c2s, 0, CIPHER_KEY_LEN);
+ memset(this->nep_key_ciphertext_s2c, 0, CIPHER_KEY_LEN);
+ memset(this->server_nonce, 0, NONCE_LEN);
+ memset(this->client_nonce, 0, NONCE_LEN);
+ memset(&this->clnt_addr, 0, sizeof(struct sockaddr_storage ));
+ server_nonce_set=false;
+ client_nonce_set=false;
+} /* End of reset() */
+
+
+clientid_t NEPContext::getIdentifier(){
+ return this->id;
+} /* End of getIdentifier() */
+
+
+int NEPContext::setIdentifier(clientid_t clnt){
+ this->id=clnt;
+ return OP_SUCCESS;
+} /* End of setIdentifier() */
+
+
+struct sockaddr_storage NEPContext::getAddress(){
+ return this->clnt_addr;
+} /* End of getAddress() */
+
+
+int NEPContext::setAddress(const struct sockaddr_storage &a){
+ this->clnt_addr=a;
+ return OP_SUCCESS;
+} /* End of setAddress() */
+
+nsock_iod NEPContext::getNsockIOD(){
+ return this->nsi;
+} /* End of getNsockIOD() */
+
+
+int NEPContext::setNsockIOD(nsock_iod iod){
+ this->nsi=iod;
+ return OP_SUCCESS;
+} /* End of setNsockIOD() */
+
+
+bool NEPContext::ready(){
+ return (this->state==STATE_READY_SENT);
+}
+
+int NEPContext::setState(int st){
+ this->state=st;
+ return OP_SUCCESS;
+} /* End of setState() */
+
+
+int NEPContext::getState(){
+ return this->state;
+} /* End of getState() */
+
+
+int NEPContext::setNextEncryptionIV(u8 *block){
+ if(block==NULL)
+ return OP_FAILURE;
+ else{
+ memcpy(this->next_iv_enc, block, CIPHER_BLOCK_SIZE);
+ return OP_SUCCESS;
+ }
+} /* End of setLastBlock4Encryption() */
+
+
+u8 *NEPContext::getNextEncryptionIV(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=CIPHER_BLOCK_SIZE;
+ return this->next_iv_enc;
+} /* End of getLastBlock4Encryption() */
+
+
+u8 *NEPContext::getNextEncryptionIV(){
+ return this->getNextEncryptionIV(NULL);
+} /* End of getLastBlock4Encryption() */
+
+
+int NEPContext::setNextDecryptionIV(u8 *block){
+ if(block==NULL)
+ return OP_FAILURE;
+ else{
+ memcpy(this->next_iv_dec, block, CIPHER_BLOCK_SIZE);
+ return OP_SUCCESS;
+ }
+} /* End of setLastBlock4Decryption() */
+
+
+u8 *NEPContext::getNextDecryptionIV(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=CIPHER_BLOCK_SIZE;
+ return this->next_iv_dec;
+} /* End of getLastBlock4Decryption() */
+
+
+u8 *NEPContext::getNextDecryptionIV(){
+ return this->getNextDecryptionIV(NULL);
+} /* End of getLastBlock4Decryption() */
+
+
+int NEPContext::setLastServerSequence(u32 seq){
+ this->last_seq_server=seq;
+ return OP_SUCCESS;
+} /* End of setLastServerSequence() */
+
+
+u32 NEPContext::getLastServerSequence(){
+ return this->last_seq_server;
+} /* End of getLastServerSequence() */
+
+
+/** Increments current server sequence number by one and returns it.
+ * @warning this function changes object's internal state. It should be
+ * called only when the caller wants to increment the internal last_seq_client
+ * attribute. */
+u32 NEPContext::getNextServerSequence(){
+ if( this->last_seq_server==0xFFFFFFFF)
+ this->last_seq_server=0; /* Wrap back to zero */
+ else
+ this->last_seq_server++;
+ return this->last_seq_server;
+} /* End of getNextServerSequence() */
+
+
+int NEPContext::setLastClientSequence(u32 seq){
+ this->last_seq_client=seq;
+ return OP_SUCCESS;
+} /* End of setLastClientSequence() */
+
+
+u32 NEPContext::getLastClientSequence(){
+ return this->last_seq_client;
+} /* End of getLastClientSequence() */
+
+
+/** Increments current client sequence number by one and returns it.
+ * @warning this function changes object's internal state. It should be
+ * called only when the caller wants to increment the internal last_seq_client
+ * attribute. */
+u32 NEPContext::getNextClientSequence(){
+ if( this->last_seq_client==0xFFFFFFFF)
+ this->last_seq_client=0; /* Wrap back to zero */
+ else
+ this->last_seq_client++;
+ return this->last_seq_client;
+} /* End of getNextClientSequence() */
+
+
+int NEPContext::generateInitialServerSequence(){
+ return Crypto::generateNonce((u8 *)&(this->last_seq_server), sizeof(u32));
+} /* End of generateInitialServerSequence() */
+
+
+int NEPContext::generateInitialClientSequence(){
+ return Crypto::generateNonce((u8 *)&(this->last_seq_client), sizeof(u32));
+} /* End of generateInitialClientSequence() */
+
+
+u8 *NEPContext::generateKey(int key_type, size_t *final_len){
+ u8 data[1024];
+ char key_type_id[128+1];
+ size_t len=0;
+
+ /* Copy the passphrase */
+ char *passphrase=o.getEchoPassphrase();
+ size_t plen=strlen(passphrase);
+ memcpy(data, passphrase, plen);
+ len+=plen;
+
+ /* Copy the nonces */
+ memcpy(data+len, this->getServerNonce(), NONCE_LEN );
+ len+=NONCE_LEN;
+ if(key_type==MAC_KEY_S2C_INITIAL){
+ memset(data+len, 0, NONCE_LEN); /* Empty nonce in this case */
+ len+=NONCE_LEN;
+ }else{
+ memcpy(data+len, this->getClientNonce(), NONCE_LEN);
+ len+=NONCE_LEN;
+ }
+
+ switch(key_type){
+
+ case MAC_KEY_S2C_INITIAL:
+ strncpy(key_type_id, "NEPkeyforMACServer2ClientInitial", 128);
+ break;
+ case MAC_KEY_S2C:
+ strncpy(key_type_id, "NEPkeyforMACServer2Client", 128);
+ break;
+ case MAC_KEY_C2S:
+ strncpy(key_type_id, "NEPkeyforMACClient2Server", 128);
+ break;
+ case CIPHER_KEY_C2S:
+ strncpy(key_type_id, "NEPkeyforCiphertextClient2Server", 128);
+ break;
+ case CIPHER_KEY_S2C:
+ strncpy(key_type_id, "NEPkeyforCiphertextServer2Client", 128);
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ /* Copy the id */
+ memcpy(data+len, key_type_id, strlen(key_type_id));
+ len+=strlen(key_type_id);
+
+ return Crypto::deriveKey(data, len, final_len);
+} /* End of generateKey() */
+
+
+/** Set key for C->S MAC computation (NEP_KEY_MAC_C2S)*/
+int NEPContext::setMacKeyC2S(u8 *key){
+ if(key==NULL)
+ return OP_FAILURE;
+ else
+ memcpy(this->nep_key_mac_c2s, key, MAC_KEY_LEN);
+ return OP_SUCCESS;
+} /* End of setMacKeyC2S() */
+
+
+/** Returns NEP_KEY_MAC_C2S key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getMacKeyC2S(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=MAC_KEY_LEN;
+ return this->nep_key_mac_c2s;
+} /* End of getMacKeyC2S() */
+
+
+/** Returns NEP_KEY_MAC_C2S key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getMacKeyC2S(){
+ return this->getMacKeyC2S(NULL);
+} /* End of getMacKeyC2S() */
+
+
+int NEPContext::generateMacKeyC2S(){
+ u8 *key=NULL;
+ size_t len=0;
+ if( (key=this->generateKey(MAC_KEY_C2S, &len))==NULL )
+ return OP_FAILURE;
+ return this->setMacKeyC2S(key);
+} /* End of generateMacKeyC2S() */
+
+
+/** Set key for S->C MAC computation (NEP_KEY_MAC_S2C) */
+int NEPContext::setMacKeyS2C(u8 *key){
+ if(key==NULL)
+ return OP_FAILURE;
+ else
+ memcpy(this->nep_key_mac_s2c, key, MAC_KEY_LEN);
+ return OP_SUCCESS;
+} /* End of setMacKeyS2C() */
+
+
+/** Returns NEP_KEY_MAC_S2C key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getMacKeyS2C(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=MAC_KEY_LEN;
+ return this->nep_key_mac_s2c;
+} /* End of getMacKeyS2C() */
+
+
+
+/** Returns NEP_KEY_MAC_S2C key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getMacKeyS2C(){
+ return this->getMacKeyS2C(NULL);
+} /* End of getMacKeyS2C() */
+
+
+int NEPContext::generateMacKeyS2C(){
+ u8 *key=NULL;
+ size_t len=0;
+ if( (key=this->generateKey(MAC_KEY_S2C, &len))==NULL )
+ return OP_FAILURE;
+ return this->setMacKeyS2C(key);
+} /* End of generateMacKeyS2C() */
+
+
+int NEPContext::generateMacKeyS2CInitial(){
+ u8 *key=NULL;
+ size_t len=0;
+ if( (key=this->generateKey(MAC_KEY_S2C_INITIAL, &len))==NULL )
+ return OP_FAILURE;
+ return this->setMacKeyS2C(key);
+} /* End of generateMacKeyS2CInitial() */
+
+
+/** Set cipher key for C->S ciphertext (NEP_KEY_CIPHERTEXT_C2S) */
+int NEPContext::setCipherKeyC2S(u8 *key){
+ if(key==NULL)
+ return OP_FAILURE;
+ else
+ memcpy(this->nep_key_ciphertext_c2s, key, CIPHER_KEY_LEN);
+ return OP_SUCCESS;
+} /* End of setCipherKeyC2S() */
+
+
+/** Returns NEP_KEY_CIPHERTEXT_C2S key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getCipherKeyC2S(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=MAC_KEY_LEN;
+ return this->nep_key_ciphertext_c2s;
+} /* End of getCipherKeyC2S() */
+
+
+/** Returns NEP_KEY_CIPHERTEXT_C2S key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getCipherKeyC2S(){
+ return this->getCipherKeyC2S(NULL);
+} /* End of getCipherKeyC2S() */
+
+
+int NEPContext::generateCipherKeyC2S(){
+ u8 *key=NULL;
+ size_t len=0;
+ if( (key=this->generateKey(CIPHER_KEY_C2S, &len))==NULL )
+ return OP_FAILURE;
+ return this->setCipherKeyC2S(key);
+} /* End of generateCipherKeyC2S() */
+
+
+/** Set cipher key for S->C ciphertext (NEP_KEY_CIPHERTEXT_S2C) */
+int NEPContext::setCipherKeyS2C(u8 *key){
+ if(key==NULL)
+ return OP_FAILURE;
+ else
+ memcpy(this->nep_key_ciphertext_s2c, key, CIPHER_KEY_LEN);
+ return OP_SUCCESS;
+} /* End of setCipherKeyS2C() */
+
+
+/** Returns NEP_KEY_CIPHERTEXT_S2C key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getCipherKeyS2C(size_t *final_len){
+ if(final_len!=NULL)
+ *final_len=CIPHER_KEY_LEN;
+ return this->nep_key_ciphertext_s2c;
+} /* End of getCipherKeyS2C() */
+
+
+/** Returns NEP_KEY_CIPHERTEXT_S2C key. If final_len is not NULL, key length
+ * is stored in it. */
+u8 *NEPContext::getCipherKeyS2C(){
+ return this->getCipherKeyS2C(NULL);
+} /* End of getCipherKeyS2C() */
+
+
+int NEPContext::generateCipherKeyS2C(){
+ u8 *key=NULL;
+ size_t len=0;
+ if( (key=this->generateKey(CIPHER_KEY_S2C, &len))==NULL )
+ return OP_FAILURE;
+ return this->setCipherKeyS2C(key);
+} /* End of generateCipherKeyS2C() */
+
+
+/** Generates a random nonce which is, if possible, cryptographically secure.
+ * This method is used by the Echo client to generate its own nonce for the
+ * initial NEP_HANDSHAKE_CLIENT message */
+int NEPContext::generateClientNonce(){
+ return Crypto::generateNonce(this->client_nonce, NONCE_LEN);
+} /* End of generateClientNonce() */
+
+
+/** Generates a random nonce which is, if possible, cryptographically secure.
+ * This method is used by the Echo server to generate its own nonce for the
+ * initial NEP_HANDSHAKE_SERVER message */
+int NEPContext::generateServerNonce(){
+ return Crypto::generateNonce(this->server_nonce, NONCE_LEN);
+} /* End of generateServerNonce() */
+
+
+/** This method is used by the Echo server to store the initial nonce received
+ * from the client. */
+int NEPContext::setClientNonce(u8 *buff){
+ if(buff==NULL)
+ return OP_FAILURE;
+ else{
+ memcpy(this->client_nonce, buff, NONCE_LEN);
+ this->client_nonce_set=true;
+ }
+ return OP_SUCCESS;
+} /* End of setClientNonce() */
+
+
+/** This method is used by the Echo client to store the initial nonce received
+ * from the server. */
+int NEPContext::setServerNonce(u8 *buff){
+ if(buff==NULL)
+ return OP_FAILURE;
+ else{
+ memcpy(this->server_nonce, buff, NONCE_LEN);
+ this->server_nonce_set=true;
+ }
+ return OP_SUCCESS;
+} /* End of setServerNonce() */
+
+
+u8 *NEPContext::getClientNonce(){
+ return this->client_nonce;
+} /* End of getClientNonce() */
+
+
+u8 *NEPContext::getServerNonce(){
+ return this->server_nonce;
+} /* End of getServerNonce() */
+
+
+/** Adds a field specifier, received from the client in a NEP_PACKET_SPEC
+ * message. */
+int NEPContext::addClientFieldSpec(u8 field, u8 len, u8 *value){
+ fspec_t t;
+ if(value==NULL){
+ return OP_FAILURE;
+ }else{
+ t.field=field;
+ t.len=MIN(len, PACKETSPEC_FIELD_LEN);
+ memcpy(t.value, value, t.len);
+ this->fspecs.push_back(t);
+ }
+ return OP_SUCCESS;
+} /* End of addClientFieldSpec() */
+
+
+/** Returns a pointer to the N-th client's field specifier. Callers should start
+ * passing 0 and then incrementing the index by one until it returns NULL */
+fspec_t *NEPContext::getClientFieldSpec(int index){
+ if(index<0 || index>=(int)this->fspecs.size() )
+ return NULL;
+ else
+ return &(this->fspecs[index]);
+} /* End of getClientFieldSpec() */
+
+
+/** Returns true if we already have a packet spec of the same type. This
+ * method should be called for EVERY spec in a NEP_PACKET_SPEC message, to
+ * ensure that malicious clients are not supplying the same spec repeatedly
+ * to increase their packet score. */
+bool NEPContext::isDuplicateFieldSpec(u8 test_field){
+ int i=0;
+ fspec_t *spec=NULL;
+
+ /* Iterate through the list of stored specs and determine if we already
+ have a spec of the same type. */
+ while( (spec=this->getClientFieldSpec(i++))!=NULL ){
+ if(spec->field==test_field)
+ return true;
+ }
+ return false;
+} /* End of isDuplicateFieldSpect() */
+
+
+/** Deletes all previous field specifiers. This should be used when dealing
+ * with clients that send multiple NEP_PACKET_SPEC messages, so only the last
+ * PacketSpec is taken into account. */
+int NEPContext::resetClientFieldSpecs(){
+ this->fspecs.clear();
+ return OP_SUCCESS;
+} /* End of resetClientFieldSpecs() */
diff --git a/nping/NEPContext.h b/nping/NEPContext.h
new file mode 100644
index 0000000..4067eae
--- /dev/null
+++ b/nping/NEPContext.h
@@ -0,0 +1,213 @@
+
+/***************************************************************************
+ * NEPContext.cc -- *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef __NEPCONTEXT_H__
+#define __NEPCONTEXT_H__ 1
+
+
+
+#include "nsock.h"
+#include "EchoHeader.h"
+#include <vector>
+
+/* SERVER STATE MACHINE */
+/* _ */
+/* (O) */
+/* | */
+/* Capture Raw / | Rcvd TCP Connection / */
+/* Send NEP_ECHO | +--------+ Send NEP_HANDSHAKE_SERVER */
+/* +----------+ +---->| LISTEN |-----------------+ */
+/* | | +--------+ | */
+/* | \|/ \|/ */
+/* | +----+------+ +----------+-----------+ */
+/* +-----| NEP_READY | | NEP_HANDSHAKE_SERVER | */
+/* | SENT | | SENT | */
+/* +----+------+ +----------+-----------+ */
+/* /|\ | */
+/* | | */
+/* | +---------------------+ | */
+/* | | NEP_HANDSHAKE_FINAL | | */
+/* +-------| SENT |<---------+ */
+/* +---------------------+ Rcvd NEP_HANDSHAKE_CLIENT/ */
+/* Rcvd NEP_PACKETSPEC / Send NEP_HANDSHAKE_FINAL */
+/* Send NEP_READY */
+/* */
+/* */
+
+
+
+#define STATE_LISTEN 0x00
+#define STATE_HS_SERVER_SENT 0x01
+#define STATE_HS_FINAL_SENT 0x02
+#define STATE_READY_SENT 0x03
+
+#define CLIENT_NOT_FOUND -1
+typedef int clientid_t; /**< Type for client identifiers */
+
+#define MAC_KEY_S2C_INITIAL 0x01
+#define MAC_KEY_S2C 0x02
+#define MAC_KEY_C2S 0x03
+#define CIPHER_KEY_C2S 0x04
+#define CIPHER_KEY_S2C 0x05
+
+
+/* Client field specifier */
+typedef struct field_spec{
+ u8 field; /* Field identifier (See NEP RFC) */
+ u8 len; /* Field length */
+ u8 value[PACKETSPEC_FIELD_LEN]; /* Field data */
+}fspec_t;
+
+class NEPContext {
+
+ private:
+
+ clientid_t id; /**< Client identifier */
+ nsock_iod nsi; /**< Client nsock IOD */
+ int state;
+ u32 last_seq_client;
+ u32 last_seq_server;
+ u8 next_iv_enc[CIPHER_BLOCK_SIZE];
+ u8 next_iv_dec[CIPHER_BLOCK_SIZE];
+ u8 nep_key_mac_c2s[MAC_KEY_LEN];
+ u8 nep_key_mac_s2c[MAC_KEY_LEN];
+ u8 nep_key_ciphertext_c2s[CIPHER_KEY_LEN];
+ u8 nep_key_ciphertext_s2c[CIPHER_KEY_LEN];
+ u8 server_nonce[NONCE_LEN];
+ u8 client_nonce[NONCE_LEN];
+ bool server_nonce_set;
+ bool client_nonce_set;
+ std::vector<fspec_t> fspecs;
+ struct sockaddr_storage clnt_addr;
+
+ u8 *generateKey(int key_type, size_t *final_len);
+
+ public:
+
+ NEPContext();
+ ~NEPContext();
+ void reset();
+
+ int setIdentifier(clientid_t clnt);
+ clientid_t getIdentifier();
+
+ int setAddress(const struct sockaddr_storage &a);
+ struct sockaddr_storage getAddress();
+
+ int setNsockIOD(nsock_iod iod);
+ nsock_iod getNsockIOD();
+
+ int setState(int state);
+ int getState();
+
+ bool ready();
+
+ int setNextEncryptionIV(u8 *block);
+ u8 *getNextEncryptionIV(size_t *final_len);
+ u8 *getNextEncryptionIV();
+
+ int setNextDecryptionIV(u8 *block);
+ u8 *getNextDecryptionIV(size_t *final_len);
+ u8 *getNextDecryptionIV();
+
+ int setLastServerSequence(u32 seq);
+ u32 getLastServerSequence();
+ u32 getNextServerSequence();
+ int setLastClientSequence(u32 seq);
+ u32 getLastClientSequence();
+ u32 getNextClientSequence();
+ int generateInitialServerSequence();
+ int generateInitialClientSequence();
+
+ int setMacKeyC2S(u8 *key);
+ u8 *getMacKeyC2S();
+ u8 *getMacKeyC2S(size_t *final_len);
+ int generateMacKeyC2S();
+
+ int setMacKeyS2C(u8 *key);
+ u8 *getMacKeyS2C();
+ u8 *getMacKeyS2C(size_t *final_len);
+ int generateMacKeyS2C();
+
+ int setCipherKeyC2S(u8 *key);
+ u8 *getCipherKeyC2S();
+ u8 *getCipherKeyC2S(size_t *final_len);
+ int generateCipherKeyC2S();
+ int generateMacKeyS2CInitial();
+
+ int setCipherKeyS2C(u8 *key);
+ u8 *getCipherKeyS2C();
+ u8 *getCipherKeyS2C(size_t *final_len);
+ int generateCipherKeyS2C();
+
+ int generateClientNonce();
+ int generateServerNonce();
+ int setClientNonce(u8 *buff);
+ u8 *getClientNonce();
+ int setServerNonce(u8 *buff);
+ u8 *getServerNonce();
+
+ int addClientFieldSpec(u8 field, u8 len, u8 *value);
+ fspec_t *getClientFieldSpec(int index);
+ bool isDuplicateFieldSpec(u8 test_field);
+ int resetClientFieldSpecs();
+
+};
+
+#endif /* __NEPCONTEXT_H__ */
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() */
diff --git a/nping/NpingOps.h b/nping/NpingOps.h
new file mode 100644
index 0000000..37d5ee8
--- /dev/null
+++ b/nping/NpingOps.h
@@ -0,0 +1,650 @@
+
+/***************************************************************************
+ * NpingOps.h -- 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/
+ *
+ ***************************************************************************/
+
+#ifndef NPING_NPINGOPS_H
+#define NPING_NPINGOPS_H
+
+/* Probe Modes */
+#define TCP_CONNECT 0xF1
+#define TCP 0xF2
+#define UDP 0xF3
+#define UDP_UNPRIV 0xF4
+#define ICMP 0xF5
+#define ARP 0xF6
+
+/* Roles */
+#define ROLE_NORMAL 0x22
+#define ROLE_CLIENT 0x44
+#define ROLE_SERVER 0x66
+
+/* Payload types */
+#define PL_NONE 0x00
+#define PL_HEX 0xAA
+#define PL_RAND 0xBB
+#define PL_FILE 0xCC
+#define PL_STRING 0xDD
+
+/* Misc */
+#define ARP_TYPE_REQUEST 0x01
+#define ARP_TYPE_REPLY 0x02
+#define RARP_TYPE_REQUEST 0x03
+#define RARP_TYPE_REPLY 0x04
+
+#define FLAG_CWR 0 /* Do not change these values because they */
+#define FLAG_ECN 1 /* are used as indexes of an array */
+#define FLAG_URG 2
+#define FLAG_ACK 3
+#define FLAG_PSH 4
+#define FLAG_RST 5
+#define FLAG_SYN 6
+#define FLAG_FIN 7
+
+#define PACKET_SEND_NOPREF 1 /* These have been taken from NmapOps.h */
+#define PACKET_SEND_ETH_WEAK 2
+#define PACKET_SEND_ETH_STRONG 4
+#define PACKET_SEND_ETH 6
+#define PACKET_SEND_IP_WEAK 8
+#define PACKET_SEND_IP_STRONG 16
+#define PACKET_SEND_IP 24
+
+#define IP_VERSION_4 0x04
+#define IP_VERSION_6 0x06
+
+#define NOT_SET -1
+#define SET_RANDOM -2
+
+#define MAX_ICMP_ADVERT_ENTRIES 128
+
+#include "nping.h"
+#include "global_structures.h"
+#include "stats.h"
+#include "NpingTargets.h"
+#include <string>
+
+class NpingOps {
+
+ private:
+
+ /* Probe modes */
+ int mode; /* Probe mode (TCP,UDP,ICMP,ARP,RARP...) */
+ bool mode_set;
+ bool traceroute; /* Is traceroute mode enabled? */
+ bool traceroute_set;
+
+ /* Output */
+ int vb; /* Current Verbosity level */
+ bool vb_set;
+ int dbg; /* Current Debugging level */
+ bool dbg_set;
+ bool show_sent_pkts; /* Print packets sent by Nping? */
+ bool show_sent_pkts_set;
+
+ /* Operation and Performance */
+ u32 pcount; /* No of packets 2be sent to each target */
+ bool pcount_set;
+ int sendpref; /* Sending preference: eth or raw ip */
+ bool sendpref_set;
+ bool send_eth; /* True: send at raw ethernet level */
+ bool send_eth_set;
+ long delay; /* Delay between each probe */
+ bool delay_set;
+ char device[MAX_DEV_LEN]; /* Network interface */
+ bool device_set;
+ bool spoofsource; /* Did user request IP spoofing? */
+ bool spoofsource_set;
+ char *bpf_filter_spec; /* Custom, user-supplied BPF filter spec */
+ bool bpf_filter_spec_set;
+ int current_round; /** Current round. Used in traceroute mode */
+ bool have_pcap; /* True if we have access to libpcap */
+ bool disable_packet_capture; /* If false, no packets are captured */
+ bool disable_packet_capture_set;
+
+ /* Privileges */
+ bool isr00t; /* True if current user has root privs */
+
+ /* Payloads */
+ int payload_type; /* Type of payload (RAND,HEX,FILE) */
+ bool payload_type_set;
+ u8 *payload_buff; /* Pointer 2buff with the actual payload */
+ bool payload_buff_set;
+ int payload_len; /* Length of payload */
+ bool payload_len_set;
+
+ /* Roles */
+ int role; /* Nping's role: normal|client|server. */
+ bool role_set;
+
+ /* IPv4 */
+ u8 ttl; /* IPv4 TTL / IPv6 Hop limit */
+ bool ttl_set;
+ u8 tos; /* Type of service */
+ bool tos_set;
+ u16 identification; /* Identification field */
+ bool identification_set;
+ bool mf; /* More fragments flag */
+ bool mf_set;
+ bool df; /* Don't fragment flag */
+ bool df_set;
+ bool rf; /* Reserved / Evil flag */
+ bool rf_set;
+ u32 mtu; /* Custom MTU len (for IP fragmentation) */
+ bool mtu_set;
+ bool badsum_ip; /* Generate invalid checksums in TCP/UDP */
+ bool badsum_ip_set;
+ u8 ipversion; /* IP version to be used in all packets */
+ bool ipversion_set;
+ struct in_addr ipv4_src_address; /* Source IPv4 address */
+ bool ipv4_src_address_set;
+ char *ip_options; /* IP Options */
+ bool ip_options_set;
+
+ /* IPv6 */
+ u8 ipv6_tclass; /* Traffic Class */
+ bool ipv6_tclass_set;
+ u32 ipv6_flowlabel; /* Flow Label */
+ bool ipv6_flowlabel_set;
+ struct in6_addr ipv6_src_address; /**< Source IPv6 address */
+ bool ipv6_src_address_set;
+
+ /* TCP / UDP */
+ u16 *target_ports; /* Will point to an array of ports */
+ int tportcount; /* Total number of target ports */
+ bool target_ports_set;
+ u16 source_port; /* Source port for TCP/UPD packets */
+ bool source_port_set;
+ u32 tcpseq; /* TCP Sequence number */
+ bool tcpseq_set;
+ u32 tcpack; /* TCP Acknowledgement */
+ bool tcpack_set;
+ u8 tcpflags[8]; /* TCP Flags */
+ bool tcpflags_set;
+ u16 tcpwin; /* TCP Window */
+ bool tcpwin_set;
+ bool badsum; /* Generate invalid TCP/UDP checksums? */
+ bool badsum_set;
+
+ /* ICMP */
+ u8 icmp_type; /* ICMP Type */
+ bool icmp_type_set;
+ u8 icmp_code; /* ICMP Code */
+ bool icmp_code_set;
+ bool badsum_icmp; /* Generate invalid ICMP checksums? */
+ bool badsum_icmp_set;
+ struct in_addr icmp_redir_addr; /* ICMP Redirect Address */ /* ##TODO## Turn this into an IPAddress object */
+ bool icmp_redir_addr_set;
+ u8 icmp_paramprob_pnt; /* ICMP Parameter Problem pointer */
+ bool icmp_paramprob_pnt_set;
+ u16 icmp_routeadv_ltime; /* ICMP Router Advertisement lifetime */
+ bool icmp_routeadv_ltime_set;
+ u16 icmp_id; /* ICMP message identifier */
+ bool icmp_id_set;
+ u16 icmp_seq; /* ICMP sequence number */
+ bool icmp_seq_set;
+ u32 icmp_orig_time; /* ICMP originate timestamp */
+ bool icmp_orig_time_set;
+ u32 icmp_recv_time; /* ICMP receive timestamp */
+ bool icmp_recv_time_set;
+ u32 icmp_trans_time; /* ICMP transmit timestamp */
+ bool icmp_trans_time_set;
+ /* ICMP Router advertisement entries */
+ struct in_addr icmp_advert_entry_addr[MAX_ICMP_ADVERT_ENTRIES];
+ u32 icmp_advert_entry_pref[MAX_ICMP_ADVERT_ENTRIES];
+ int icmp_advert_entry_count;
+ bool icmp_advert_entry_set;
+
+ /* Ethernet */
+ u8 src_mac[6]; /* Source MAC address */
+ bool src_mac_set;
+ u8 dst_mac[6]; /* Destination MAC address */
+ bool dst_mac_set;
+ u16 eth_type; /* EtherType field of the Ethernet frame */
+ bool eth_type_set;
+
+ /* ARP/RARP */
+ u16 arp_htype; /* ARP Hardware type */
+ bool arp_htype_set;
+ u16 arp_ptype; /* ARP Protocol type */
+ bool arp_ptype_set;
+ u8 arp_hlen; /* ARP Hardware address length */
+ bool arp_hlen_set;
+ u8 arp_plen; /* ARP protocol address length */
+ bool arp_plen_set;
+ u16 arp_opcode; /* ARP Operation code */
+ bool arp_opcode_set;
+ u8 arp_sha[6]; /* ARP Sender hardware address */
+ bool arp_sha_set;
+ u8 arp_tha[6]; /* ARP Target hardware address */
+ bool arp_tha_set;
+ struct in_addr arp_spa; /* ARP Sender protocol address */
+ bool arp_spa_set;
+ struct in_addr arp_tpa; /* ARP Target protocol address */
+ bool arp_tpa_set;
+
+ /* Echo mode */
+ u16 echo_port; /* Echo port to listen or connect to */
+ bool echo_port_set;
+ char echo_passphrase[1024]; /* User passphrase */
+ bool echo_passphrase_set;
+ bool do_crypto; /* Do encrypted & authenticated sessions? */
+ bool echo_payload; /* Echo application-layer payloads? */
+ bool echo_payload_set;
+ bool echo_server_once; /* Run server for only 1 client and quit? */
+ bool echo_server_once_set;
+ struct timeval last_sent_pkt_time; /* Time last packet was sent */
+ char *delayed_rcvd_str; /* Delayed RCVD output string */
+ bool delayed_rcvd_str_set; /* Do we have a delayed RCVD string? */
+ nsock_event_id delayed_rcvd_event; /* Nsock event for delayed RCVD */
+
+ public:
+ NpingTargets targets;
+ NpingStats stats; /* Global statistics */
+
+ public:
+
+ /* Constructors / Destructors */
+ NpingOps();
+ ~NpingOps();
+
+ /* Probe modes */
+ int setMode(int md);
+ int getMode();
+ char *mode2Ascii(int md);
+ bool issetMode();
+
+ bool getTraceroute();
+ bool enableTraceroute();
+ bool disableTraceroute();
+ bool issetTraceroute();
+
+ /* Output */
+ int setVerbosity(int level);
+ int getVerbosity();
+ int increaseVerbosity();
+ int decreaseVerbosity();
+ bool issetVerbosity();
+
+ int setDebugging(int level);
+ int getDebugging();
+ int increaseDebugging();
+ bool issetDebugging();
+
+ int setShowSentPackets(bool val);
+ bool showSentPackets();
+ bool issetShowSentPackets();
+
+ /* Operation and Performance */
+ int setHostTimeout(long t);
+ long getHostTimeout();
+ bool issetHostTimeout();
+
+ int setDelay(long t);
+ long getDelay();
+ bool issetDelay();
+
+ int setPacketCount(u32 val);
+ u32 getPacketCount();
+ bool issetPacketCount();
+
+ int setSendPreference(int v);
+ int getSendPreference();
+ bool issetSendPreference();
+ bool sendPreferenceEthernet();
+ bool sendPreferenceIP();
+
+ int setSendEth(bool val);
+ bool sendEth();
+ bool issetSendEth();
+
+ int setDevice(char *n);
+ char *getDevice();
+ bool issetDevice();
+
+ int setSpoofSource();
+ bool spoofSource();
+ bool getSpoofSource();
+ bool issetSpoofSource();
+
+ int setBPFFilterSpec(char *val);
+ char *getBPFFilterSpec();
+ bool issetBPFFilterSpec();
+
+ int setCurrentRound(int val);
+ int getCurrentRound();
+ bool issetCurrentRound();
+
+ bool havePcap();
+ int setHavePcap(bool val);
+
+ int setDisablePacketCapture(bool val);
+ bool disablePacketCapture();
+ bool issetDisablePacketCapture();
+
+ int setIPVersion(u8 val);
+ int getIPVersion();
+ bool issetIPVersion();
+ bool ipv4();
+ bool ipv6();
+ bool ipv6UsingSocket();
+ int af();
+
+ /* Privileges */
+ int setIsRoot(int v);
+ int setIsRoot();
+ bool isRoot();
+
+ /* Payloads */
+ int setPayloadType(int t);
+ int getPayloadType();
+ bool issetPayloadType();
+ int setPayloadBuffer(u8 *p, int len);
+ u8 *getPayloadBuffer();
+ bool issetPayloadBuffer();
+ int getPayloadLen();
+ bool issetPayloadLen();
+
+ /* Roles */
+ int setRole(int r);
+ int setRoleClient();
+ int setRoleServer();
+ int setRoleNormal();
+ int getRole();
+ bool issetRole();
+
+ /* IPv4 */
+ bool enableBadsumIP();
+ bool disableBadsumIP();
+ bool getBadsumIP();
+ bool issetBadsumIP();
+
+ int setTTL(u8 t);
+ u8 getTTL();
+ bool issetTTL();
+
+ int setTOS(u8 tos);
+ u8 getTOS();
+ bool issetTOS();
+
+ int setIdentification(u16 i);
+ u16 getIdentification();
+ bool issetIdentification();
+
+ int setMF();
+ bool getMF();
+ bool issetMF();
+
+ int setDF();
+ bool getDF();
+ bool issetDF();
+
+ int setRF();
+ bool getRF();
+ bool issetRF();
+
+ struct in_addr getIPv4SourceAddress();
+ int setIPv4SourceAddress(struct in_addr i);
+ bool issetIPv4SourceAddress();
+
+ int setIPOptions(char *txt);
+ char *getIPOptions();
+ bool issetIPOptions();
+
+ int setMTU(u32 t);
+ u32 getMTU();
+ bool issetMTU();
+
+ /* IPv6 */
+ int setTrafficClass(u8 val);
+ u8 getTrafficClass();
+ bool issetTrafficClass();
+
+ int setFlowLabel(u32 val);
+ u32 getFlowLabel();
+ bool issetFlowLabel();
+
+ int setHopLimit(u8 t);
+ u8 getHopLimit();
+ bool issetHopLimit();
+
+ int setIPv6SourceAddress(u8 *val);
+ int setIPv6SourceAddress(struct in6_addr val);
+ struct in6_addr getIPv6SourceAddress();
+ bool issetIPv6SourceAddress();
+
+ struct sockaddr_storage *getSourceSockAddr();
+ struct sockaddr_storage *getSourceSockAddr(struct sockaddr_storage *ss);
+
+ /* TCP / UDP */
+ u16 *getTargetPorts( int *len );
+ int setTargetPorts( u16 *pnt, int n );
+ bool issetTargetPorts();
+ bool scan_mode_uses_target_ports(int mode);
+
+
+
+ int setSourcePort(u16 val);
+ u16 getSourcePort();
+ bool issetSourcePort();
+
+ bool enableBadsum();
+ bool disableBadsum();
+ bool getBadsum();
+ bool issetBadsum();
+
+ int setFlagTCP(int flag);
+ int setAllFlagsTCP();
+ int unsetAllFlagsTCP();
+ int getFlagTCP(int flag);
+ u8 getTCPFlags();
+ bool issetTCPFlags();
+
+ int setTCPSequence(u32 val);
+ u32 getTCPSequence();
+ bool issetTCPSequence();
+
+ int setTCPAck(u32 val);
+ u32 getTCPAck();
+ bool issetTCPAck();
+
+ int setTCPWindow(u16 val);
+ u16 getTCPWindow();
+ bool issetTCPWindow();
+
+ /* ICMP */
+ int setICMPType(u8 type);
+ u8 getICMPType();
+ bool issetICMPType();
+
+ int setICMPCode(u8 val);
+ u8 getICMPCode();
+ bool issetICMPCode();
+
+ bool enableBadsumICMP();
+ bool disableBadsumICMP();
+ bool getBadsumICMP();
+ bool issetBadsumICMP();
+
+ int setICMPRedirectAddress(struct in_addr val);
+ struct in_addr getICMPRedirectAddress();
+ bool issetICMPRedirectAddress();
+
+ int setICMPParamProblemPointer(u8 val);
+ u8 getICMPParamProblemPointer();
+ bool issetICMPParamProblemPointer();
+
+ int setICMPRouterAdvLifetime(u16 val);
+ u16 getICMPRouterAdvLifetime();
+ bool issetICMPRouterAdvLifetime();
+
+ int setICMPIdentifier(u16 val);
+ u16 getICMPIdentifier();
+ bool issetICMPIdentifier();
+
+ int setICMPSequence(u16 val);
+ u16 getICMPSequence();
+ bool issetICMPSequence();
+
+ int setICMPOriginateTimestamp(u32 val);
+ u32 getICMPOriginateTimestamp();
+ bool issetICMPOriginateTimestamp();
+
+ int setICMPReceiveTimestamp(u32 val);
+ u32 getICMPReceiveTimestamp();
+ bool issetICMPReceiveTimestamp();
+
+ int setICMPTransmitTimestamp(u32 val);
+ u32 getICMPTransmitTimestamp();
+ bool issetICMPTransmitTimestamp();
+
+ int addICMPAdvertEntry(struct in_addr addr, u32 pref );
+ int getICMPAdvertEntry(int num, struct in_addr *addr, u32 *pref);
+ int getICMPAdvertEntryCount();
+ bool issetICMPAdvertEntry();
+
+ /* Ethernet */
+ int setSourceMAC(u8 * val);
+ u8 * getSourceMAC();
+ bool issetSourceMAC();
+
+ int setDestMAC(u8 * val);
+ u8 * getDestMAC();
+ bool issetDestMAC();
+
+ int setEtherType(u16 val);
+ u16 getEtherType();
+ bool issetEtherType();
+
+ /* ARP/RARP */
+ int setARPHardwareType(u16 val);
+ u16 getARPHardwareType();
+ bool issetARPHardwareType();
+
+ int setARPProtocolType(u16 val);
+ u16 getARPProtocolType();
+ bool issetARPProtocolType();
+
+ int setARPHwAddrLen(u8 val);
+ u8 getARPHwAddrLen();
+ bool issetARPHwAddrLen();
+
+ int setARPProtoAddrLen(u8 val);
+ u8 getARPProtoAddrLen();
+ bool issetARPProtoAddrLen();
+
+ int setARPOpCode(u16 val);
+ u16 getARPOpCode();
+ bool issetARPOpCode();
+
+ int setARPSenderHwAddr(u8 * val);
+ u8 * getARPSenderHwAddr();
+ bool issetARPSenderHwAddr();
+
+ int setARPTargetHwAddr(u8 * val);
+ u8 * getARPTargetHwAddr();
+ bool issetARPTargetHwAddr();
+
+ int setARPSenderProtoAddr(struct in_addr val);
+ struct in_addr getARPSenderProtoAddr();
+ bool issetARPSenderProtoAddr();
+
+ int setARPTargetProtoAddr(struct in_addr val);
+ struct in_addr getARPTargetProtoAddr();
+ bool issetARPTargetProtoAddr();
+
+ /* Echo Mode */
+ int setEchoPort(u16 val);
+ u16 getEchoPort();
+ bool issetEchoPort();
+
+ int setEchoPassphrase(const char *str);
+ char *getEchoPassphrase();
+ bool issetEchoPassphrase();
+
+ bool doCrypto();
+ int doCrypto(bool value);
+
+ bool echoPayload();
+ int echoPayload(bool value);
+
+ int setOnce(bool val);
+ bool once();
+
+ /* Validation */
+ void validateOptions();
+ bool canRunUDPWithoutPrivileges();
+ bool canDoIPv6ThroughSocket();
+ bool canDoIPv6Ethernet();
+ char *select_network_iface();
+
+ /* Misc */
+ void displayNpingDoneMsg();
+ void displayStatistics();
+ int cleanup();
+ int setDefaultHeaderValues();
+ int getTotalProbes();
+
+ int setLastPacketSentTime(struct timeval t);
+ struct timeval getLastPacketSentTime();
+
+ int setDelayedRcvd(const char *str, nsock_event_id id);
+ char *getDelayedRcvd(nsock_event_id *id);
+
+}; /* End of class NpingOps */
+
+#endif // NPING_NPINGOPS_H
diff --git a/nping/NpingTarget.cc b/nping/NpingTarget.cc
new file mode 100644
index 0000000..d85296c
--- /dev/null
+++ b/nping/NpingTarget.cc
@@ -0,0 +1,1046 @@
+
+/***************************************************************************
+ * NpingTarget.cc -- The NpingTarget class encapsulates much of the *
+ * information Nping has about a host. Things like next hop address or the *
+ * network interface that should be used to send probes to the target, are *
+ * stored in this class as they are determined. *
+ * *
+ ***********************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 "nping_winconfig.h"
+#endif
+
+#ifndef FQDN_LEN
+#define FQDN_LEN 254
+#endif
+
+#include "NpingTarget.h"
+#include <dnet.h>
+#include "nbase.h"
+#include "nping.h"
+#include "output.h"
+#include "common.h"
+#include "stats.h"
+#include "common_modified.h"
+
+
+
+/** Constructor */
+NpingTarget::NpingTarget() {
+ this->Initialize();
+} /* End of NpingTarget constructor */
+
+
+/** Initializes object attributes */
+void NpingTarget::Initialize() {
+ memset(this->devname, 0, sizeof(this->devname));
+ memset(this->devfullname, 0, sizeof(this->devfullname));
+ dev_type=devt_other;
+ directly_connected = -1;
+ distance = -1;
+ nameIPBuf = NULL;
+ hostname = NULL;
+ namedhost=-1;
+ targetname = NULL;
+ addressfamily=-1;
+ memset(&targetsock, 0, sizeof(targetsock));
+ memset(&sourcesock, 0, sizeof(sourcesock));
+ memset(&spoofedsrcsock, 0, sizeof(spoofedsrcsock));
+ memset(&nexthopsock, 0, sizeof(nexthopsock));
+ targetsocklen = 0;
+ sourcesocklen = 0;
+ spoofedsrcsocklen=0;
+ nexthopsocklen = 0;
+ spoofedsrc_set=false;
+ memset(this->targetipstring, 0, INET6_ADDRSTRLEN);
+ targetipstring_set=false;
+ memset(&MACaddress, 0, sizeof(MACaddress));
+ memset(&SrcMACaddress, 0, sizeof(SrcMACaddress));
+ memset(&NextHopMACaddress, 0, sizeof(NextHopMACaddress));
+ MACaddress_set = false;
+ SrcMACaddress_set = false;
+ NextHopMACaddress_set = false;
+ icmp_id = get_random_u16();
+ icmp_seq = 1;
+ memset(sentprobes, 0, sizeof(pktstat_t)* MAX_SENTPROBEINFO_ENTRIES);
+ current_stat=0;
+ total_stats=0;
+ sent_total=0;
+ recv_total=0;
+ max_rtt=0;
+ max_rtt_set=false;
+ min_rtt=0;
+ min_rtt_set=false;
+ avg_rtt=0;
+ avg_rtt_set=false;
+} /* End of Initialize() */
+
+
+/** Recycles the object by freeing internal objects and reinitializing
+ * to default state */
+void NpingTarget::Recycle() {
+ this->FreeInternal();
+ this->Initialize();
+} /* End of Recycle() */
+
+
+/** Destructor */
+NpingTarget::~NpingTarget() {
+ this->FreeInternal();
+} /* End of NpingTarget destructor */
+
+
+/** Frees memory allocated inside this object */
+void NpingTarget::FreeInternal() {
+ /* Free the DNS name if we resolved one */
+ if (hostname){
+ free(hostname);
+ hostname=NULL;
+ }
+ /* Free user supplied host name if we got one */
+ if (targetname){
+ free(targetname);
+ targetname=NULL;
+ }
+ /* Free IP-Name info string */
+ if (nameIPBuf) {
+ free(nameIPBuf);
+ nameIPBuf = NULL;
+ }
+} /* End of FreeInternal() */
+
+
+/** Fills a sockaddr_storage with the AF_INET or AF_INET6 address
+ information of the target. This is a preferred way to get the
+ address since it is portable for IPv6 hosts. Returns 0 for
+ success. ss_len must be provided. It is not examined, but is set
+ to the size of the sockaddr copied in. */
+int NpingTarget::getTargetSockAddr(struct sockaddr_storage *ss, size_t *ss_len) {
+ assert(ss);
+ assert(ss_len);
+ if (targetsocklen <= 0)
+ return 1;
+ assert(targetsocklen <= sizeof(*ss));
+ memcpy(ss, &targetsock, targetsocklen);
+ *ss_len = targetsocklen;
+ return 0;
+
+} /* End of getTargetSockAddr() */
+
+
+/** Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
+ to sockaddr_storage */
+int NpingTarget::setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len) {
+ assert(ss_len > 0 && ss_len <= sizeof(*ss));
+ struct sockaddr_in *tmp=(struct sockaddr_in *)ss;
+ this->addressfamily=tmp->sin_family;
+ memcpy(&targetsock, ss, ss_len);
+ targetsocklen = ss_len;
+ generateIPString();
+ return OP_SUCCESS;
+} /* End of setTargetSockAddr() */
+
+
+/** Returns IPv4 host address or {0} if unavailable. */
+struct in_addr NpingTarget::getIPv4Address() {
+ const struct in_addr *addy = getIPv4Address_aux();
+ struct in_addr in;
+ if (addy) return *addy;
+ in.s_addr = 0;
+ return in;
+} /* End of getIPv4Address() */
+
+
+/** Aux function for getIPv4Address() */
+const struct in_addr *NpingTarget::getIPv4Address_aux(){
+ struct sockaddr_in *sin = (struct sockaddr_in *) &targetsock;
+ if (sin->sin_family == AF_INET) {
+ return &(sin->sin_addr);
+ }
+ return NULL;
+} /* End of getIPv4Address_aux() */
+
+
+u8 *NpingTarget::getIPv6Address_u8(){
+ const struct in6_addr *in = getIPv6Address_aux();
+ if( in==NULL )
+ return NULL;
+ else
+ return (u8*)in->s6_addr;
+} /* End of getIPv6Address_u8() */
+
+
+/** Returns IPv6 host address or {0} if unavailable. */
+struct in6_addr NpingTarget::getIPv6Address() {
+ const struct in6_addr *addy = getIPv6Address_aux();
+ struct in6_addr in;
+ if (addy) return *addy;
+ memset(&in, 0, sizeof(struct in6_addr));
+ return in;
+} /* End of getIPv6Address() */
+
+
+/** Aux function for getIPv6Address() */
+const struct in6_addr *NpingTarget::getIPv6Address_aux(){
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &targetsock;
+ if (sin->sin6_family == AF_INET6) {
+ return &(sin->sin6_addr);
+ }
+ return NULL;
+} /* End of getIPv6Address_aux() */
+
+
+/** Get source address used to reach the target. */
+int NpingTarget::getSourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len) {
+ if (sourcesocklen <= 0)
+ return 1;
+ assert(sourcesocklen <= sizeof(*ss));
+ if (ss)
+ memcpy(ss, &sourcesock, sourcesocklen);
+ if (ss_len)
+ *ss_len = sourcesocklen;
+ return 0;
+} /* End of getSourceSockAddr() */
+
+
+/** Set source address used to reach the target.
+ * Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
+ * to sockaddr_storage */
+int NpingTarget::setSourceSockAddr(struct sockaddr_storage *ss, size_t ss_len) {
+ assert(ss_len > 0 && ss_len <= sizeof(*ss));
+ memcpy(&sourcesock, ss, ss_len);
+ sourcesocklen = ss_len;
+ return OP_SUCCESS;
+} /* End of setSourceSockAddr() */
+
+
+/** Set source address used to reach the target.
+ * Note that it is OK to pass in a sockaddr_in or sockaddr_in6 casted
+ * to sockaddr_storage */
+int NpingTarget::setSpoofedSourceSockAddr(struct sockaddr_storage *ss, size_t ss_len) {
+ assert(ss_len > 0 && ss_len <= sizeof(*ss));
+ memcpy(&spoofedsrcsock, ss, ss_len);
+ spoofedsrcsocklen = ss_len;
+ this->spoofedsrc_set=true;
+ return OP_SUCCESS;
+} /* End of setSpoofedSourceSockAddr() */
+
+
+/** Get source address used to reach the target. */
+int NpingTarget::getSpoofedSourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len) {
+ if (spoofedsrcsocklen <= 0)
+ return 1;
+ assert(spoofedsrcsocklen <= sizeof(*ss));
+ if (ss)
+ memcpy(ss, &spoofedsrcsock, spoofedsrcsocklen);
+ if (ss_len)
+ *ss_len = spoofedsrcsocklen;
+ return 0;
+} /* End of getSpoofedSourceSockAddr() */
+
+
+bool NpingTarget::spoofingSourceAddress(){
+ return this->spoofedsrc_set;
+} /* End of spoofingSourceAddress()*/
+
+
+/** Returns IPv4 host address or {0} if unavailable. */
+struct in_addr NpingTarget::getIPv4SourceAddress() {
+ const struct in_addr *addy = getIPv4SourceAddress_aux();
+ struct in_addr in;
+ if (addy) return *addy;
+ in.s_addr = 0;
+ return in;
+} /* End of getIPv4SourceAddress() */
+
+
+/** Returns IPv4 host address or NULL if unavailable.*/
+const struct in_addr *NpingTarget::getIPv4SourceAddress_aux() {
+ struct sockaddr_in *sin = (struct sockaddr_in *) &sourcesock;
+ if (sin->sin_family == AF_INET) {
+ return &(sin->sin_addr);
+ }
+ return NULL;
+} /* End of getIPv4SourceAddress_aux() */
+
+
+
+
+/** Returns IPv4 host address or {0} if unavailable. */
+struct in_addr NpingTarget::getIPv4SpoofedSourceAddress() {
+ const struct in_addr *addy = getIPv4SpoofedSourceAddress_aux();
+ struct in_addr in;
+ if (addy) return *addy;
+ in.s_addr = 0;
+ return in;
+} /* End of getIPv4SourceAddress() */
+
+
+/** Returns IPv4 host address or NULL if unavailable.*/
+const struct in_addr *NpingTarget::getIPv4SpoofedSourceAddress_aux() {
+ struct sockaddr_in *sin = (struct sockaddr_in *) &spoofedsrcsock;
+ if (sin->sin_family == AF_INET) {
+ return &(sin->sin_addr);
+ }
+ return NULL;
+} /* End of getIPv4SpoofedSourceAddress_aux() */
+
+
+/** Returns IPv6 host address or {0} if unavailable. */
+struct in6_addr NpingTarget::getIPv6SourceAddress() {
+ const struct in6_addr *addy = getIPv6SourceAddress_aux();
+ struct in6_addr in;
+ if (addy) return *addy;
+ memset(&in, 0, sizeof(struct in6_addr));
+ return in;
+} /* End of getIPv6SourceAddress() */
+
+
+/** Returns IPv6 host address or NULL if unavailable.*/
+const struct in6_addr *NpingTarget::getIPv6SourceAddress_aux() {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &sourcesock;
+ if (sin6->sin6_family == AF_INET) {
+ return &(sin6->sin6_addr);
+ }
+ return NULL;
+} /* End of getIPv6SourceAddress_aux() */
+
+
+u8 *NpingTarget::getIPv6SourceAddress_u8(){
+ const struct in6_addr *in = getIPv6SourceAddress_aux();
+ if( in==NULL )
+ return NULL;
+ else
+ return (u8*)in->s6_addr;
+} /* End of getIPv6Address_u8() */
+
+
+/** If the host is directly connected on a network, set and retrieve
+ * that information here. directlyConnected() will abort if it hasn't
+ * been set yet. */
+void NpingTarget::setDirectlyConnected(bool connected) {
+ directly_connected = (connected) ? 1 : 0;
+} /* End of setDirectlyConnected() */
+
+
+int NpingTarget::isDirectlyConnectedOrUnset(){
+ return directly_connected;
+} /* End of isDirectlyConnectedOrUnset() */
+
+
+bool NpingTarget::isDirectlyConnected() {
+ assert(directly_connected == 0 || directly_connected == 1);
+ return directly_connected;
+} /* End of isDirectlyConnected() */
+
+
+/** Returns the next hop for sending packets to this host. Returns true if
+ * next_hop was filled in. It might be false, for example, if
+ * next_hop has never been set */
+bool NpingTarget::getNextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len) {
+ if (nexthopsocklen <= 0)
+ return false;
+ assert(nexthopsocklen <= sizeof(*next_hop));
+ if (next_hop)
+ memcpy(next_hop, &nexthopsock, nexthopsocklen);
+ if (next_hop_len)
+ *next_hop_len = nexthopsocklen;
+ return true;
+} /* End of getNextHop() */
+
+
+/** Sets the next hop for sending packets to this host. Note that it is OK to
+ * pass in a sockaddr_in or sockaddr_in6 casted to sockaddr_storage */
+void NpingTarget::setNextHop(struct sockaddr_storage *next_hop, size_t next_hop_len) {
+ assert(next_hop_len > 0 && next_hop_len <= sizeof(nexthopsock));
+ memcpy(&nexthopsock, next_hop, next_hop_len);
+ nexthopsocklen = next_hop_len;
+} /* End of setNextHop() */
+
+
+/** Sets next hop MAC address
+ * @warning addy must contain at least 6 bytes. */
+int NpingTarget::setNextHopMACAddress(const u8 *addy) {
+ if (addy==NULL)
+ return OP_FAILURE;
+ memcpy(NextHopMACaddress, addy, 6);
+ NextHopMACaddress_set = 1;
+ return OP_SUCCESS;
+} /* End of setNextHopMACAddress() */
+
+
+/** Returns a pointer to a 6 byte buffer that contains next hop MAC address */
+const u8 *NpingTarget::getNextHopMACAddress() {
+ return (NextHopMACaddress_set)? NextHopMACaddress : NULL;
+} /* End of getNextHopMACAddress() */
+
+
+/** Sets target MAC address.
+ * Returns OP_SUCCESS if MAC address set successfully and OP_FAILURE in case
+ * of error. */
+int NpingTarget::setMACAddress(const u8 *addy) {
+ if (addy==NULL)
+ return OP_FAILURE;
+ memcpy(MACaddress, addy, 6);
+ MACaddress_set = 1;
+ return OP_SUCCESS;
+} /* End of setMACAddress() */
+
+
+/** Returns the 6-byte long MAC address, or NULL if none has been set */
+const u8 *NpingTarget::getMACAddress(){
+ return (MACaddress_set)? MACaddress : NULL;
+} /* End of getMACAddress() */
+
+
+/** Sets the MAC address that should be used when sending raw ethernet frames
+ * from this host to the target.
+ * Returns OP_SUCCESS if MAC address set successfully and OP_FAILURE in case
+ * of error. */
+int NpingTarget::setSrcMACAddress(const u8 *addy) {
+ if (addy==NULL)
+ return OP_FAILURE;
+ memcpy(SrcMACaddress, addy, 6);
+ SrcMACaddress_set = 1;
+ return OP_SUCCESS;
+} /* End of setSrcMACAddress() */
+
+
+/** Returns the 6-byte long Source MAC address, or NULL if none has been set */
+const u8 *NpingTarget::getSrcMACAddress() {
+ return (SrcMACaddress_set)? SrcMACaddress : NULL;
+} /* End of getSrcMACAddress() */
+
+
+/** Set the device names so that they can be returned by deviceName()
+ and deviceFullName(). The normal name may not include alias
+ qualifier, while the full name may include it (e.g. "eth1:1"). If
+ these are non-null, they will overwrite the stored version */
+void NpingTarget::setDeviceNames(const char *name, const char *fullname) {
+ if (name)
+ Strncpy(devname, name, sizeof(devname));
+ if (fullname)
+ Strncpy(devfullname, fullname, sizeof(devfullname));
+} /* End of setDeviceNames() */
+
+
+/** Returns device normal name (e.g. eth0) */
+const char * NpingTarget::getDeviceName() {
+ return (devname[0] != '\0')? devname : NULL;
+} /* End of getDeviceName() */
+
+
+/** Returns device full name (e.g. eth0:1) */
+const char * NpingTarget::getDeviceFullName() {
+ return (devfullname[0] != '\0')? devfullname : NULL;
+} /* End of getDeviceFullName() */
+
+
+int NpingTarget::setDeviceType(devtype type){
+ this->dev_type = type;
+ return OP_SUCCESS;
+} /* End of setDeviceType() */
+
+
+devtype NpingTarget::getDeviceType(){
+ return this->dev_type;
+} /* End of getDeviceType() */
+
+
+/** Set target resolved host name. You can set to NULL to erase a name or if
+ * it failed to resolve, or just don't call this if it fails to resolve */
+void NpingTarget::setResolvedHostName(char *name) {
+ char *p;
+ if (hostname) {
+ free(hostname);
+ hostname = NULL;
+ }
+ if (name) {
+ p = hostname = strdup(name);
+ while (*p) {
+ // I think only a-z A-Z 0-9 . and - are allowed, but I'll be a little more
+ // generous.
+ if (!isalnum(*p) && !strchr(".-+=:_~*", *p)) {
+ nping_warning(QT_2, "Illegal character(s) in hostname -- replacing with '*'\n");
+ *p = '*';
+ }
+ p++;
+ }
+ }
+} /* End of setResolvedHostName() */
+
+
+/** Give the name from the last setHostName() call, which should be
+ the name obtained from reverse-resolution (PTR query) of the IP (v4
+ or v6). If the name has not been set, or was set to NULL, an empty
+ string ("") is returned to make printing easier. */
+const char *NpingTarget::getResolvedHostName(){
+ return hostname? hostname : "";
+} /* End of getResolvedHostName() */
+
+
+/** Set user supplied host name. You can set to NULL to erase a name. */
+int NpingTarget::setSuppliedHostName(char *name) {
+ if(name==NULL)
+ return OP_FAILURE;
+ if (targetname) {
+ free(targetname);
+ targetname = NULL;
+ }
+ targetname = strdup(name);
+ return OP_SUCCESS;
+} /* End of setSuppliedHostName() */
+
+
+/** Give the name from the last setTargetName() call, which is the
+ name of the target given on the command line if it's a named
+ host. */
+const char *NpingTarget::getSuppliedHostName(){
+ return targetname;
+} /* End of getSuppliedHostName() */
+
+
+int NpingTarget::setNamedHost(bool val){
+ this->namedhost= (val)? 1 : 0;
+ return OP_SUCCESS;
+} /* End of setNamedHost() */
+
+
+bool NpingTarget::isNamedHost(){
+ assert(this->namedhost==1 || this->namedhost==0 );
+ return (this->namedhost==1);
+} /* End of isNamedHost() */
+
+
+/** Creates a "presentation" formatted string out of the IPv4/IPv6 address.
+ Called when the IP changes */
+void NpingTarget::generateIPString() {
+ const char *ret=NULL;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &targetsock;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &targetsock;
+ if (sin->sin_family == AF_INET){
+ ret=inet_ntop(AF_INET, (char *) &sin->sin_addr, targetipstring, sizeof(targetipstring));
+ }else if(sin->sin_family == AF_INET6){
+ ret=inet_ntop(AF_INET6, (char *) &sin6->sin6_addr, targetipstring, sizeof(targetipstring));
+ }else{
+ nping_fatal(QT_3, "NpingTarget::GenerateIPString(): Unsupported address family");
+ }
+ if( ret==NULL )
+ nping_fatal(QT_3, "NpingTarget::GenerateIPString(): Unsupported address family");
+ targetipstring_set=true;
+} /* End of generateIPString() */
+
+
+/** Creates a "presentation" formatted string out of the IPv4/IPv6 address.
+ Called when the IP changes */
+const char *NpingTarget::getSourceIPStr() {
+ static char buffer[256];
+ const char *ret=NULL;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &sourcesock;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &sourcesock;
+
+ if (sin->sin_family == AF_INET){
+ ret=inet_ntop(AF_INET, (char *) &sin->sin_addr, buffer, sizeof(buffer));
+ }else if(sin->sin_family == AF_INET6){
+ ret=inet_ntop(AF_INET6, (char *) &sin6->sin6_addr, buffer, sizeof(buffer));
+ }else{
+ nping_fatal(QT_3, "NpingTarget::getSourceIPString(): Unsupported address family");
+ }
+ if(ret==NULL)
+ return NULL;
+ else
+ return buffer;
+} /* End of getSourceIPStr() */
+
+
+
+
+/** Creates a "presentation" formatted string out of the IPv4/IPv6 address.
+ Called when the IP changes */
+const char *NpingTarget::getSpoofedSourceIPStr() {
+ static char buffer[256];
+ const char *ret=NULL;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &spoofedsrcsock;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &spoofedsrcsock;
+
+ if (sin->sin_family == AF_INET){
+ ret=inet_ntop(AF_INET, (char *) &sin->sin_addr, buffer, sizeof(buffer));
+ }else if(sin->sin_family == AF_INET6){
+ ret=inet_ntop(AF_INET6, (char *) &sin6->sin6_addr, buffer, sizeof(buffer));
+ }else{
+ nping_fatal(QT_3, "NpingTarget::getSourceIPString(): Unsupported address family");
+ }
+ if(ret==NULL)
+ return NULL;
+ else
+ return buffer;
+} /* End of getSpoofedSourceIPStr() */
+
+
+const char *NpingTarget::getNextHopIPStr(){
+ static char buffer[256];
+ const char *ret=NULL;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &nexthopsock;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &nexthopsock;
+ if (sin->sin_family == AF_INET){
+ ret=inet_ntop(AF_INET, (char *) &sin->sin_addr, buffer, sizeof(buffer));
+ }else if(sin->sin_family == AF_INET6){
+ ret=inet_ntop(AF_INET6, (char *) &sin6->sin6_addr, buffer, sizeof(buffer));
+ }else{
+ nping_fatal(QT_3, "NpingTarget::getNextHopIPStr(): Unsupported address family");
+ }
+ if(ret==NULL)
+ return NULL;
+ else
+ return buffer;
+} /* End of getNextHopIPStr() */
+
+
+const char *NpingTarget::getMACStr(u8 *mac){
+ static char buffer[256];
+ assert(mac!=NULL);
+ sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x", (u8)mac[0],(u8)mac[1],
+ (u8)mac[2], (u8)mac[4],(u8)mac[4],(u8)mac[5]);
+ return buffer;
+}
+
+const char *NpingTarget::getTargetMACStr(){
+ return getMACStr(this->MACaddress);
+}
+
+
+const char *NpingTarget::getSourceMACStr(){
+ return getMACStr(this->SrcMACaddress);
+}
+
+
+const char *NpingTarget::getNextHopMACStr(){
+ return getMACStr(this->NextHopMACaddress);
+}
+
+
+/** Returns a "presentation" formatted string for the targetIPv4/IPv6 address. */
+const char *NpingTarget::getTargetIPstr(){
+ if( targetipstring_set == false )
+ this->generateIPString();
+ return targetipstring;
+} /* End of getTargetIPstr() */
+
+
+/** Generates a printable string consisting of the host's IP address and
+ * hostname (if available). Eg "www.insecure.org (64.71.184.53)" or
+ * "fe80::202:e3ff:fe14:1102". The name is written into the buffer provided,
+ * which is also returned. Results that do not fit in buflen will be
+ * truncated.
+ */
+const char *NpingTarget::getNameAndIP(char *buf, size_t buflen) {
+ assert(buf);
+ assert(buflen > 8);
+ if (hostname) {
+ Snprintf(buf, buflen, "%s (%s)", hostname, targetipstring);
+ }else if (targetname){
+ Snprintf(buf, buflen, "%s (%s)", targetname, targetipstring);
+ }else Strncpy(buf, targetipstring, buflen);
+ return buf;
+} /* End of getNameAndIP() */
+
+/** This next version returns a static buffer -- so no concurrency */
+const char *NpingTarget::getNameAndIP() {
+ if(!nameIPBuf)
+ nameIPBuf = (char *)safe_malloc(FQDN_LEN + INET6_ADDRSTRLEN + 4);
+ return getNameAndIP(nameIPBuf, FQDN_LEN + INET6_ADDRSTRLEN + 4);
+} /* End of getNameAndIP() */
+
+
+/* This method returns a number suitable to be used as a ICMP sequence field.
+ * The first time this function is called, 1 is returned. The internal icmp_seq
+ * attribute is incremented in every call so subsequent calls will return
+ * n+1 where n is the value returned by last call. */
+u16 NpingTarget::obtainICMPSequence() {
+ return this->icmp_seq++;
+} /* End of obtainICMPSequence() */
+
+
+u16 NpingTarget::getICMPIdentifier(){
+ return this->icmp_id;
+} /* End of getICMPIdentifier()*/
+
+
+/* This function ensures that the next hop MAC address for a target is
+ filled in. This address is the target's own MAC if it is directly
+ connected, and the next hop mac otherwise. Returns true if the
+ address is set when the function ends, false if not. This function
+ firt checks if it is already set, if not it tries the arp cache,
+ and if that fails it sends an ARP request itself. This should be
+ called after an ARP scan if many directly connected machines are
+ involved. setDirectlyConnected() (whether true or false) should
+ have already been called on target before this. The target device
+ and src mac address should also already be set. */
+bool NpingTarget::determineNextHopMACAddress() {
+ struct sockaddr_storage targetss, srcss;
+ size_t sslen;
+ arp_t *a;
+ u8 mac[6];
+ struct arp_entry ae;
+
+ if (this->getDeviceType() != devt_ethernet)
+ return false; /* Duh. */
+
+ /* First check if we already have it, duh. */
+ if ( this->getNextHopMACAddress() )
+ return true;
+
+ nping_print(DBG_2,"Determining target %s MAC address or next hop MAC address...", this->getTargetIPstr() );
+ /* For connected machines, it is the same as the target addy */
+ if (this->isDirectlyConnected() && this->getMACAddress() ) {
+ this->setNextHopMACAddress(this->getMACAddress());
+ return true;
+ }
+
+ if (this->isDirectlyConnected()) {
+ this->getTargetSockAddr(&targetss, &sslen);
+ } else {
+ if (!this->getNextHop(&targetss, &sslen))
+ fatal("%s: Failed to determine nextHop to target", __func__);
+ }
+
+ /* First, let us check the ARP cache ... */
+ if (mac_cache_get(&targetss, mac)) {
+ this->setNextHopMACAddress(mac);
+ return true;
+ }
+
+ /* Maybe the system ARP cache will be more helpful */
+ nping_print(DBG_3," > Checking system's ARP cache...");
+ a = arp_open();
+ addr_ston((sockaddr *)&targetss, &ae.arp_pa);
+ if (arp_get(a, &ae) == 0) {
+ mac_cache_set(&targetss, ae.arp_ha.addr_eth.data);
+ this->setNextHopMACAddress(ae.arp_ha.addr_eth.data);
+ arp_close(a);
+ nping_print(DBG_3," > Success: Entry found [%s]", this->getNextHopMACStr() );
+ return true;
+ }
+ arp_close(a);
+ nping_print(DBG_3," > No relevant entries found in system's ARP cache.");
+
+
+ /* OK, the last choice is to send our own damn ARP request (and
+ retransmissions if necessary) to determine the MAC */
+ /* We first try sending the ARP with our spoofed IP address on it */
+ if( this->spoofingSourceAddress() ){
+ nping_print(DBG_3," > Sending ARP request using spoofed IP %s...", this->getSpoofedSourceIPStr() );
+ this->getSpoofedSourceSockAddr(&srcss, NULL);
+ if (doArp(this->getDeviceName(), this->getSrcMACAddress(), &srcss, &targetss, mac, NULL)) {
+ mac_cache_set(&targetss, mac);
+ this->setNextHopMACAddress(mac);
+ nping_print(DBG_4," > Success: 1 ARP response received [%s]", this->getNextHopMACStr() );
+ return true;
+ }
+ }
+ nping_print(DBG_3," > No ARP responses received." );
+
+ /* If our spoofed IP address didn't work, try our real IP */
+ nping_print(DBG_4," > Sending ARP request using our real IP %s...", this->getSourceIPStr() );
+ this->getSourceSockAddr(&srcss, NULL);
+ if (doArp(this->getDeviceName(), this->getSrcMACAddress(), &srcss, &targetss, mac, NULL)) {
+ mac_cache_set(&targetss, mac);
+ this->setNextHopMACAddress(mac);
+ nping_print(DBG_3," > Success: 1 ARP response received [%s]", this->getNextHopMACStr() );
+ return true;
+ }
+ nping_print(DBG_3," > No ARP responses received" );
+
+ /* I'm afraid that we couldn't find it! Maybe it doesn't exist?*/
+ return false;
+}
+
+
+/* Sets Target MAC if is directly connected to us. In that case, Next Hop MAC
+ * address is copied into the target mac */
+bool NpingTarget::determineTargetMACAddress() {
+ if( this->isDirectlyConnected() ){
+ if(this->NextHopMACaddress_set){
+ memcpy(MACaddress, NextHopMACaddress, 6);
+ return true;
+ }
+ }
+ return false;
+} /* End of determineTargetMACAddress() */
+
+
+/* Prints target details. Used for testing. */
+void NpingTarget::printTargetDetails(){
+ devtype aux = this->getDeviceType();
+ const char *type=NULL;
+
+ switch(aux){
+ case devt_ethernet: type="Ethernet"; break;
+ case devt_loopback: type="Loopback"; break;
+ case devt_p2p: type="P2P"; break;
+ default: type="Unknown"; break;
+ }
+
+ printf("+-----------------TARGET-----------------+\n");
+ printf("Device Name: %s\n", this->getDeviceName() );
+ printf("Device FullName: %s\n", this->getDeviceFullName());
+ printf("Device Type: %s\n", type);
+ printf("Directly connected?: %s\n", this->isDirectlyConnected()? "yes" : "no");
+ printf("Address family: %s\n", this->addressfamily==AF_INET? "AF_INET" : "AF_INET6/OTHER");
+ printf("Resolved Hostname: %s\n", this->getResolvedHostName());
+ printf("Supplied Hostname: %s\n", this->getSuppliedHostName());
+ printf("Target Address: %s\n", this->getTargetIPstr());
+ printf("Source Address: %s\n", this->getSourceIPStr());
+ if(this->spoofedsrc_set)
+ printf("Spoofed Address: %s\n", this->getSpoofedSourceIPStr() );
+ printf("Next Hop Address: %s\n", this->getNextHopIPStr());
+ printf("Target MAC Address: %s\n", this->getTargetMACStr());
+ printf("Source MAC Address: %s\n", this->getSourceMACStr());
+ printf("Next Hop MAC Address: %s\n", this->getNextHopMACStr());
+ return;
+} /* End of printTargetDetails() */
+
+
+
+
+
+/* Update info about the last TCP probe sent */
+int NpingTarget::setProbeSentTCP(u16 sport, u16 dport){
+ this->sent_total++;
+ /* Check if we already have an entry for the supplied dst port */
+ for(int i=0; i<MAX_SENTPROBEINFO_ENTRIES && i<total_stats; i++){
+ if( this->sentprobes[i].tcp_port==dport ){
+ gettimeofday(&this->sentprobes[i].sent, NULL); /* overwrite previous value? TODO: think about this */
+ return OP_SUCCESS;
+ }
+ }
+ /* If we get here means that we don't have the dst port on our small
+ * stats "cache", so we have to overwrite an existing port with this one */
+ gettimeofday(&this->sentprobes[current_stat].sent, NULL);
+ this->sentprobes[current_stat].tcp_port=dport;
+ current_stat=(current_stat+1)%MAX_SENTPROBEINFO_ENTRIES;
+ if( total_stats< MAX_SENTPROBEINFO_ENTRIES)
+ total_stats++;
+ return OP_SUCCESS;
+} /* End of setProbeSentTCP() */
+
+
+/* Update info about the last TCP probe received */
+int NpingTarget::setProbeRecvTCP(u16 sport, u16 dport){
+ int i=0;
+ unsigned long int diff=0;
+ this->recv_total++;
+/* Let's see if we have the supplied source port in our stats "cache". */
+ for(i=0; i<MAX_SENTPROBEINFO_ENTRIES; i++){
+ if( this->sentprobes[i].tcp_port == sport ){
+ gettimeofday(&this->sentprobes[i].recv, NULL);
+ /* Update stats info */
+ diff= TIMEVAL_SUBTRACT(this->sentprobes[i].recv, this->sentprobes[i].sent);
+ this->updateRTTs(diff);
+
+ return OP_SUCCESS;
+ }
+ }
+ /* If we get here means that, for some reason, we don't have a tx time for
+ * the received packet so there is no point on updating anything since we
+ * cannot compute the rtt without the initial time. */
+ return OP_FAILURE;
+} /* End of setProbeRecvTCP() */
+
+
+/* For the moment we are treating TCP and UDP the same way. However, this
+ * function is provided just in case we want to differentiate in the future. */
+int NpingTarget::setProbeRecvUDP(u16 sport, u16 dport){
+ return this->setProbeRecvTCP(sport, dport);
+} /* End of setProbeRecvUDP() */
+
+
+/* For the moment we are treating TCP and UDP the same way. However, this
+ * function is provided just in case we want to differentiate in the future. */
+int NpingTarget::setProbeSentUDP(u16 sport, u16 dport){
+ return this->setProbeSentTCP(sport, dport);
+} /* End of setProbeSentUDP() */
+
+
+/* Update info about the last ICMP probe sent */
+int NpingTarget::setProbeSentICMP(u16 id, u16 seq){
+ this->sent_total++;
+ /* Check if we already have an entry for the supplied id and seq numbers */
+ for(int i=0; i<MAX_SENTPROBEINFO_ENTRIES && i<total_stats; i++){
+ if( this->sentprobes[i].icmp_id==id && this->sentprobes[i].icmp_seq==seq){
+ gettimeofday(&this->sentprobes[i].sent, NULL); /* overwrite previous value? TODO: think about this */
+ return OP_SUCCESS;
+ }
+ }
+ /* If we get here means that we don't have the id/seq on our small
+ * stats "cache", so we have to overwrite an existing entry with this one */
+ gettimeofday(&this->sentprobes[current_stat].sent, NULL);
+ this->sentprobes[current_stat].icmp_id=id;
+ this->sentprobes[current_stat].icmp_seq=seq;
+ current_stat=(current_stat+1)%MAX_SENTPROBEINFO_ENTRIES;
+ if( total_stats< MAX_SENTPROBEINFO_ENTRIES)
+ total_stats++;
+ return OP_SUCCESS;
+} /* End of setProbeSentARP() */
+
+
+
+
+/* Update info about the last ICMP probe received */
+int NpingTarget::setProbeRecvICMP(u16 id, u16 seq){
+ int i= this->current_stat-1;
+ unsigned long int diff=0;
+
+ if( i<0 && total_stats>=MAX_SENTPROBEINFO_ENTRIES)
+ i=MAX_SENTPROBEINFO_ENTRIES-1;
+
+ gettimeofday(&this->sentprobes[i].recv, NULL);
+
+ /* Update stats info */
+ recv_total++;
+ diff= TIMEVAL_SUBTRACT(this->sentprobes[i].recv, this->sentprobes[i].sent);
+ this->updateRTTs(diff);
+ return OP_FAILURE;
+} /* End of setProbeRecvICMP() */
+
+
+/* Update info about the last ARP probe sent */
+int NpingTarget::setProbeSentARP(){
+ this->sent_total++;
+ return OP_SUCCESS;
+} /* End of setProbeSentARP() */
+
+
+/* Update info about the last ICMP probe received */
+int NpingTarget::setProbeRecvARP(){
+ //int i= this->current_stat-1;
+ //unsigned long int diff=0;
+ return OP_FAILURE;
+} /* End of setProbeRecvICMP() */
+
+
+/* Assumes recv_total has already been incremented */
+int NpingTarget::updateRTTs(unsigned long int diff){
+ if( diff > max_rtt || max_rtt==0 ){
+ max_rtt=diff;
+ max_rtt_set=true;
+ }
+ if( diff < min_rtt || min_rtt==0){
+ min_rtt=diff;
+ min_rtt_set=true;
+ }
+
+ /* Update average round trip time */
+ if(!avg_rtt_set || recv_total<=1)
+ avg_rtt = diff;
+ else
+ avg_rtt = ((avg_rtt*(recv_total-1))+diff) / (recv_total);
+ avg_rtt_set=true;
+
+ return OP_SUCCESS;
+} /* End of updateRTTs() */
+
+
+int NpingTarget::printStats(){
+ nping_print(VB_0, "Statistics for host %s:", this->getNameAndIP());
+ nping_print(VB_0|NO_NEWLINE," | ");
+ this->printCounts();
+ nping_print(VB_0|NO_NEWLINE," |_ ");
+ this->printRTTs();
+ return OP_SUCCESS;
+} /* End of printStats() */
+
+
+/* Print packet counts */
+void NpingTarget::printCounts(){
+ unsigned long int lost = this->sent_total - this->recv_total;
+
+ /* Sent Packets */
+ nping_print(VB_0|NO_NEWLINE, "Probes Sent: %ld ", this->sent_total);
+ /* Received Packets */
+ nping_print(VB_0|NO_NEWLINE,"| Rcvd: %ld ", this->recv_total );
+ /* Lost Packets */
+ nping_print(VB_0|NO_NEWLINE,"| Lost: %ld ", lost );
+
+ /* Only compute percentage if we actually sent packets, don't do divisions
+ * by zero! (this could happen when user presses CTRL-C and we print the
+ * stats */
+ float percentlost=0.0;
+ if( lost!=0 && this->sent_total!=0)
+ percentlost=((double)lost)/((double)this->sent_total) * 100;
+ nping_print(VB_0," (%.2lf%%)", percentlost);
+} /* End of printCounts() */
+
+
+/* Print round trip times */
+void NpingTarget::printRTTs(){
+ if( max_rtt_set )
+ nping_print(QT_1|NO_NEWLINE,"Max rtt: %.3lfms ", this->max_rtt/1000.0 );
+ else
+ nping_print(QT_1|NO_NEWLINE,"Max rtt: N/A ");
+
+ if( min_rtt_set )
+ nping_print(QT_1|NO_NEWLINE,"| Min rtt: %.3lfms ", this->min_rtt/1000.0 );
+ else
+ nping_print(QT_1|NO_NEWLINE,"| Min rtt: N/A " );
+
+ if( avg_rtt_set)
+ nping_print(QT_1,"| Avg rtt: %.3lfms", this->avg_rtt/1000.0 );
+ else
+ nping_print(QT_1,"| Avg rtt: N/A" );
+} /* End of printRTTs() */
diff --git a/nping/NpingTarget.h b/nping/NpingTarget.h
new file mode 100644
index 0000000..942b1ed
--- /dev/null
+++ b/nping/NpingTarget.h
@@ -0,0 +1,261 @@
+
+/***************************************************************************
+ * NpingTarget.h -- The NpingTarget class encapsulates much of the *
+ * information Nping has about a host. Things like next hop address or the *
+ * network interface that should be used to send probes to the target, are *
+ * stored in this class as they are determined. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef NPINGTARGET_H
+#define NPINGTARGET_H
+
+#include "nping.h"
+#include "common.h"
+#include "../libnetutil/netutil.h"
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+class NpingTarget {
+
+ private:
+
+ char devname[32]; /**< Net interface normal name */
+ char devfullname[32]; /**< Net interface full name */
+ devtype dev_type; /**< Type of network interface */
+ int directly_connected; /**< -1 = unset; 0 = no; 1 = yes */
+ int distance; /**< Distance to target in hops */
+ int addressfamily; /**< Address family: AF_INET or AF_INET6 */
+ char *nameIPBuf; /**< for the NameIP(void) function to return */
+ char *hostname; /**< Resolved host name */
+ int namedhost; /**< =1 is named host; =0 is an IP; =-1 unset */
+ char *targetname; /**< Name of the target host given on the *
+ * command line if it is a named host */
+
+ struct sockaddr_storage targetsock; /**< Target address */
+ size_t targetsocklen;
+
+ struct sockaddr_storage sourcesock; /**< Source address */
+ size_t sourcesocklen;
+
+ struct sockaddr_storage spoofedsrcsock; /**< Spoofed Source address */
+ size_t spoofedsrcsocklen;
+ bool spoofedsrc_set;
+
+ struct sockaddr_storage nexthopsock; /**< Next Hop address */
+ size_t nexthopsocklen;
+
+ char targetipstring[INET6_ADDRSTRLEN];
+ bool targetipstring_set;
+
+ u8 MACaddress[6]; /**< Target MAC Address */
+ bool MACaddress_set;
+
+ u8 SrcMACaddress[6]; /**< Source MAC Address */
+ bool SrcMACaddress_set;
+
+ u8 NextHopMACaddress[6]; /**< Next Hop MAC Address */
+ bool NextHopMACaddress_set;
+
+ /* This is for the ICMP identification field. It is supposed to be
+ * initialized only once so we send all ICMP probes to this target with
+ * the same ID (as ping utilities do) */
+ u16 icmp_id;
+
+ /* This is for the ICMP sequence field. It is supposed to be initialized
+ * to 1 and then be incremented each time its value is requested through
+ * obtainICMPSequence(). */
+ u16 icmp_seq;
+
+ /* Private methods */
+ void Initialize();
+ void FreeInternal();
+ void generateIPString();
+
+ public:
+
+ NpingTarget();
+ ~NpingTarget();
+ void Recycle();
+
+ /* Target IP address */
+ int getTargetSockAddr(struct sockaddr_storage *ss, size_t *ss_len);
+ int setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len);
+ struct in_addr getIPv4Address();
+ const struct in_addr *getIPv4Address_aux();
+ struct in6_addr getIPv6Address();
+ const struct in6_addr *getIPv6Address_aux();
+ u8 *getIPv6Address_u8();
+
+ /* Source address used to reach the target */
+ int getSourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len);
+ int setSourceSockAddr(struct sockaddr_storage *ss, size_t ss_len);
+ int getSpoofedSourceSockAddr(struct sockaddr_storage *ss, size_t *ss_len);
+ int setSpoofedSourceSockAddr(struct sockaddr_storage *ss, size_t ss_len);
+ bool spoofingSourceAddress();
+ struct in_addr getIPv4SourceAddress();
+ const struct in_addr *getIPv4SourceAddress_aux();
+ struct in_addr getIPv4SpoofedSourceAddress();
+ const struct in_addr *getIPv4SpoofedSourceAddress_aux();
+ struct in6_addr getIPv6SourceAddress();
+ const struct in6_addr *getIPv6SourceAddress_aux();
+ u8 *getIPv6SourceAddress_u8();
+
+ /* Info about host proximity */
+ void setDirectlyConnected(bool connected);
+ bool isDirectlyConnected();
+ int isDirectlyConnectedOrUnset();
+
+ /* Next hop */
+ void setNextHop(struct sockaddr_storage *next_hop, size_t next_hop_len);
+ bool getNextHop(struct sockaddr_storage *next_hop, size_t *next_hop_len);
+ int setNextHopMACAddress(const u8 *addy);
+ const u8 *getNextHopMACAddress();
+
+ /* Target MAC address (used when target is directly connected) */
+ int setMACAddress(const u8 *addy);
+ const u8 *getMACAddress();
+ bool determineNextHopMACAddress();
+ bool determineTargetMACAddress();
+
+ /* Source MAC address */
+ int setSrcMACAddress(const u8 *addy);
+ const u8 *getSrcMACAddress();
+
+ /* Network device used for this target */
+ void setDeviceNames(const char *name, const char *fullname);
+ const char *getDeviceName();
+ const char *getDeviceFullName();
+ int setDeviceType(devtype type);
+ devtype getDeviceType();
+
+ /* Resolved Host name */
+ const char *getResolvedHostName();
+ void setResolvedHostName(char *name);
+
+ /* Target name as supplied from the command line */
+ const char *getSuppliedHostName();
+ int setSuppliedHostName(char *name);
+ int setNamedHost(bool val);
+ bool isNamedHost();
+
+ /* Printable strings */
+ const char *getTargetIPstr();
+ const char *getNameAndIP(char *buf, size_t buflen);
+ const char *getNameAndIP();
+ const char *getSourceIPStr();
+ const char *getSpoofedSourceIPStr();
+ const char *getNextHopIPStr();
+ const char *getMACStr(u8 *mac);
+ const char *getTargetMACStr();
+ const char *getSourceMACStr();
+ const char *getNextHopMACStr();
+
+ /* ICMP related methods */
+ u16 obtainICMPSequence();
+ u16 getICMPIdentifier();
+
+ /* Misc */
+ void printTargetDetails();
+
+
+
+/* STATS***********************************************************************/
+#define MAX_SENTPROBEINFO_ENTRIES 10
+
+typedef struct pkt_stat{
+ int proto;
+ u16 tcp_port;
+ u16 icmp_id;
+ u16 icmp_seq;
+ struct timeval sent;
+ struct timeval recv;
+}pktstat_t;
+
+
+pktstat_t sentprobes[MAX_SENTPROBEINFO_ENTRIES];
+int current_stat;
+int total_stats;
+
+unsigned long int sent_total;
+unsigned long int recv_total;
+unsigned long int max_rtt;
+bool max_rtt_set;
+unsigned long int min_rtt;
+bool min_rtt_set;
+unsigned long int avg_rtt;
+bool avg_rtt_set;
+
+
+int setProbeRecvTCP(u16 sport, u16 dport);
+int setProbeSentTCP(u16 sport, u16 dport);
+int setProbeRecvUDP(u16 sport, u16 dport);
+int setProbeSentUDP(u16 sport, u16 dport);
+int setProbeSentICMP(u16 id, u16 seq);
+int setProbeRecvICMP(u16 id, u16 seq);
+int setProbeSentARP();
+int setProbeRecvARP();
+int updateRTTs(unsigned long int diff);
+int printStats();
+void printCounts();
+void printRTTs();
+/* STATS***********************************************************************/
+
+};
+
+#endif /* NPINGTARGET_H */
diff --git a/nping/NpingTargets.cc b/nping/NpingTargets.cc
new file mode 100644
index 0000000..20c1ea3
--- /dev/null
+++ b/nping/NpingTargets.cc
@@ -0,0 +1,387 @@
+
+/***************************************************************************
+ * NpingTargets.cc -- Class that handles target spec parsing and allows to *
+ * obtain the different targets that need to be ping-ed. *
+ * *
+ ***********************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 "NpingOps.h"
+#include "global_structures.h"
+#include "output.h"
+#include "nbase.h"
+#include "utils.h"
+#include "NpingTargets.h"
+#include "common.h"
+#include "common_modified.h"
+
+extern NpingOps o;
+#ifdef WIN32
+/* from libdnet's intf-win32.c */
+extern "C" int g_has_npcap_loopback;
+#endif
+
+NpingTargets::NpingTargets(){
+ memset(specs, 0, 1024*(sizeof(char *)) );
+ memset(skipspec, 0, 1024*(sizeof(bool)) );
+ speccount=0;
+ current_spec=-1;
+ finished=false;
+ targets_fetched=0;
+ current_target=0;
+ ready=false;
+} /* End of NpingTargets constructor */
+
+
+NpingTargets::~NpingTargets(){
+} /* End of NpingTargets destructor */
+
+
+/** Adds a target specification to an internal array of specs */
+int NpingTargets::addSpec(char *spec){
+ if(spec==NULL)
+ return OP_FAILURE;
+ if( this->speccount >= 1024 )
+ return OP_FAILURE;
+ specs[ this->speccount ] = spec;
+ this->speccount++;
+ return OP_SUCCESS;
+} /* End of NpingTargets */
+
+
+/** Returns next target */
+int NpingTargets::getNextTargetAddressAndName(struct sockaddr_storage *t, size_t *tlen, char *hname, size_t hlen){
+ struct sockaddr_storage next;
+ memset(&next, 0, sizeof(struct sockaddr_storage));
+ size_t nextlen=0;
+ int r=0;
+ int family= (o.getIPVersion()==IP_VERSION_6) ? AF_INET6 : AF_INET;
+
+ if( t==NULL || tlen==NULL )
+ nping_fatal(QT_3,"getNextTarget(): NULL values supplied.");
+
+ /* Return failure if there are no specs or we noticed that we were finished in
+ * a previous call. */
+ if ( this->speccount <= 0 || finished==true )
+ return OP_FAILURE;
+
+ /* If this is the first time we call to this method */
+ if (this->current_spec == -1 ){
+
+ current_spec=0;
+ if ( !skipspec[ current_spec ] ){
+ if ( current_group.parse_expr( specs[ current_spec ], family ) != 0 ){
+ skipspec[ current_spec ]=true; /* Make sure we skip it next time */
+ return OP_FAILURE;
+
+ }
+ }
+ else{ /* We are skipping current target, return the next one */
+ return this->getNextTargetAddressAndName(t, tlen, hname, hlen);
+ }
+ }
+
+ r=current_group.get_next_host(&next, &nextlen);
+
+ if ( r!=0 ){ /* We exhausted current group */
+ /* Is there any other group? */
+ if (++current_spec == speccount){ /* No more specs to parse */
+ finished=true;
+ return OP_FAILURE;
+ }
+ /* Ok, there are more groups, so let's go with the next spec */
+ if ( !skipspec[ current_spec ] ){
+ if ( current_group.parse_expr( specs[ current_spec ], family ) != 0 ){
+ skipspec[ current_spec ]=true;
+ return this->getNextTargetAddressAndName(t, tlen, hname, hlen);
+
+ }
+ }
+ else{ /* We are skipping current target, return the next one */
+ return this->getNextTargetAddressAndName(t, tlen, hname, hlen);
+ }
+
+ r=current_group.get_next_host(&next, &nextlen);
+
+ if (r != 0)
+ nping_fatal(QT_3,"BUG: TargetGroups are supposed to contain at least one IP! ");
+ }
+ memcpy( t, &next, sizeof( struct sockaddr_storage ) );
+ /* If current spec is a named host (not a range), store name in supplied buff */
+ if(current_group.get_namedhost()){
+ if( hname!=NULL && hlen>0 )
+ strncpy(hname, specs[ current_spec ], hlen);
+ }else{ /* If current spec is not a named host, insert NULL in the first position */
+ if( hname!=NULL && hlen>0 )
+ hname[0]='\0';
+ }
+ *tlen=nextlen;
+ targets_fetched++;
+ return OP_SUCCESS;
+ } /* End of getNextTarget() */
+
+
+int NpingTargets::getNextIPv4Address(u32 *addr){
+ struct sockaddr_storage t;
+ size_t tlen;
+ char buff[257];
+ memset(buff, 0, 257);
+ if( addr == NULL )
+ nping_fatal(QT_3, "getNextIPv4Address(): NULL value supplied. ");
+ if ( this->getNextTargetAddressAndName(&t, &tlen, buff, 256) != OP_SUCCESS )
+ return OP_FAILURE;
+ struct sockaddr_in *p=( struct sockaddr_in *)&t;
+ if(p->sin_family!=AF_INET)
+ nping_fatal(QT_3, "getNextIPv4Address(): Trying to obtain an IPv4 address from an IPv6 target.");
+ *addr = p->sin_addr.s_addr;
+ return OP_SUCCESS;
+} /* End of getNextIPv4Address() */
+
+
+int NpingTargets::rewindSpecs(){
+ current_spec=-1;
+ finished=false;
+ targets_fetched=0;
+ return OP_SUCCESS;
+} /* End of rewind() */
+
+
+unsigned long int NpingTargets::getTargetsFetched(){
+ return this->Targets.size();
+} /* getTargetsFetched() */
+
+
+int NpingTargets::getTargetSpecCount(){
+ return this->speccount;
+} /* End of getTargetSpecCount() */
+
+
+/** This method should be called when all the target specs have been entered
+ * using addSpec(). What it does is to create a NpingTarget objects for
+ * each IP address extracted from the specs. Objects are stored in an internal
+ * vector. */
+int NpingTargets::processSpecs(){
+ char buff[MAX_NPING_HOSTNAME_LEN+1];
+ struct sockaddr_storage ss;
+ size_t slen=0;
+ bool result=false;
+ struct route_nfo rnfo;
+
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+ memset(buff, 0, MAX_NPING_HOSTNAME_LEN+1);
+
+ /* Rewind spec index just in case someone has been playing around with it */
+ o.targets.rewindSpecs();
+
+ /* Get next host IP address and, if it is a named host, its hostname */
+ while ( this->getNextTargetAddressAndName(&ss, &slen, buff, MAX_NPING_HOSTNAME_LEN) == OP_SUCCESS ){
+ NpingTarget *mytarget = new NpingTarget();
+ mytarget->setTargetSockAddr(&ss, slen);
+ if( buff[0]=='\0')
+ mytarget->setNamedHost(false);
+ else{
+ mytarget->setSuppliedHostName(buff);
+ mytarget->setNamedHost(true);
+ }
+
+ /* For the moment, we only run this code if we are not dealing with IPv6 */
+ if( !o.ipv6() ){
+
+ /* Get all the information needed to send packets to this target.
+ * (Only in case we are not in unprivileged modes) */
+ if(o.getMode()!=TCP_CONNECT && o.getMode()!=UDP_UNPRIV){
+ result=route_dst( &ss, &rnfo, o.getDevice(), NULL );
+ if(result==false){
+ nping_warning(QT_2, "Failed to determine route to host %s. Skipping it...", mytarget->getTargetIPstr() );
+ delete mytarget;
+ continue;
+ }
+#ifdef WIN32
+ if (g_has_npcap_loopback == 0 && rnfo.ii.device_type == devt_loopback){
+ nping_warning(QT_2, "Skipping %s because Windows does not allow localhost scans (try --unprivileged).", mytarget->getTargetIPstr() );
+ delete mytarget;
+ continue;
+ }
+#endif
+ /* Determine next hop */
+ if( rnfo.direct_connect ){
+ mytarget->setDirectlyConnected(true);
+ mytarget->setNextHop(&ss, slen);
+ }
+ else{
+ mytarget->setDirectlyConnected(false);
+ mytarget->setNextHop(&rnfo.nexthop, sizeof(struct sockaddr_storage));
+ }
+ /* Source IP address that we should use when targeting this host */
+ mytarget->setSourceSockAddr(&rnfo.srcaddr, sizeof(struct sockaddr_storage));
+
+ /* If user requested to spoof IP source address, set it */
+ if( o.spoofSource() ){
+ mytarget->setSpoofedSourceSockAddr( o.getSourceSockAddr(), sizeof(struct sockaddr_storage));
+ }
+
+ /* Network interface */
+ mytarget->setDeviceNames( rnfo.ii.devname, rnfo.ii.devfullname );
+ mytarget->setDeviceType( rnfo.ii.device_type );
+
+ /* Set source MAC address */
+ mytarget->setSrcMACAddress( rnfo.ii.mac );
+
+ if( rnfo.ii.device_up == false )
+ nping_warning(QT_2, "Device used for target host %s seems to be down.", mytarget->getTargetIPstr());
+
+ /* Determine next hop MAC address and target MAC address */
+ if( o.sendEth() ){
+#ifdef WIN32
+ if (g_has_npcap_loopback == 1 && rnfo.ii.device_type == devt_loopback) {
+ mytarget->setNextHopMACAddress(mytarget->getSrcMACAddress());
+ }
+ else {
+#endif
+ mytarget->determineNextHopMACAddress();
+ mytarget->determineTargetMACAddress(); /* Sets Target MAC only if is directly connected to us */
+#ifdef WIN32
+ }
+#endif
+ }
+ /* If we are in debug mode print target details */
+ if(o.getDebugging() >= DBG_3)
+ mytarget->printTargetDetails();
+ }
+ }else{
+ struct sockaddr_storage ss;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ss;
+ memset(&ss, 0, sizeof(sockaddr_storage));
+ s6->sin6_family=AF_INET6;
+ mytarget->setSourceSockAddr(&ss, sizeof(struct sockaddr_storage));
+ }
+
+ /* Insert current target into targets array */
+ this->Targets.push_back(mytarget);
+ }
+
+ /* getNextTarget() checks this to ensure user has previously called processSpecs() */
+ this->ready=true;
+ o.targets.rewind();
+ return OP_SUCCESS;
+} /* End of getTargetSpecCount() */
+
+
+
+NpingTarget *NpingTargets::getNextTarget(){
+ /* When !ready it means that processSpecs() has not been called yet. This
+ * happens when user hits CTRL-C early. */
+ if( this->ready == false )
+ return NULL;
+ /* Did we reach the end of the vector in the last call? */
+ if( this->current_target >= this->Targets.size() )
+ return NULL;
+ nping_print(DBG_4, "Next target returned by getNextTarget(): Targets[%lu/%lu] --> %s \n", this->current_target, (unsigned long) this->Targets.size(), this->Targets.at(this->current_target)->getTargetIPstr() );
+ return this->Targets.at( this->current_target++ );
+} /* End of getNextTarget() */
+
+
+int NpingTargets::rewind(){
+ current_target=0;
+ return OP_SUCCESS;
+} /* End of rewind() */
+
+/* Frees all of the Targets. Returns the number of freed targets. The number
+ * return should match value returned by getTargetsFetched(). */
+unsigned long int NpingTargets::freeTargets(){
+ unsigned long int cnt=0;
+ while(!this->Targets.empty()) {
+ this->currenths = Targets.back();
+ delete currenths;
+ Targets.pop_back();
+ cnt++;
+ }
+ return cnt;
+} /* End of freeTargets() */
+
+
+NpingTarget *NpingTargets::findTarget(struct sockaddr_storage *tt){
+ size_t i=0;
+ struct sockaddr_storage ss;
+ size_t ss_len;
+ struct sockaddr_in *s_ip4=(struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *s_ip6=(struct sockaddr_in6 *)&ss;
+ struct sockaddr_in *t_ip4=(struct sockaddr_in *)tt;
+ struct sockaddr_in6 *t_ip6=(struct sockaddr_in6 *)tt;
+
+ if (tt==NULL)
+ return NULL;
+
+ for(i=0; i<this->Targets.size(); i++){
+ this->Targets[i]->getTargetSockAddr(&ss, &ss_len);
+ /* Are we are dealing with IPv4 addresses? */
+ if( s_ip4->sin_family==AF_INET && t_ip4->sin_family==AF_INET){
+
+ if( !memcmp(&(s_ip4->sin_addr), &(t_ip4->sin_addr), sizeof(struct in_addr)) )
+ return this->Targets[i];
+ }
+ /* Are they IPv6 addresses? */
+ else if( s_ip6->sin6_family==AF_INET6 && t_ip6->sin6_family==AF_INET6 ){
+ if( !memcmp(&(s_ip6->sin6_addr), &(t_ip6->sin6_addr), sizeof(struct in6_addr)) )
+ return this->Targets[i];
+ }
+ /* Unknown type of address, skipping... */
+ else{
+ continue;
+ }
+ }
+ return NULL;
+} /* End of findTarget() */
diff --git a/nping/NpingTargets.h b/nping/NpingTargets.h
new file mode 100644
index 0000000..7ab9341
--- /dev/null
+++ b/nping/NpingTargets.h
@@ -0,0 +1,111 @@
+
+/***************************************************************************
+ * NpingTargets.cc -- Class that handles target spec parsing and allows to *
+ * obtain the different targets that need to be ping-ed. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef NPINGTARGETS_H
+#define NPINGTARGETS_H
+
+
+/* TODO: Needs to be changed if we move TargetGroup to another source file */
+#include "common_modified.h"
+#include "NpingTarget.h"
+#include <vector>
+
+#define MAX_NPING_HOSTNAME_LEN 512 /**< Max length for named hosts */
+
+class NpingTargets {
+
+ private:
+
+ char *specs[1024];
+ bool skipspec[1024];
+ int speccount;
+ int current_spec;
+ bool lastwaslastingroup;
+ bool finished;
+ TargetGroup current_group;
+
+ bool ready;
+ unsigned long int targets_fetched;
+ unsigned long int current_target;
+
+ public:
+
+ NpingTargets();
+ ~NpingTargets();
+ int addSpec(char *spec);
+ int getNextTargetSockAddr(struct sockaddr_storage *t, size_t *tlen);
+ NpingTarget *getNextTarget();
+ int rewind();
+ int getNextTargetAddressAndName(struct sockaddr_storage *t, size_t *tlen, char *hname, size_t hlen);
+ int getNextIPv4Address(u32 *addr);
+ int rewindSpecs();
+ unsigned long int getTargetsFetched();
+ int getTargetSpecCount();
+ int processSpecs();
+ unsigned long int freeTargets();
+ NpingTarget *findTarget(struct sockaddr_storage *tt);
+
+ /* TODO: Make private */
+ NpingTarget *currenths;
+ std::vector<NpingTarget *> Targets;
+
+}; /* End of class NpingTargets */
+
+#endif
diff --git a/nping/ProbeMode.cc b/nping/ProbeMode.cc
new file mode 100644
index 0000000..b8887a8
--- /dev/null
+++ b/nping/ProbeMode.cc
@@ -0,0 +1,2342 @@
+
+/***************************************************************************
+ * ProbeMode.cc -- Probe Mode is nping's default working mode. Basically, *
+ * it involves sending the packets that the user requested at regular *
+ * intervals and capturing responses from the wire. *
+ * *
+ ***********************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 "ProbeMode.h"
+#include <vector>
+#include "nsock.h"
+#include "output.h"
+#include "NpingOps.h"
+
+#ifdef WIN32
+/* Need DnetName2PcapName */
+#include "libnetutil/netutil.h"
+#endif
+
+extern NpingOps o;
+
+
+ProbeMode::ProbeMode() {
+ this->reset();
+} /* End of ProbeMode constructor */
+
+
+ProbeMode::~ProbeMode() {
+} /* End of ProbeMode destructor */
+
+
+/** Sets every attribute to its default value- */
+void ProbeMode::reset() {
+ this->nsock_init=false;
+} /* End of reset() */
+
+
+/** Sets up the internal nsock pool and the nsock trace level */
+int ProbeMode::init_nsock(){
+ struct timeval now;
+ if( nsock_init==false ){
+ /* Create a new nsock pool */
+ if ((nsp = nsock_pool_new(NULL)) == NULL)
+ nping_fatal(QT_3, "Failed to create new pool. QUITTING.\n");
+ nsock_pool_set_device(nsp, o.getDevice());
+
+ /* Allow broadcast addresses */
+ nsock_pool_set_broadcast(nsp, 1);
+
+ /* Set nsock trace level */
+ gettimeofday(&now, NULL);
+ if( o.getDebugging() == DBG_5)
+ nsock_set_loglevel(NSOCK_LOG_INFO);
+ else if( o.getDebugging() > DBG_5 )
+ nsock_set_loglevel(NSOCK_LOG_DBG_ALL);
+ /* Flag it as already initialized so we don't do it again */
+ nsock_init=true;
+ }
+ return OP_SUCCESS;
+} /* End of init() */
+
+
+/** Cleans up the internal nsock pool and any other internal data that
+ * needs to be taken care of before destroying the object. */
+int ProbeMode::cleanup(){
+ nsock_pool_delete(this->nsp);
+ return OP_SUCCESS;
+} /* End of cleanup() */
+
+
+/** Returns the internal nsock pool.
+ * @warning the caller must ensure that init_nsock() has been called before
+ * calling this method; otherwise, it will fatal() */
+nsock_pool ProbeMode::getNsockPool(){
+ if( this->nsock_init==false)
+ nping_fatal(QT_3, "getNsockPool() called before init_nsock(). Please report a bug.");
+ return this->nsp;
+} /* End of getNsockPool() */
+
+
+/** This function handles regular ping mode. Basically it handles both
+ * unprivileged modes (TCP_CONNECT and UDP_UNPRIV) and raw packet modes
+ * (TCP, UDP, ICMP, ARP). This function is where the loops that iterate
+ * over target hosts and target ports are located. It uses the nsock lib
+ * to schedule transmissions. The actual Tx and Rx is done inside the nsock
+ * event handlers, here we just schedule them, take care of the timers,
+ * set up pcap and the bpf filter, etc. */
+int ProbeMode::start(){
+ int rc;
+ int p=0, pc=-1; /**< Indexes for ports count */
+ u32 c=0; /**< Index for packet count */
+ u32 zero=0; /**< Empty payload */
+ u8 pktinfobuffer[512+1]; /**< Used in ippackethdrinfo() calls */
+ u8 pkt[MAX_IP_PACKET_LEN]; /**< Holds packets returned by fillpacket */
+ int pktLen=0; /**< Length of current packet */
+ NpingTarget *target=NULL; /**< Current target */
+ u16 *targetPorts=NULL; /**< Pointer to array of target ports */
+ int numTargetPorts=0; /**< Total number of target ports */
+ u16 currentPort=0; /**< Current target port */
+ char *filterstring; /**< Stores BFP filter spec string */
+ int rawipsd=-1; /**< Descriptor for raw IP socket */
+ enum nsock_loopstatus loopret; /**< Stores nsock_loop returned status */
+ nsock_iod pcap_nsi; /**< Stores Pcap IOD */
+ u32 packetno=0; /**< Total packet count */
+ bool first_time=true; /**< First time we run the loop? */
+ char pcapdev[128]; /**< Device name passed to pcap_open_live */
+ #define MX_PKT 1024 /**< Packet structs we keep simultaneously*/
+ sendpkt_t pkts2send[MX_PKT]; /**< We have a race condition here but the
+ * problem is not trivial to solve because we cannot create a sendpkt_t
+ * struct for every probe we send. That could be alright in most cases but
+ * not when targeting large networks or when doing flooding. The problem here
+ * is that we may need access to specific sendpkt_t vars inside the nsock
+ * event handlers but as some operations are asynchronous, we may exhaust
+ * the current array of sendpkt_t structs and overwrite some positions
+ * that contain data that has not been read yet. Anyway, this bug should not
+ * happen when using Nping for normal purposes. As long as you don't choose
+ * to ping a 100 million hosts with an inter-probe delay of 1ms, you should be
+ * fine. For more info, write to luis.mgarc@gmail.com or post a message to the
+ * nmap-dev mailing list. */
+
+
+ /* Some safe zero initializations */
+ memset(pktinfobuffer, 0, 512+1);
+ memset(pkt, 0, MAX_IP_PACKET_LEN);
+ memset(&pcap_nsi, 0, sizeof(pcap_nsi));
+ memset(pkts2send, 0, MX_PKT * sizeof(sendpkt_t));
+
+ /* Get array of target ports */
+ targetPorts = o.getTargetPorts( &numTargetPorts );
+
+ /* Set up nsock */
+ this->init_nsock();
+
+ switch( o.getMode() ){
+
+ /***************************************************************************/
+ /** TCP CONNECT MODE **/
+ /***************************************************************************/
+ case TCP_CONNECT:
+ o.stats.startClocks();
+ for( c=0; c < o.getPacketCount(); c++){ /* Do requested times */
+ o.targets.rewind();
+ for (p=0; p < numTargetPorts; p++){ /* Iterate through all destination ports */
+ o.targets.rewind();
+ while( (target=o.targets.getNextTarget()) != NULL ){
+
+ /* Store relevant info so we can pass it to the handler */
+ pc=(pc+1)%MX_PKT;
+ pkts2send[pc].type=PKT_TYPE_TCP_CONNECT;
+ pkts2send[pc].target=target;
+ pkts2send[pc].dstport=targetPorts[p];
+
+ /* Schedule a TCP Connect attempt */
+ if( first_time ){
+ nsock_timer_create(nsp, tcpconnect_event_handler, 1, &pkts2send[pc]);
+ first_time=false;
+ loopret=nsock_loop(nsp, 2);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }else{
+ nsock_timer_create(nsp, tcpconnect_event_handler, o.getDelay()+1, &pkts2send[pc]);
+ loopret=nsock_loop(nsp, o.getDelay()+1);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }
+ }
+ }
+ }
+ o.stats.stopTxClock();
+ /* If there are some events pending, we'll wait for DEFAULT_WAIT_AFTER_PROBES ms,
+ * otherwise nsock_loop() will return immediately */
+ loopret=nsock_loop(nsp, DEFAULT_WAIT_AFTER_PROBES);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ o.stats.stopRxClock();
+ return OP_SUCCESS;
+ break; /* case TCP_CONNECT */
+
+
+ /***************************************************************************/
+ /** UDP UNPRIVILEGED MODE **/
+ /***************************************************************************/
+ case UDP_UNPRIV:
+ o.stats.startClocks();
+ for( c=0; c < o.getPacketCount(); c++){ /* Do requested times */
+ o.targets.rewind();
+ for (p=0; p < numTargetPorts; p++){ /* Iterate through all destination ports */
+ o.targets.rewind();
+ while( (target=o.targets.getNextTarget()) != NULL ){
+
+ /* Store relevant info so we can pass it to the handler */
+ pc=(pc+1)%MX_PKT;
+ pkts2send[pc].type=PKT_TYPE_UDP_NORMAL;
+ pkts2send[pc].target=target;
+ pkts2send[pc].dstport=targetPorts[p];
+
+ if(o.issetPayloadBuffer() ){
+ pkts2send[pc].pkt=o.getPayloadBuffer();
+ pkts2send[pc].pktLen=o.getPayloadLen();
+ }else{
+ /* We send 4 bytes of value 0 because nsock does not let us send empty UDP packets */
+ pkts2send[pc].pkt=(u8*)&zero;
+ pkts2send[pc].pktLen=4;
+ /* TODO: At some point we want to support David's custom UDP payloads here*/
+ }
+
+ /* Schedule a UDP attempt */
+ if( first_time ){
+ nsock_timer_create(nsp, udpunpriv_event_handler, 1, &pkts2send[pc]);
+ first_time=false;
+ loopret=nsock_loop(nsp, 2);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }else{
+ nsock_timer_create(nsp, udpunpriv_event_handler, o.getDelay(), &pkts2send[pc]);
+ loopret=nsock_loop(nsp, o.getDelay());
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }
+ }
+ }
+ }
+ o.stats.stopTxClock();
+ /* If there are some events pending, we'll wait for DEFAULT_WAIT_AFTER_PROBES ms,
+ * otherwise nsock_loop() will return immediately */
+ if(!o.disablePacketCapture()){
+ loopret=nsock_loop(nsp, DEFAULT_WAIT_AFTER_PROBES);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }
+ o.stats.stopRxClock();
+ return OP_SUCCESS;
+ break; /* case UDP_UNPRIV */
+
+
+
+ /***************************************************************************/
+ /** TCP/UDP/ICMP/ARP MODES **/
+ /***************************************************************************/
+ case TCP:
+ case UDP:
+ case ICMP:
+ case ARP:
+
+ if( o.getMode()!=ARP && o.sendEth()==false ){
+ /* Get socket descriptor. No need for it in ARP since we send at eth level */
+ if ((rawipsd = obtainRawSocket()) < 0 )
+ nping_fatal(QT_3,"Couldn't acquire raw socket. Are you root?");
+ }
+
+ /* Check if we have enough information to get the party started */
+ if((o.getMode()==TCP || o.getMode()==UDP) && targetPorts==NULL)
+ nping_fatal(QT_3, "normalProbeMode(): NpingOps does not contain correct target ports\n");
+
+ /* Set up libpcap */
+ if(!o.disablePacketCapture()){
+ /* Create new IOD for pcap */
+ if ((pcap_nsi = nsock_iod_new(nsp, NULL)) == NULL)
+ nping_fatal(QT_3, "Failed to create new nsock_iod. QUITTING.\n");
+
+ /* Open pcap */
+ filterstring=getBPFFilterString();
+ nping_print(DBG_2,"Opening pcap device %s", o.getDevice() );
+ #ifdef WIN32
+ /* Nping normally uses device names obtained through dnet for interfaces,
+ * but Pcap has its own naming system. So the conversion is done here */
+ if (!DnetName2PcapName(o.getDevice(), pcapdev, sizeof(pcapdev))) {
+ /* Oh crap -- couldn't find the corresponding dev apparently.
+ * Let's just go with what we have then ... */
+ Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
+ }
+ #else
+ Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
+ #endif
+
+ rc = nsock_pcap_open(nsp, pcap_nsi, pcapdev, 8192,
+ (o.spoofSource()) ? 1 : 0, filterstring);
+ if (rc)
+ nping_fatal(QT_3, "Error opening capture device %s\n", o.getDevice());
+ nping_print(DBG_2,"Pcap device %s open successfully", o.getDevice());
+ }
+
+ /* Ready? Go! */
+ o.stats.startClocks();
+
+ switch ( o.getMode() ){
+
+ /* Modes in which we need to iterate over target ports */
+ case TCP:
+ case UDP:
+ /* Do user requested times */
+ for( c=0; c < o.getPacketCount(); c++){
+ o.targets.rewind();
+ o.setCurrentRound( o.issetTTL() ? ((c%(256-o.getTTL()))+o.getTTL()) : ((c%255)+1 ) ); /* Used in traceroute mode */
+ /* Iterate through all destination ports */
+ for (p=0; p < numTargetPorts; p++){
+ o.targets.rewind();
+ /* Iterate trough all target IP addresses */
+ while( (target=o.targets.getNextTarget()) != NULL ){
+
+ currentPort=targetPorts[p];
+
+ if ( fillPacket( target, currentPort, pkt, MAX_IP_PACKET_LEN, &pktLen, rawipsd ) != OP_SUCCESS ){
+ nping_fatal(QT_3, "normalProbeMode(): Error in packet creation");
+ }
+ /* Safe checks */
+ if (pktLen <=0)
+ nping_fatal(QT_3, "normalProbeMode(): Invalid packet returned by fillPacket() ");
+
+ /* Store relevant info so we can pass it to the handler */
+ pc=(pc+1)%MX_PKT;
+ pkts2send[pc].type = (o.getMode()==TCP) ? PKT_TYPE_TCP_RAW : PKT_TYPE_UDP_RAW;
+ pkts2send[pc].pkt = pkt;
+ pkts2send[pc].target=target;
+ pkts2send[pc].pktLen = pktLen;
+ pkts2send[pc].rawfd = rawipsd;
+ pkts2send[pc].seq = ++packetno;
+ pkts2send[pc].dstport=currentPort;
+
+ /* Tell nsock we expect one reply. Actually we schedule 2 pcap events just in case
+ * we get more than one response. */
+ if(!o.disablePacketCapture()){
+ nsock_pcap_read_packet(nsp, pcap_nsi, nping_event_handler, o.getDelay(), NULL);
+ nsock_pcap_read_packet(nsp, pcap_nsi, nping_event_handler, o.getDelay(), NULL);
+ }
+
+ /* Let nsock handle probe transmission and inter-probe delay */
+ if( first_time ){
+ nsock_timer_create(nsp, nping_event_handler, 1, &pkts2send[pc]);
+ first_time=false;
+ loopret=nsock_loop(nsp, 2);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }else{
+ nsock_timer_create(nsp, nping_event_handler, o.getDelay(), &pkts2send[pc]);
+ loopret=nsock_loop(nsp, o.getDelay()+1);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }
+ }
+ }
+ }
+ break; /* Nested case UDP/TCP */
+
+
+ /* Modes in which we DO NOT need to iterate over target ports */
+ case ICMP:
+ case ARP:
+ /* Do user requested times */
+ for( c=0; c < o.getPacketCount(); c++){
+ o.targets.rewind();
+ o.setCurrentRound( o.issetTTL() ? ((c%(256-o.getTTL()))+o.getTTL()) : ((c%255)+1 ) ); /* Used in traceroute mode */
+ /* Iterate trough all target IP addresses */
+ while( (target=o.targets.getNextTarget()) != NULL ){
+
+ if ( fillPacket( target, 0, pkt, MAX_IP_PACKET_LEN, &pktLen, rawipsd ) != OP_SUCCESS )
+ nping_fatal(QT_3, "normalProbeMode(): Error in packet creation");
+ if (pktLen <=0)
+ nping_fatal(QT_3, "normalProbeMode(): Error packet returned by createPacket() ");
+
+ /* Store relevant info so we can pass it to the handler */
+ pc=(pc+1)%MX_PKT;
+ pkts2send[pc].type = (o.getMode()==ICMP) ? PKT_TYPE_ICMP_RAW : PKT_TYPE_ARP_RAW;
+ pkts2send[pc].pkt = pkt;
+ pkts2send[pc].pktLen = pktLen;
+ pkts2send[pc].target=target;
+ pkts2send[pc].rawfd = rawipsd;
+ pkts2send[pc].seq = ++packetno;
+
+ /* Tell nsock we expect one reply. Actually we schedule 2 pcap events just in case
+ * we get more than one response. */
+ if(!o.disablePacketCapture()){
+ nsock_pcap_read_packet(nsp, pcap_nsi, nping_event_handler, o.getDelay(), NULL);
+ nsock_pcap_read_packet(nsp, pcap_nsi, nping_event_handler, o.getDelay(), NULL);
+ }
+
+ /* Let nsock handle probe transmission and inter-probe delay */
+ if( first_time ){
+ nsock_timer_create(nsp, nping_event_handler, 1, &pkts2send[pc]);
+ first_time=false;
+ loopret=nsock_loop(nsp, 2);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }else{
+ nsock_timer_create(nsp, nping_event_handler, o.getDelay(), &pkts2send[pc]);
+ loopret=nsock_loop(nsp, o.getDelay()+1);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ }
+ }
+ }
+ break; /* Nested case ICMP/ARP */
+
+ } /* End of nested switch */
+
+ o.stats.stopTxClock();
+ if(!o.disablePacketCapture()){
+ nsock_pcap_read_packet(nsp, pcap_nsi, nping_event_handler, DEFAULT_WAIT_AFTER_PROBES, NULL);
+ loopret=nsock_loop(nsp, DEFAULT_WAIT_AFTER_PROBES);
+ if (loopret == NSOCK_LOOP_ERROR)
+ nping_fatal(QT_3, "Unexpected nsock_loop error.\n");
+ o.stats.stopRxClock();
+ }
+ /* Close opened descriptors */
+ if(rawipsd>=0)
+ close(rawipsd);
+ break; /* case TCP || case UDP || case ICMP || case ARP */
+
+ default:
+ nping_fatal(QT_3, "normalProbeMode(): Wrong mode. Please report this bug.");
+ break;
+ } /* End of main switch */
+ return OP_SUCCESS;
+} /* End of start() */
+
+
+
+
+
+/** Creates buffer suitable to be passed to a sendto() call. The buffer
+ * represents a raw network packet. The specific protocols are obtained from
+ * the information stored in "NpingOps o" object. For example, if o.getMode()
+ * returns TCP and o.ipv4() is true, then an IPv4-TCP packet will be generated
+ * and stored in the supplied buffer.
+ * @param target should contain a valid target with an IP that matches
+ * NpingOps::af() returned value.
+ * @param port is the destination port number. It is only necessary in TCP and
+ * UDP modes. You can safely pass a dummy value in ICMP and ARP modes.
+ * @param buff should point to a buffer where the generated packet can be stored.
+ * @param bufflen should be the size of the supplied buffer. This function will
+ * never write more than "bufflen" bytes to the buffer.
+ * @param filledlen will be set to the amount of bytes actually written into
+ * the buffer.
+ * @param rawfd is the raw socket descriptor that will be used to send the
+ * packet. This is only necessary when sending IPv6 packets at raw TCP level
+ * because some IPv6 options like hop limit are tuned using calls to
+ * setsockopt() */
+int ProbeMode::fillPacket(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd){
+ EthernetHeader e; /* Used when sending at raw Ethernet level. */
+ u8 *pnt=buff; /* Aux pointer to keep track of user supplied "buff". */
+ int pntlen=bufflen; /* Aux counter to store how many bytes we have left. */
+ int final_len=0;
+ bool eth_included=false;
+
+ if(target==NULL || buff==NULL || bufflen<=0 || filledlen==NULL)
+ return OP_FAILURE;
+ else
+ nping_print(DBG_4, "fillPacket(target=%p, port=%d, buff=%p, bufflen=%d, filledlen=%p rawfd=%d)", target, port, buff, bufflen, filledlen, rawfd);
+
+/* If o.sendEth() is true that means we need to send packets at raw Ethernet
+ * level (we are probably running on windows or user requested that explicitly.
+ * Ethernet frames that carry ARP packets have special requirements (e.g. some
+ * of them are sent to a FF:FF:FF:FF:FF:FF broadcast address). That's why we
+ * don't create Ethernet frames here when ARP is used. Function fillPacketARP()
+ * takes care of that already. */
+ if(o.sendEth() && o.getMode()!=ARP){
+ e.setNextElement( NULL );
+ if( buff==NULL || filledlen==NULL)
+ nping_fatal(QT_3,"fillPacketARP(): NULL pointer supplied.");
+ /* Source MAC Address */
+ if( o.issetSourceMAC() )
+ e.setSrcMAC( o.getSourceMAC() );
+ else{
+ if( target->getSrcMACAddress() )
+ e.setSrcMAC( (u8 *)target->getSrcMACAddress() );
+ else
+ nping_fatal(QT_3, "fillPacket(): Cannot determine Source MAC address.");
+ }
+
+ /* Destination MAC Address */
+ if( o.issetDestMAC() )
+ e.setDstMAC( o.getDestMAC() );
+ else{
+ if( target->getNextHopMACAddress() )
+ e.setDstMAC( (u8 *)target->getNextHopMACAddress() );
+ else
+ nping_fatal(QT_3, "fillPacket(): Cannot determine Next Hop MAC address.");
+ }
+
+ /* Ethertype value */
+ if( o.issetEtherType() )
+ e.setEtherType( o.getEtherType() );
+ else{
+ if( o.getIPVersion() == IP_VERSION_4 )
+ e.setEtherType(ETHTYPE_IPV4);
+ else if ( o.getIPVersion() == IP_VERSION_6 )
+ e.setEtherType(ETHTYPE_IPV6);
+ else
+ nping_fatal(QT_3, "Bug in fillPacket() and NpingOps::ipversion");
+ }
+
+ /* Write the ethernet header to the beginning of the original buffer */
+ e.dumpToBinaryBuffer(buff, 14);
+
+ /* Move this pointer so the fillPacketXXXX() functions start from the
+ * right byte. */
+ pnt+=14;
+ pntlen-=14;
+ eth_included=true;
+ }
+
+ switch( o.getMode() ){
+ case TCP:
+ fillPacketTCP(target, port, pnt, pntlen, &final_len, rawfd);
+ break;
+ case UDP:
+ fillPacketUDP(target, port, pnt, pntlen, &final_len, rawfd);
+ break;
+ case ICMP:
+ fillPacketICMP(target, pnt, pntlen, &final_len, rawfd);
+ break;
+ case ARP: /* ARP builds its own Ethernet header inside fillPacketARP() */
+ fillPacketARP(target, pnt, pntlen, &final_len, rawfd);
+ break;
+ default:
+ nping_fatal(QT_3, "Bug in fillPacket() and NpingOps::getMode()");
+ break;
+ }
+
+ if( eth_included )
+ final_len+=14;
+ *filledlen=final_len;
+ return OP_SUCCESS;
+} /* End of createPacket() */
+
+
+
+/** Fills an IPv4Header object with information obtained from the NpingOps
+ * class.
+ * @return OP_SUCCESS on success and fatal()s in case of failure. */
+int ProbeMode::createIPv4(IPv4Header *i, PacketElement *next_element, const char *next_proto, NpingTarget *target){
+ if( i==NULL || next_proto==NULL || target==NULL)
+ nping_fatal(QT_3,"createIPv4(): NULL pointer supplied.");
+
+ i->setNextElement( next_element ); /* Set datagram payload */
+ i->setDestinationAddress( target->getIPv4Address() ); /* Destination IP */
+ i->setSourceAddress( o.spoofSource() ? o.getIPv4SourceAddress() : target->getIPv4SourceAddress()); /* Source IP */
+ i->setTOS( o.getTOS() ); /* Type of service */
+ i->setIdentification( o.getIdentification() ); /* Identification */
+ i->setNextProto(next_proto);
+
+ /* Time to live */
+ if(o.issetTraceroute()){
+ i->setTTL( o.getCurrentRound() );
+ }else{
+ i->setTTL( o.getTTL() );
+ }
+
+ /* Flags */
+ if( o.issetMF() && o.getMF() == true )
+ i->setMF();
+ if( o.issetDF() && o.getDF() == true )
+ i->setDF();
+ if( o.issetRF() && o.getRF() == true )
+ i->setRF();
+
+ /* IP Options */
+ if( o.issetIPOptions() == true )
+ i->setOpts( o.getIPOptions() );
+
+ i->setTotalLength();
+
+ /* Checksum */
+ if( o.getBadsumIP() == true )
+ i->setSumRandom();
+ else
+ i->setSum();
+
+ return OP_SUCCESS;
+} /* End of createIPv4() */
+
+
+
+
+
+/** Fills an IPv6Header object with information obtained from the NpingOps
+ * class.
+ * @return OP_SUCCESS on success and fatal()s in case of failure. */
+int ProbeMode::createIPv6(IPv6Header *i, PacketElement *next_element, const char *next_proto, NpingTarget *target){
+ if( i==NULL || next_proto==NULL || target==NULL)
+ nping_fatal(QT_3,"createIPv6(): NULL pointer supplied.");
+
+ /* Set datagram payload */
+ i->setNextElement( next_element );
+
+ i->setVersion();
+ i->setTrafficClass( o.getTrafficClass() );
+ i->setFlowLabel( o.getFlowLabel() );
+ i->setNextHeader(next_proto);
+ i->setPayloadLength();
+ i->setDestinationAddress( target->getIPv6Address_u8() );
+
+ /* Hop Limit */
+ if ( o.issetTraceroute() ){
+ i->setHopLimit( o.getCurrentRound() );
+ }else{
+ i->setHopLimit( o.getHopLimit() );
+ }
+
+ /* Source IP */
+ if( o.issetIPv6SourceAddress() ){
+ i->setSourceAddress( o.getIPv6SourceAddress() );
+ }else{
+ if ( target->getIPv6SourceAddress_u8() != NULL )
+ i->setSourceAddress( target->getIPv6SourceAddress_u8() );
+ else
+ nping_fatal(QT_3, "createIPv6(): Cannot determine Source IPv6 Address");
+ }
+ return OP_SUCCESS;
+} /* End of createIPv6() */
+
+
+/** This function is a bit tricky. The thing is that some engineer had
+ * the brilliant idea to remove IP_HDRINCL support in IPv6. As a result, it's
+ * a big pain in the ass to create raw IPv6 headers because we can only do it
+ * if we are sending packets at raw Ethernet level. So if we want our own IPv6
+ * header (for source IP spoofing, etc) we have to do things like determine
+ * source and dest MAC addresses (this is even more complicated in IPv6 than
+ * in IPv4 because we don't have ARP anymore, we have to use something new, the
+ * NDP, Neighbor Discovery Protocol.)
+ * So the thing is that, if the user does not want to play with the IPv6 header,
+ * why bother with all that link layer work? So what we do is create raw
+ * transport layer packets and then send them through a raw IPv6 socket. The
+ * socket will encapsulate our packets into a nice clean IPv6 header
+ * automatically so we don't have to worry about low level details anymore.
+ *
+ * So this function basically takes a raw IPv6 socket descriptor and then tries
+ * to set some basic parameters (like Hop Limit) using setsockopt() calls.
+ * It always returns OP_SUCCESS. However, if errors are found, they are printed
+ * (QT_2 level) using nping_warning();
+ * */
+int ProbeMode::doIPv6ThroughSocket(int rawfd){
+
+ /* Hop Limit */
+ int hoplimit=0;
+ if( o.issetHopLimit() )
+ hoplimit= o.getHopLimit();
+ else if ( o.issetTraceroute() ){
+ hoplimit= (o.getCurrentRound()<255)? o.getCurrentRound() : (o.getCurrentRound()%255)+1;
+ }else{
+ hoplimit=DEFAULT_IPv6_TTL;
+ }
+ if( setsockopt(rawfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&hoplimit, sizeof(hoplimit)) != 0 )
+ nping_warning(QT_2, "doIPv6ThroughSocket(): setsockopt() for Unicast Hop Limit on IPv6 socket failed");
+ if( setsockopt(rawfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&hoplimit, sizeof(hoplimit)) != 0 )
+ nping_warning(QT_2, "doIPv6ThroughSocket(): setsockopt() for Multicast Hop Limit on IPv6 socket failed");
+
+#ifdef IPV6_CHECKSUM /* This is not available in when compiling with MinGW */
+ /* Transport layer checksum */
+ /* This is totally crazy. We have to tell the kernel EXPLICITLY that we
+ * want it to set the TCP/UDP checksum for us. Why the hell is this the
+ * default behavior if it's so incredibly difficult to get the IPv6 source
+ * address?
+ * Additionally, we have to be very careful not to set this option when
+ * dealing with ICMPv6 because in that case the kernel computes the
+ * checksum automatically and Nping can actually crash if we've set
+ * this option manually, can you believe it? */
+ if( o.getMode()==TCP || o.getMode()==UDP){
+ /* We don't request valid TCP checksums if the user requested bogus sums */
+ if( o.getBadsum()==false ){
+ int offset = 16;
+ if( setsockopt (rawfd, IPPROTO_IPV6, IPV6_CHECKSUM, (char *)&offset, sizeof(offset)) != 0 )
+ nping_warning(QT_2, "doIPv6ThroughSocket(): failed to set IPV6_CHECKSUM option on IPv6 socket. ");
+ }
+ }
+#endif
+
+ /* Bind IPv6 socket to a specific network interface */
+ if ( o.issetDevice() ) {
+ /* It seems that SO_BINDTODEVICE only work on Linux */
+ #ifdef LINUX
+ if (setsockopt(rawfd, SOL_SOCKET, SO_BINDTODEVICE, o.getDevice(), strlen(o.getDevice())+1) == -1) {
+ nping_warning(QT_2, "Error binding IPv6 socket to device %s", o.getDevice() );
+ }
+ #endif
+ }
+
+ return OP_SUCCESS;
+
+} /* End of doIPv6ThroughSocket() */
+
+
+
+
+
+/** This function handles TCP packet creation. However, the final packet that
+ * it produces also includes an IP header.
+ * There is one exception. When we are sending IPv6 packet at raw TCP level,
+ * the returned packet does not contain an IPv6 header but the supplied
+ * rawfd socket descriptor is ready to go because some options have been
+ * set on it by doIPv6ThroughSocket(). */
+int ProbeMode::fillPacketTCP(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd){
+
+ IPv4Header i;
+ IPv6Header i6;
+ TCPHeader t;
+ RawData p;
+ struct in_addr tip, sip;
+
+ if( buff==NULL || filledlen==NULL || target==NULL)
+ nping_fatal(QT_3,"fillPacketTCP(): NULL pointer supplied.");
+
+ /* Add Payload if necessary */
+ if ( o.issetPayloadType() ){
+ switch( o.getPayloadType() ){
+ case PL_RAND: case PL_HEX: case PL_STRING:
+ p.store(o.getPayloadBuffer(), o.getPayloadLen());
+ break;
+
+ case PL_FILE:
+ break;
+
+ default:
+ break;
+ }
+ t.setNextElement( &p );
+ }
+
+ /* Craft TCP Header */
+ t.setSourcePort( o.getSourcePort() );
+ t.setDestinationPort( port );
+ t.setSeq( o.getTCPSequence() );
+ t.setAck( o.getTCPAck() );
+ t.setOffset();
+ t.setWindow( o.getTCPWindow() );
+ t.setUrgPointer(0);
+ t.setFlags(0);
+
+ /* Flags */
+ if( o.getFlagTCP(FLAG_CWR) == 1 ) t.setCWR();
+ if( o.getFlagTCP(FLAG_ECN) == 1 ) t.setECN();
+ if( o.getFlagTCP(FLAG_URG) == 1 ) t.setURG();
+ if( o.getFlagTCP(FLAG_ACK) == 1 ) t.setACK();
+ if( o.getFlagTCP(FLAG_PSH) == 1 ) t.setPSH();
+ if( o.getFlagTCP(FLAG_RST) == 1 ) t.setRST();
+ if( o.getFlagTCP(FLAG_SYN) == 1 ) t.setSYN();
+ if( o.getFlagTCP(FLAG_FIN) == 1 ) t.setFIN();
+
+
+ /* Now let's encapsulate the TCP packet into an IP packet */
+ switch( o.getIPVersion() ){
+
+ case IP_VERSION_4:
+
+ /* Fill the IPv4Header object with the info from NpingOps */
+ createIPv4(&i, &t, "TCP", target);
+
+ tip=target->getIPv4Address();
+ i.getSourceAddress(&sip);
+ if( o.getBadsum() == true ){
+ t.setSumRandom(tip, sip);
+ }else{
+ t.setSum();
+ }
+ /* Store result in user supplied buffer */
+ *filledlen = i.dumpToBinaryBuffer(buff, bufflen);
+
+ break;
+
+ case IP_VERSION_6:
+ if( o.sendEth() ){
+ /* Fill the IPv6Header object with the info from NpingOps */
+ createIPv6(&i6, &t, "TCP", target);
+
+ if( o.getBadsum() == true )
+ t.setSumRandom();
+ else{
+ *filledlen = i6.dumpToBinaryBuffer(buff, bufflen);
+ ip6_checksum(buff, *filledlen); /* Provided by dnet */
+ return OP_SUCCESS;
+ }
+
+ /* Store result in user supplied buffer */
+ *filledlen = i6.dumpToBinaryBuffer(buff, bufflen);
+ }else{
+ doIPv6ThroughSocket(rawfd);
+
+ /* Set some bogus checksum */
+ if( o.getBadsum()==true )
+ t.setSumRandom();
+ /* Set checksum to zero and pray for the kernel to set it to
+ * the right value. Brothers and sisters:
+ *
+ * Our TCP/IP stack, Who is in the kernel,
+ * Holy is Your Name;
+ * Your kingdom come,
+ * Your will be done,
+ * on userland as it is in kernel space.
+ * Give us this day our TCP checksum,
+ * and forgive us for our raw sockets,
+ * as we forgive you for your kernel panics;
+ * and lead us not into /dev/null,
+ * but deliver our packet to the next hop. Amen.
+ * */
+ else
+ t.setSum(0);
+
+ /* Since we cannot include our own header like we do in IPv4, the
+ * buffer we return is the TCP one. */
+ *filledlen = t.dumpToBinaryBuffer(buff, bufflen);
+ }
+ break;
+
+ default:
+ nping_fatal(QT_3, "fillPacketTCP(): Wrong IP version in NpingOps\n");
+ break;
+
+ }
+
+ return OP_SUCCESS;
+
+} /* End of fillPacketTCP() */
+
+
+
+
+
+
+/** This function handles UDP packet creation. However, the final packet that
+ * it produces also includes an IP header.
+ * There is one exception. When we are sending IPv6 packet at raw TCP level,
+ * the returned packet does not contain an IPv6 header but the supplied
+ * rawfd socket descriptor is ready to go because some options have been
+ * set on it by doIPv6ThroughSocket(). */
+int ProbeMode::fillPacketUDP(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd){
+
+ IPv4Header i;
+ IPv6Header i6;
+ UDPHeader u;
+ RawData p;
+ struct in_addr tip, sip;
+
+ if( buff==NULL || filledlen==NULL || target==NULL)
+ nping_fatal(QT_3,"fillPacketUDP(): NULL pointer supplied.");
+
+
+ /* Add Payload if necessary */
+ if ( o.issetPayloadType() ){
+ switch( o.getPayloadType() ){
+ case PL_RAND: case PL_HEX: case PL_STRING:
+ p.store(o.getPayloadBuffer(), o.getPayloadLen());
+ break;
+
+ case PL_FILE:
+ break;
+
+ default:
+ break;
+ }
+ u.setNextElement( &p );
+ }
+
+ /* Craft UDP Header */
+ u.setSourcePort( o.getSourcePort() );
+ u.setDestinationPort( port );
+ u.setTotalLength();
+
+ /* Now let's encapsulate the TCP packet into an IP packet */
+ switch( o.getIPVersion() ){
+
+ case IP_VERSION_4:
+
+ /* Fill the IPv4Header object with the info from NpingOps */
+ createIPv4(&i, &u, "UDP", target);
+
+ /* Set checksum */
+ tip=target->getIPv4Address();
+ i.getSourceAddress(&sip);
+ if( o.getBadsum() == true ){
+ u.setSumRandom(tip, sip);
+ }else{
+ u.setSum();
+ }
+ /* Store result in user supplied buffer */
+ *filledlen = i.dumpToBinaryBuffer(buff, bufflen);
+
+ break;
+
+ case IP_VERSION_6:
+
+ if( o.sendEth() ){
+ /* Fill the IPv6Header object with the info from NpingOps */
+ createIPv6(&i6, &u, "UDP", target);
+
+ if( o.getBadsum() == true ){
+ u.setSumRandom();
+ /* Store result in user supplied buffer */
+ *filledlen = i6.dumpToBinaryBuffer(buff, bufflen);
+ }
+ else{
+ *filledlen = i6.dumpToBinaryBuffer(buff, bufflen);
+ ip6_checksum(buff, *filledlen); /* Provided by dnet */
+ return OP_SUCCESS;
+ }
+ }else{
+ doIPv6ThroughSocket(rawfd);
+
+ /* Set some bogus checksum */
+ if( o.getBadsum()==true )
+ u.setSumRandom();
+ /* Set checksum to zero and assume the kernel is gonna set the
+ * right value. If it doesn't, it's not that important since
+ * UDP checksum is optional and can safely be set to zero */
+ else
+ u.setSum(0);
+
+ /* Since we cannot include our own header like we do in IPv4, the
+ * buffer we return is the UDP one. */
+ *filledlen = u.dumpToBinaryBuffer(buff, bufflen);
+ }
+ break;
+
+ default:
+ nping_fatal(QT_3, "fillPacketUDP(): Wrong IP version in NpingOps\n");
+ break;
+
+ }
+
+ return OP_SUCCESS;
+
+} /* End of fillPacketUDP() */
+
+
+
+/** This function handles ICMP packet creation. However, the final packet that
+ * it produces also includes an IP header.
+ *
+ * Currently this function only supports ICMPv4 packet creation. ICMPv6 will
+ * be added in the future.*/
+int ProbeMode::fillPacketICMP(NpingTarget *target, u8 *buff, int bufflen, int *filledlen, int rawfd){
+ IPv4Header i;
+ IPv6Header i6;
+ ICMPv4Header c4;
+ ICMPv6Header c6;
+ RawData p;
+
+ if( buff==NULL || filledlen==NULL || target==NULL)
+ nping_fatal(QT_3,"fillPacketICMP(): NULL pointer supplied.");
+ nping_print(DBG_4, "fillPacketICMP(target=%p, buff=%p, bufflen=%d, filledlen=%p)", target, buff, bufflen, filledlen);
+
+ /* Add Payload if necessary */
+ if ( o.issetPayloadType() ){
+ switch( o.getPayloadType() ){
+ case PL_RAND: case PL_HEX: case PL_STRING:
+ p.store(o.getPayloadBuffer(), o.getPayloadLen());
+ break;
+
+ case PL_FILE:
+ break;
+
+ default:
+ break;
+ }
+ c4.setNextElement( &p );
+ c6.setNextElement( &p );
+ }
+
+ if( o.ipv4() ){
+
+ c4.setType( o.getICMPType() );
+ c4.setCode( o.getICMPCode() );
+
+ /* Lets go for type specific options */
+ switch ( c4.getType() ){
+
+ case ICMP_REDIRECT:
+ c4.setGatewayAddress( o.getICMPRedirectAddress() );
+ break;
+
+ case ICMP_ECHO:
+ case ICMP_ECHOREPLY:
+ if( o.issetICMPIdentifier() )
+ c4.setIdentifier( o.getICMPIdentifier() );
+ else
+ c4.setIdentifier( target->getICMPIdentifier() );
+
+ if( o.issetICMPSequence() )
+ c4.setSequence( o.getICMPSequence() );
+ else
+ c4.setSequence( target->obtainICMPSequence() );
+ break;
+
+ case ICMP_ROUTERADVERT:
+ c4.setAddrEntrySize( 2 );
+ c4.setLifetime( o.getICMPRouterAdvLifetime() );
+
+ if( o.issetICMPAdvertEntry() )
+ for (int z=0; z<o.getICMPAdvertEntryCount(); z++){
+ struct in_addr entryaddr;
+ u32 entrypref;
+ o.getICMPAdvertEntry(z, &entryaddr, &entrypref );
+ c4.addRouterAdvEntry(entryaddr, entrypref);
+ }
+ break;
+
+ case ICMP_PARAMPROB:
+ c4.setParameterPointer( o.getICMPParamProblemPointer() );
+ break;
+
+ case ICMP_TSTAMP:
+ case ICMP_TSTAMPREPLY:
+ if( o.issetICMPIdentifier() )
+ c4.setIdentifier( o.getICMPIdentifier() );
+ else
+ c4.setIdentifier( target->getICMPIdentifier() );
+
+ if( o.issetICMPSequence() )
+ c4.setSequence( o.getICMPSequence() );
+ else
+ c4.setSequence( target->obtainICMPSequence() );
+ c4.setOriginateTimestamp( o.getICMPOriginateTimestamp() );
+ c4.setReceiveTimestamp( o.getICMPReceiveTimestamp() );
+ c4.setTransmitTimestamp( o.getICMPTransmitTimestamp() );
+ break;
+
+ case ICMP_INFO:
+ case ICMP_INFOREPLY:
+ case ICMP_MASK:
+ case ICMP_MASKREPLY:
+ case ICMP_TRACEROUTE:
+ case ICMP_UNREACH:
+ case ICMP_SOURCEQUENCH:
+ case ICMP_ROUTERSOLICIT:
+ case ICMP_TIMXCEED:
+ break;
+
+ default:
+ /* TODO: What do we do here if user specified a non standard type? */
+ break;
+
+ }
+ /* Compute checksum */
+ c4.setSum(); /* TODO: Do we want to implement --badsum-icmp? */
+
+ /* Fill the IPv4Header object with the info from NpingOps */
+ createIPv4(&i, &c4, "ICMP", target);
+
+ /* Store result in user supplied buffer */
+ *filledlen = i.dumpToBinaryBuffer(buff, bufflen);
+
+ }else{
+
+ c6.setType( o.getICMPType() );
+ c6.setCode( o.getICMPCode() );
+
+ switch( c6.getType() ){
+
+ case ICMPv6_ECHO:
+ case ICMPv6_ECHOREPLY:
+ c6.setIdentifier(o.issetICMPIdentifier() ? o.getICMPIdentifier() : target->getICMPIdentifier());
+ c6.setSequence(o.issetICMPSequence() ? o.getICMPSequence() : target->obtainICMPSequence());
+ break;
+
+ case ICMPv6_UNREACH:
+ case ICMPv6_PKTTOOBIG:
+ case ICMPv6_TIMXCEED:
+ case ICMPv6_PARAMPROB:
+
+ case ICMPv6_ROUTERSOLICIT:
+ case ICMPv6_ROUTERADVERT:
+ case ICMPv6_NGHBRSOLICIT:
+ case ICMPv6_NGHBRADVERT:
+ case ICMPv6_REDIRECT:
+ case ICMPv6_RTRRENUM:
+ default:
+ break;
+ }
+
+ /* Fill the IPv4Header object with the info from NpingOps */
+ createIPv6(&i6, &c6, "ICMPv6", target);
+
+ /* Compute checksum */
+ c6.setSum();
+
+ /* Store result in user supplied buffer */
+ *filledlen = i6.dumpToBinaryBuffer(buff, bufflen);
+
+ }
+
+ return OP_SUCCESS;
+
+} /* End of fillPacketICMP() */
+
+
+
+
+/** This function handles ARP packet creation. However, the final packet that
+ * it produces also includes an Ethernet header. */
+int ProbeMode::fillPacketARP(NpingTarget *target, u8 *buff, int bufflen, int *filledlen, int rawfd){
+
+ EthernetHeader e;
+ ARPHeader a;
+
+ u8 bcastmac[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+ u8 nullmac[6]={0x00,0x00,0x00,0x00,0x00,0x00};
+
+ if(target==NULL || buff==NULL || filledlen==NULL)
+ nping_fatal(QT_3,"fillPacketARP(): NULL pointer supplied.");
+
+ nping_print(DBG_4, "fillPacketARP(target=%p, buff=%p, bufflen=%d, filledlen=%p)", target, buff, bufflen, filledlen);
+
+ /* Source MAC Address */
+ if( o.issetSourceMAC() )
+ e.setSrcMAC( o.getSourceMAC() );
+ else if( target->getSrcMACAddress()!=NULL )
+ e.setSrcMAC(target->getSrcMACAddress());
+ else
+ e.setSrcMAC( nullmac ); /* Defaults to 00:00:00:00:00:00 */
+
+ /* Destination MAC Address */
+ if( o.issetDestMAC() )
+ e.setDstMAC( o.getDestMAC() );
+ else
+ e.setDstMAC( bcastmac ); /* Defaults to FF:FF:FF:FF:FF:FF */
+
+ /* Ethertype value */
+ if( o.issetEtherType() )
+ e.setEtherType( o.getEtherType() );
+ else
+ e.setEtherType(ETHTYPE_ARP);
+
+ /* Link Ethernet header to ARP packet. */
+ e.setNextElement(&a);
+
+ /* Hardware type */
+ if( o.issetARPHardwareType() )
+ a.setHardwareType( o.getARPHardwareType() );
+ else
+ a.setHardwareType();
+
+ /* Protocol type */
+ if( o.issetARPProtocolType() )
+ a.setProtocolType( o.getARPProtocolType() );
+ else
+ a.setProtocolType();
+
+ /* Length of HW Address */
+ if( o.issetARPHwAddrLen() )
+ a.setHwAddrLen( o.getARPHwAddrLen() );
+ else
+ a.setHwAddrLen(); /* Defaults to length of a MAC address */
+
+ /* Length of Protocol Address */
+ if( o.issetARPProtoAddrLen() )
+ a.setProtoAddrLen( o.getARPProtoAddrLen() );
+ else
+ a.setProtoAddrLen(); /* Defaults to length of IPv4 */
+
+ /* ARP Operation code. */
+ a.setOpCode( o.getARPOpCode() );
+
+ /* Sender HW Address */
+ if( o.issetARPSenderHwAddr() )
+ a.setSenderMAC( o.getARPSenderHwAddr() );
+ else
+ a.setSenderMAC( e.getSrcMAC() ); /* Get Ethernet's source MAC */
+
+ /* Sender Protocol Address */
+ if( o.issetARPSenderProtoAddr() )
+ a.setSenderIP( o.getARPSenderProtoAddr() );
+ else if ( o.issetIPv4SourceAddress() )
+ a.setSenderIP( o.getIPv4SourceAddress() );
+ else
+ a.setSenderIP( target->getIPv4SourceAddress() );
+
+ /* Target HW Address */
+ if( o.issetARPTargetProtoAddr() )
+ a.setTargetIP( o.getARPTargetProtoAddr() );
+ else
+ a.setTargetIP( target->getIPv4Address() );
+
+ /* Target Protocol Address */
+ if( o.issetARPTargetHwAddr() )
+ a.setTargetMAC( o.getARPTargetHwAddr() );
+ else
+ a.setTargetMAC( nullmac ); /* Get Ethernet's target MAC */
+
+ /* Store result in user supplied buffer */
+ *filledlen = e.dumpToBinaryBuffer(buff, bufflen);
+
+ return OP_SUCCESS;
+}
+
+
+
+/** This function creates a BPF filter specification, suitable to be passed to
+ * pcap_compile() or nsock_pcap_open(). It reads info from "NpingOps o" and
+ * creates the right BPF filter for the current operation mode. However, if
+ * user has supplied a custom BPF filter through option --bpf-filter, the
+ * same string stored in o.getBPFFilterSpec() is returned (so the caller
+ * should not even bother to check o.issetBPFFilterSpec() because that check
+ * is done here already.
+ * @warning Returned pointer is a statically allocated buffer that subsequent
+ * calls will overwrite. */
+char *ProbeMode::getBPFFilterString(){
+
+ char ipstring[128];
+ static char filterstring[1024];
+ char *buffer=filterstring;
+ u8 icmp_send_type=0;
+ u8 icmp_recv_type=0;
+ u16 arp_send_type=0;
+ u16 arp_recv_type=0;
+ bool skip_icmp_matching=false;
+ bool skip_arp_matching=false;
+ bool src_equals_target=false;
+ NpingTarget *t=NULL;
+ struct sockaddr_storage srcss;
+ struct sockaddr_in *s4=(struct sockaddr_in *)&srcss;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&srcss;
+ struct sockaddr_storage dstss;
+ struct sockaddr_in *d4=(struct sockaddr_in *)&dstss;
+ struct sockaddr_in6 *d6=(struct sockaddr_in6 *)&dstss;
+ size_t dstlen, srclen;
+ memset(&srcss, 0, sizeof(struct sockaddr_storage));
+ memset(&dstss, 0, sizeof(struct sockaddr_storage));
+ memset(buffer, 0, 1024);
+ memset(ipstring, 0, 128);
+
+ /* If user supplied a BPF from the cmd line, use it */
+ if( o.issetBPFFilterSpec() ){
+ buffer=o.getBPFFilterSpec();
+ /* We copy it to our internal static buffer just in case... */
+ if(buffer!=NULL)
+ strncpy(filterstring, buffer, sizeof(filterstring)-1);
+ else
+ strncpy(filterstring, "", 2);
+ nping_print(DBG_1, "BPF-filter: %s", filterstring);
+ return filterstring;
+ }
+
+ /* For the server in Echo mode we need a special filter */
+ if( o.getRole()==ROLE_SERVER ){
+ /* Capture all IP packets but the ones that belong to the side-channel */
+ sprintf(filterstring, "ip and ( not (tcp and (dst port %d or src port %d) ) )", o.getEchoPort(), o.getEchoPort() );
+ nping_print(DBG_1, "BPF-filter: %s", filterstring);
+ return filterstring;
+ }
+
+ /* Obtain source IP address */
+ if( o.spoofSource() )
+ memcpy( &srcss, o.getSourceSockAddr(), sizeof(struct sockaddr_storage) );
+ else if( (t=o.targets.getNextTarget())!= NULL ){
+ t->getSourceSockAddr(&srcss, &srclen);
+ }else{
+ /* This should never happen but if for some reason we cannot obtain
+ * the target, set localhost address. */
+ if ( o.ipv6() ){
+ s4->sin_family=AF_INET;
+ inet_pton(AF_INET, "::1", &s6->sin6_addr);
+ }else{
+ s4->sin_family=AF_INET;
+ inet_pton(AF_INET, "127.0.0.1", &s4->sin_addr);
+ }
+ nping_print(DBG_2, "Couldn't determine source address. Using address %s in BFP filter", IPtoa(&srcss) );
+ }
+ o.targets.rewind();
+
+ /* Obtain the first target address */
+ if(t!=NULL)
+ t->getTargetSockAddr(&dstss, &dstlen);
+
+ /* Determine if source address and target address are the same. This is a
+ * special case that occurs when nping-ing localhost */
+ if(s6->sin6_family==AF_INET6){
+ if(memcmp(&s6->sin6_addr, &d6->sin6_addr, sizeof(d6->sin6_addr))==0)
+ src_equals_target=true;
+ }else if( s4->sin_family == AF_INET ){
+ if(s4->sin_addr.s_addr == d4->sin_addr.s_addr)
+ src_equals_target=true;
+ }
+
+ /* Convert src address to an ascii string so it can be copied to the BPF string */
+ if(s6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &s6->sin6_addr, ipstring, sizeof(ipstring));
+ }else if( s4->sin_family == AF_INET ) {
+ inet_ntop(AF_INET, &s4->sin_addr, ipstring, sizeof(ipstring));
+ }else{
+ nping_warning(QT_2, "Warning: Wrong address family (%d) in getBPFFilterString(). Please report a bug", srcss.ss_family);
+ sprintf(ipstring,"127.0.0.1");
+ }
+
+ /* Tell the filter that we only want incoming packets, destined to our source IP */
+ if(o.getMode()!=ARP){
+ if(src_equals_target)
+ Snprintf(buffer, 1024, "(src host %s and dst host %s) and (", ipstring, ipstring);
+ else
+ Snprintf(buffer, 1024, "(not src host %s and dst host %s) and (", ipstring, ipstring);
+ buffer=filterstring+strlen(filterstring);
+ }
+
+ /* Time for protocol specific constraints */
+ switch( o.getMode() ){
+ case TCP: /* Restrict to packets targeting our TCP source port */
+ Snprintf(buffer, 1024-strlen(filterstring), "(tcp and dst port %d) ", o.getSourcePort());
+ break;
+
+ case UDP: /* Restrict to packets targeting our UDP source port */
+ Snprintf(buffer, 1024-strlen(filterstring), "(udp and dst port %d) ", o.getSourcePort());
+ break;
+
+ case ICMP: /* Restrict to packets that are replies to our ICMP packets */
+ icmp_send_type= o.issetICMPType() ? o.getICMPType() : DEFAULT_ICMP_TYPE;
+ switch( icmp_send_type ){
+ case ICMP_TSTAMP:
+ icmp_recv_type=ICMP_TSTAMPREPLY;
+ break;
+ case ICMP_TSTAMPREPLY: /* If we are sending replies we probably want to see */
+ icmp_recv_type=ICMP_TSTAMP; /* the requests that are being put into the network */
+ break;
+ case ICMP_INFO:
+ icmp_recv_type=ICMP_INFOREPLY;
+ break;
+ case ICMP_INFOREPLY:
+ icmp_recv_type=ICMP_INFO;
+ break;
+ case ICMP_MASK:
+ icmp_recv_type=ICMP_MASKREPLY;
+ break;
+ case ICMP_MASKREPLY:
+ icmp_recv_type=ICMP_MASK;
+ break;
+ case ICMP_ECHO:
+ icmp_recv_type=ICMP_ECHOREPLY;
+ break;
+ case ICMP_ECHOREPLY:
+ icmp_recv_type=ICMP_ECHO;
+ break;
+
+ /* These don't generate any response so we behave different */
+ case ICMP_UNREACH:
+ case ICMP_SOURCEQUENCH:
+ case ICMP_REDIRECT:
+ case ICMP_ROUTERADVERT:
+ case ICMP_ROUTERSOLICIT:
+ case ICMP_TIMXCEED:
+ case ICMP_PARAMPROB:
+ case ICMP_TRACEROUTE:
+ default:
+ skip_icmp_matching=true;
+ break;
+ }
+ /* We have an specific ICMP type to look for */
+ if(!skip_icmp_matching){
+ Snprintf(buffer, 1024-strlen(filterstring), "(icmp and icmp[icmptype] = %d) ", icmp_recv_type);
+ }else{
+ /* If we are sending messages that don't generate responses, receive anything but the type we send.
+ * This conflicts in some cases with the conditions added at the end of this functions where we
+ * allow ICMP error messages to be received. However, this is not a problem since we are already
+ * filtering out our own outgoing packets and the packets that are not for us. */
+ Snprintf(buffer, 1024-strlen(filterstring), "(icmp and icmp[icmptype] != %d) ", icmp_send_type);
+ }
+ break;
+
+ case ARP:
+ arp_send_type= o.issetARPOpCode() ? o.getARPOpCode() : DEFAULT_ARP_OP;
+ switch(arp_send_type){
+ case OP_ARP_REQUEST:
+ arp_recv_type=OP_ARP_REPLY;
+ break;
+ case OP_ARP_REPLY: /* If we are sending replies we probably want to see */
+ arp_recv_type=OP_ARP_REQUEST; /* the requests that are being put into the network */
+ break;
+ case OP_RARP_REQUEST:
+ arp_recv_type=OP_RARP_REPLY;
+ break;
+ case OP_RARP_REPLY:
+ arp_recv_type=OP_RARP_REQUEST;
+ break;
+ case OP_DRARP_REQUEST:
+ arp_recv_type=OP_DRARP_REPLY;
+ break;
+ case OP_DRARP_REPLY:
+ arp_recv_type=OP_DRARP_REQUEST;
+ break;
+ case OP_DRARP_ERROR:
+ arp_recv_type=OP_DRARP_REQUEST;
+ break;
+ case OP_INARP_REQUEST:
+ arp_recv_type=OP_INARP_REPLY;
+ break;
+ case OP_INARP_REPLY:
+ arp_recv_type=OP_INARP_REQUEST;
+ break;
+ default:
+ skip_arp_matching=true;
+ break;
+ }
+ if(!skip_arp_matching){
+ /* If we are doing DRARP we also want to receive DRARP errors */
+ if(arp_send_type==OP_DRARP_REQUEST || arp_send_type==OP_DRARP_REPLY)
+ Snprintf(buffer, 1024-strlen(filterstring), "arp and arp[6]==0x00 and (arp[7]==0x%02X or arp[7]==0x%02X)", (u8)arp_recv_type, (u8)OP_DRARP_ERROR);
+ else
+ Snprintf(buffer, 1024-strlen(filterstring), "arp and arp[6]==0x00 and arp[7]==0x%02X", (u8)arp_recv_type);
+ }else{
+ /* If we are sending things like ATMARP's ARP_NAK, we just skip the type we send and receive all others */
+ Snprintf(buffer, 1024-strlen(filterstring), "arp and arp[6]==0x00 and arp[7]!=0x%02X", (u8)arp_send_type);
+ }
+ break;
+ }
+
+ /* We also want to get all ICMP error messages */
+ if(o.getMode()!=ARP){
+ buffer=filterstring+strlen(filterstring);
+ Snprintf(buffer, 1024-strlen(filterstring), "or (icmp and (icmp[icmptype] = %d or icmp[icmptype] = %d or icmp[icmptype] = %d or icmp[icmptype] = %d or icmp[icmptype] = %d)) )" ,
+ ICMP_UNREACH, ICMP_SOURCEQUENCH, ICMP_REDIRECT, ICMP_TIMXCEED, ICMP_PARAMPROB);
+ }
+ nping_print(DBG_1, "BPF-filter: %s", filterstring);
+ return filterstring;
+} /* End of getBPFFilterString() */
+
+
+
+/** Helper to check whether a received ICMP-in-IPv4 packet is related to a probe
+ * we might have sent. Returns non-NULL target pointer if found. Otherwise
+ * returns NULL. */
+static NpingTarget *is_response_icmp(const unsigned char *packet, unsigned int packetlen) {
+ const void *data;
+ unsigned int datalen;
+ struct abstract_ip_hdr packethdr;
+ NpingTarget *trg;
+
+ /* Parse the outermost IP header (for its source address). */
+ datalen = packetlen;
+ data = ip_get_data(packet, &datalen, &packethdr);
+ if (data == NULL)
+ return NULL;
+
+ trg = o.targets.findTarget(&packethdr.src);
+ if (trg != NULL) {
+ if (packethdr.proto == IPPROTO_ICMP) {
+ struct icmp_hdr *icmp;
+ struct icmp_msg_echo *echo;
+
+ if (datalen < 4)
+ return NULL;
+ icmp = (struct icmp_hdr *) data;
+ /* In case of echo reply, make sure the ICMP ID is the same as we
+ are sending. */
+ if (icmp->icmp_type == ICMP_ECHOREPLY) {
+ u16 expected_id;
+
+ if (o.issetICMPIdentifier())
+ expected_id = o.getICMPIdentifier();
+ else
+ expected_id = trg->getICMPIdentifier();
+
+ if (datalen < 8)
+ return NULL;
+ echo = (struct icmp_msg_echo *) ((char *) icmp + 4);
+ if (ntohs(echo->icmp_id) != expected_id)
+ return NULL;
+ }
+ }
+ return trg;
+ }
+
+ /* If that didn't work, check if this is ICMP with an encapsulated IP
+ header. */
+ if (packethdr.proto == IPPROTO_ICMP) {
+ struct ip *ip;
+ unsigned int iplen;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
+
+ if (datalen < 8)
+ return NULL;
+ ip = (struct ip *) ((char *) data + 8);
+ iplen = datalen - 8;
+ /* Make sure there is enough header to have a dest address. */
+ if (iplen < 20)
+ return NULL;
+ if (ip->ip_v != 4)
+ return NULL;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = ip->ip_dst;
+ trg = o.targets.findTarget(&ss);
+
+ return trg;
+ }
+
+ return NULL;
+}
+
+
+/** This function handles nsock events related to raw packet modes
+ * TCP, UDP, ICMP and ARP (TCP_CONNEC and UDP_UNPRIV are handled by their
+ * own even handlers).
+ * Basically the handler receives nsock events and takes the appropriate
+ * action based on event type. This is basically what it does for each event:
+ *
+ * TIMERS: start() schedules probe transmissions through timers.
+ * That's how we manage to send probes at a given rate. When the alarm goes
+ * off, nsock generates a timer event so, in this function, we take the
+ * supplied "mydata" pointer, convert it to a sendpkt_t pointer and, from
+ * the info stored there, we send the packet though a raw socket.
+ *
+ * PCAP READS: start() also schedules pcap read operations so,
+ * whenever pcap has capture a packet, nsock generates a pcap read event so
+ * we just read the capture data, update the statistics and print the packet
+ * to stdout.
+ * */
+void ProbeMode::probe_nping_event_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
+
+ nsock_iod nsi = nse_iod(nse);
+ enum nse_status status = nse_status(nse);
+ enum nse_type type = nse_type(nse);
+ sendpkt_t *mypacket = (sendpkt_t *)mydata;
+ u8 pktinfobuffer[512+1];
+ char *hex=NULL;
+ char final_output[65535];
+ nsock_event_id ev_id;
+ struct timeval *t = (struct timeval *)nsock_gettimeofday();
+ const unsigned char *packet=NULL;
+ const unsigned char *link=NULL;
+ size_t linklen=0;
+ size_t packetlen=0;
+ u16 *ethtype=NULL;
+ u8 buffer[512+1];
+ size_t link_offset=0;
+ static struct timeval pcaptime;
+ static struct timeval prevtime;
+ NpingTarget *trg=NULL;
+ u16 *prt=NULL;
+ u8 proto=0;
+ bool ip=false;
+ memset(final_output, 0, sizeof(final_output));
+
+ nping_print(DBG_4, "nping_event_handler(): Received callback of type %s with status %s",
+ nse_type2str(type), nse_status2str(status));
+
+ if (status == NSE_STATUS_SUCCESS ) {
+
+ switch(type) {
+
+ /* This is actually for our raw packet probe transmissions */
+ case NSE_TYPE_TIMER:
+ if( mypacket!=NULL){
+
+ /* Send the packet */
+ send_packet(mypacket->target, mypacket->rawfd, mypacket->pkt, mypacket->pktLen);
+ o.setLastPacketSentTime(*t);
+
+ /* Print packet contents */
+ if( o.sendEth() )
+ link_offset=14;
+
+ if( mypacket->type==PKT_TYPE_ARP_RAW )
+ getPacketStrInfo("ARP",mypacket->pkt+14, mypacket->pktLen-14, pktinfobuffer, 512);
+ else if ( o.ipv6UsingSocket() ){
+ size_t sslen;
+ struct sockaddr_storage ss_src;
+ struct sockaddr_storage ss_dst;
+ mypacket->target->getSourceSockAddr(&ss_src, &sslen);
+ mypacket->target->getTargetSockAddr(&ss_dst, &sslen);
+ getPacketStrInfo("IPv6_NO_HEADER", mypacket->pkt, mypacket->pktLen, pktinfobuffer, 512, &ss_src, &ss_dst );
+ }
+ else
+ getPacketStrInfo("IP", mypacket->pkt+link_offset, mypacket->pktLen-link_offset, pktinfobuffer, 512);
+
+ o.stats.addSentPacket(mypacket->pktLen);
+ if( o.getMode()==TCP || o.getMode()==UDP){
+ mypacket->target->setProbeSentTCP(0, mypacket->dstport);
+ }else if (o.getMode()==ICMP){
+ mypacket->target->setProbeSentICMP(0,0);
+ }
+ if( o.showSentPackets() ){
+ nping_print(VB_0,"SENT (%.4fs) %s", o.stats.elapsedRuntime(t), pktinfobuffer );
+ if( o.getVerbosity() >= VB_3 )
+ luis_hdump((char*)mypacket->pkt, mypacket->pktLen);
+ }
+ }
+ break;
+
+
+
+ case NSE_TYPE_PCAP_READ:
+
+ /* Read a packet */
+ nse_readpcap(nse, &link, &linklen, &packet, &packetlen, NULL, &pcaptime);
+
+ /* If we are on a Ethernet network, extract the next packet protocol
+ * from the Ethernet frame. */
+ if( nsock_iod_linktype(nsi) == DLT_EN10MB ){
+ ethtype=(u16*)(link+12);
+ *ethtype=ntohs(*ethtype);
+ switch(*ethtype){
+ case ETHTYPE_IPV4:
+ case ETHTYPE_IPV6:
+ ip=true;
+ break;
+ case ETHTYPE_ARP:
+ case ETHTYPE_RARP:
+ ip=false;
+ break;
+ default:
+ nping_warning(QT_1, "RCVD (%.4fs) Unsupported protocol (Ethernet type %02X)", o.stats.elapsedRuntime(t), *ethtype);
+ print_hexdump(VB_3, packet, packetlen);
+ return;
+ break;
+ }
+ /* If link layer is not Ethernet, check if the first bits of the
+ * packets are 4 (IPv4) or 6 (IPv6). This is not exact science but
+ * it should be OK for the moment since we should never get non
+ * IP packets (the BPF filter prevents that) */
+ }else{
+ IPv4Header iphdr;
+ if( iphdr.storeRecvData(packet, packetlen)!=OP_SUCCESS )
+ nping_warning(QT_1, "RCVD (%.4fs) Bogus packet received.", o.stats.elapsedRuntime(t));
+ if( iphdr.getVersion()==4 || iphdr.getVersion()==6){
+ ip=true;
+ }else{
+ nping_warning(QT_1, "RCVD (%.4fs) Unsupported protocol.", o.stats.elapsedRuntime(t));
+ print_hexdump(VB_3, packet, packetlen);
+ return;
+ }
+ }
+
+ /* Packet is IP */
+ if(ip){
+ getPacketStrInfo("IP",(const u8*)packet, packetlen, buffer, 512);
+ proto = getProtoFromIPPacket((u8*)packet, packetlen);
+ if (proto == IPPROTO_UDP || proto == IPPROTO_TCP){
+ /* for UDP/TCP we print out and update the global total straight away
+ since we know that pcap only found packets from connections that we
+ opened */
+ snprintf(final_output, sizeof(final_output), "RCVD (%.4fs) %s\n", o.stats.elapsedRuntime(t), buffer);
+ if( o.getVerbosity() >= VB_3 ){
+ hex=hexdump(packet, packetlen);
+ strncat(final_output, hex, sizeof(final_output)-1);
+ free(hex);
+ }
+ prevtime=pcaptime;
+
+ /* Statistics */
+ o.stats.addRecvPacket(packetlen);
+
+ /* Then we check for a target and a port and do the individual statistics */
+ trg=o.targets.findTarget( getSrcSockAddrFromIPPacket((u8*)packet, packetlen) );
+
+ if(trg != NULL){
+ prt=getSrcPortFromIPPacket((u8*)packet, packetlen);
+ if( prt!=NULL )
+ trg->setProbeRecvTCP(*prt, 0);
+ }
+ }else if (proto==IPPROTO_ICMP || proto==IPPROTO_ICMPV6){
+ /* we look for a target based on first src addr and second the dest addr of
+ the packet header which is returned in the ICMP packet */
+ trg = is_response_icmp(packet, packetlen);
+
+ /* In the case of ICMP we only do any printing and statistics if we
+ found a target - otherwise it could be a packet that is nothing
+ to do with us */
+ if(trg!=NULL){
+ snprintf(final_output, sizeof(final_output), "RCVD (%.4fs) %s\n", o.stats.elapsedRuntime(t), buffer);
+ if( o.getVerbosity() >= VB_3 ){
+ hex=hexdump(packet, packetlen);
+ strncat(final_output, hex, sizeof(final_output)-1);
+ free(hex);
+ }
+ prevtime=pcaptime;
+ o.stats.addRecvPacket(packetlen);
+ trg->setProbeRecvICMP(0, 0);
+ }
+ }
+
+ /* Packet is ARP */
+ }else{
+ getPacketStrInfo("ARP",(const u8*)packet, packetlen, buffer, 512);
+ nping_print(VB_0, "RCVD (%.4fs) %s", o.stats.elapsedRuntime(t), buffer );
+ o.stats.addRecvPacket(packetlen);
+ print_hexdump(VB_3 | NO_NEWLINE, packet, packetlen);
+ /* TODO: find target and call setProbeRecvARP() */
+ }
+
+ if( o.getRole() == ROLE_CLIENT ){
+ int delay=(int)MIN(o.getDelay()*0.33, 333);
+ ev_id=nsock_timer_create(nsp, probe_delayed_output_handler, delay, NULL);
+ o.setDelayedRcvd(final_output, ev_id);
+ }
+ else
+ nping_print(VB_0|NO_NEWLINE, "%s", final_output);
+ break;
+
+ /* In theory we should never get these kind of events in this handler
+ * because no code schedules them */
+ case NSE_TYPE_CONNECT:
+ case NSE_TYPE_CONNECT_SSL:
+ case NSE_TYPE_READ:
+ case NSE_TYPE_WRITE:
+ nping_fatal(QT_3, "Bug in nping_event_handler(). Received %s event.", nse_type2str(type));
+ break;
+
+ default:
+ nping_fatal(QT_3, "nping_event_handler(): Bogus event type.");
+ break;
+
+ } /* switch(type) */
+
+
+ } else if (status == NSE_STATUS_EOF) {
+ nping_print(DBG_4, "nping_event_handler(): Unexpected behaviour: Got EOF. Please report this bug.\n");
+ } else if (status == NSE_STATUS_ERROR) {
+ nping_warning(QT_2, "nping_event_handler(): %s failed: %s", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ nping_print(DBG_4,"nping_event_handler(): %s timeout: %s\n", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_CANCELLED) {
+ nping_warning(QT_2, "nping_event_handler(): %s canceled: %s", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_KILL) {
+ nping_warning(QT_2, "nping_event_handler(): %s killed: %s", nse_type2str(type), strerror(socket_errno()));
+ } else{
+ nping_warning(QT_2, "nping_event_handler(): Unknown status code %d\n", status);
+ }
+ return;
+
+} /* End of nping_event_handler() */
+
+
+/** Prints the supplied string when the nsock timer event goes off. This is used
+ * by the echo client to delay output of received packets for a bit, so we
+ * receive the echoed packet and print it (CAPT) before the RCVD one. */
+void ProbeMode::probe_delayed_output_handler(nsock_pool nsp, nsock_event nse, void *mydata){
+ char *str=NULL;
+ if((str=o.getDelayedRcvd(NULL))!=NULL){
+ printf("%s", str);
+ free(str);
+ }
+ return;
+} /* End of probe_delayed_output_handler() */
+
+
+/* DEFAULT_MAX__DESCRIPTORS. is a hardcoded value for the maximum number of
+ * opened descriptors in the current system. Nping tries to determine that
+ * limit at run time, but sometimes it can't and the limit defaults to
+ * DEFAULT_MAX_DESCRIPTORS. */
+#ifndef MACOSX
+ #define DEFAULT_MAX_DESCRIPTORS 1024
+#else
+ #define DEFAULT_MAX_DESCRIPTORS 256
+#endif
+
+/* When requesting a large number of descriptors from the system (TCP-connect
+ * mode and UDP unprivileged mode), this is the number of descriptors that need
+ * to be reserved for things like stdin, stdout, echo mode sockets, data files,
+ * etc. */
+#define RESERVED_DESCRIPTORS 8
+
+/* Default timeout for UDP socket nsock_read() operations */
+#define DEFAULT_UDP_READ_TIMEOUT_MS 1000
+
+/** This function handles nsock events related to TCP_CONNECT mode
+ * Basically the handler receives nsock events and takes the appropriate
+ * action based on event type. This is basically what it does for each event:
+ *
+ * TIMERS: normalProbeMode() schedules TCP connections through timers, that's
+ * how we manage to start the TCP handshakes at a given rate. When the alarm
+ * goes off, nsock generates a timer event so, in this function, we take the
+ * supplied "mydata" pointer, convert it to a sendpkt_t pointer and, from
+ * the info stored there, we schedule a nsock_connect_tcp() event. This means
+ * that nsock will initiate a TCP handshake and return. Whenever the handshake
+ * is completed, nsock will generate a CONNECT event to indicate it so we
+ * know the other peer was alive and willing to TCP-handshake with us.
+ *
+ * CONNECTS: These events are scheduled by the code that handles timer events.
+ * As described above, nsock generates a connect event when handshakes have
+ * completed. When we get a connect event we just tell the user the handshake
+ * was successful and update the stats.
+ * */
+/* This is the callback function for the nsock events produced in TCP-Connect
+ * mode. */
+void ProbeMode::probe_tcpconnect_event_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
+
+ nsock_iod nsi; /**< Current nsock IO descriptor. */
+ enum nse_status status; /**< Current nsock event status. */
+ enum nse_type type; /**< Current nsock event type. */
+ sendpkt_t *mypacket=NULL; /**< Info about the current probe. */
+ struct timeval *t=NULL; /**< Current time obtained through nsock. */
+ struct sockaddr_storage to; /**< Stores destination address for Tx. */
+ struct sockaddr_in *to4=NULL; /**< |_ Sockaddr for IPv4. */
+ struct sockaddr_in6 *to6=NULL; /**< |_ Sockaddr for IPv6. */
+ struct sockaddr_storage peer; /**< Stores source address for Rx. */
+ struct sockaddr_in *peer4=NULL; /**< |_ Sockaddr for IPv4. */
+ struct sockaddr_in6 *peer6=NULL; /**< |_ Sockaddr for IPv6. */
+ int family=0; /**< Hill hold Rx address family. */
+ char ipstring[128]; /**< To print IP Addresses. */
+ u16 peerport=0; /**< To hold peer's port number. */
+ size_t sslen=0; /**< To store length of sockaddr structs. */
+ static nsock_iod *fds=NULL; /**< IODs for multiple parallel connections*/
+ static int max_iods=0; /**< Number of IODS in "fds" */
+ static u32 packetno=0; /**< Packets sent from this handler. */
+ NpingTarget *trg=NULL; /**< Target we look up in NpingTargets:: */
+
+ /* Initializations */
+ nsi = nse_iod(nse);
+ status = nse_status(nse);
+ type = nse_type(nse);
+ mypacket = (sendpkt_t *)mydata;
+ t = (struct timeval *)nsock_gettimeofday();
+ to6=(struct sockaddr_in6 *)&to;
+ to4=(struct sockaddr_in *)&to;
+ peer4=(struct sockaddr_in *)&peer;
+ peer6=(struct sockaddr_in6 *)&peer;
+ memset(&to, 0, sizeof(struct sockaddr_storage));
+ memset(&peer, 0, sizeof(struct sockaddr_storage));
+
+ /* Try to determine the max number of opened descriptors. If the limit is
+ * less than than we need, try to increase it. */
+ if(fds==NULL){
+ max_iods=get_max_open_descriptors()-RESERVED_DESCRIPTORS;
+ if( o.getTotalProbes() > max_iods ){
+ max_iods=set_max_open_descriptors( o.getTotalProbes() )-RESERVED_DESCRIPTORS;
+ }
+ /* If we couldn't determine the limit, just use a predefined value */
+ if(max_iods<=0)
+ max_iods=DEFAULT_MAX_DESCRIPTORS-RESERVED_DESCRIPTORS;
+ /* Allocate space for nsock_iods */
+ if( (fds=(nsock_iod *)calloc(max_iods, sizeof(nsock_iod)))==NULL ){
+ /* If we can't allocate for that many descriptors, reduce our requirements */
+ max_iods=DEFAULT_MAX_DESCRIPTORS-RESERVED_DESCRIPTORS;
+ if( (fds=(nsock_iod *)calloc(max_iods, sizeof(nsock_iod)))==NULL ){
+ nping_fatal(QT_3, "ProbeMode::probe_tcpconnect_event_handler(): Not enough memory");
+ }
+ }
+ nping_print(DBG_7, "%d descriptors needed, %d available", o.getTotalProbes(), max_iods);
+ }
+
+ nping_print(DBG_4, "tcpconnect_event_handler(): Received callback of type %s with status %s", nse_type2str(type), nse_status2str(status));
+
+ if (status == NSE_STATUS_SUCCESS ) {
+
+ switch(type) {
+
+ /* TCP Handshake was completed successfully */
+ case NSE_TYPE_CONNECT:
+ if( mypacket==NULL )
+ nping_fatal(QT_3, "tcpconnect_event_handler(): NULL value supplied.");
+ /* Determine which target are we dealing with */
+ nsock_iod_get_communication_info(nsi, NULL, &family, NULL,
+ (struct sockaddr*)&peer,
+ sizeof(struct sockaddr_storage) );
+ if(family==AF_INET6){
+ inet_ntop(AF_INET6, &peer6->sin6_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer6->sin6_port);
+ }else{
+ inet_ntop(AF_INET, &peer4->sin_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer4->sin_port);
+ }
+
+ /* We cannot trust "mydata" pointer because it's contents may have
+ * been overwritten by the time we get the CONNECT event, so we have
+ * to look up the target by its IP address. */
+ trg=o.targets.findTarget( &peer );
+ if(trg!=NULL){
+ if ( trg->getSuppliedHostName() )
+ nping_print(VB_0,"RCVD (%.4fs) Handshake with %s:%d (%s:%d) completed",
+ o.stats.elapsedRuntime(t), trg->getSuppliedHostName(), peerport, ipstring, peerport );
+ else
+ nping_print(VB_0,"RCVD (%.4fs) Handshake with %s:%d completed", o.stats.elapsedRuntime(t), ipstring, peerport );
+ trg->setProbeRecvTCP( peerport , 0);
+ }else{
+ nping_print(VB_0,"RCVD (%.4fs) Handshake with %s:%d completed", o.stats.elapsedRuntime(t), ipstring, peerport );
+ }
+ o.stats.addRecvPacket(40); /* Estimation Dst>We 1 TCP SYN|ACK */
+ break;
+
+
+ /* We need to start an scheduled TCP Handshake. Theoretically in this
+ * case we can trust the supplied "mydata" structure because all our timers
+ * have the same exact time and Nsock should do FIFO with list of timer
+ * events. Additionally, even if that failed, more than MAX_PKT timer
+ * events would have to overlap to "corrupt" "mydata". Even if that's
+ * the case, it is only a problem when dealing with multiple targets host
+ * and/or multiple target ports. */
+ case NSE_TYPE_TIMER:
+ if( mypacket==NULL )
+ nping_fatal(QT_3, "tcpconnect_event_handler():2: NULL value supplied.");
+
+ /* Fill the appropriate sockaddr for the connect() call */
+ if( o.getIPVersion() == IP_VERSION_6 ){
+ to6->sin6_addr=mypacket->target->getIPv6Address();
+ to6->sin6_family = AF_INET6;
+ to6->sin6_port = htons( mypacket->dstport );
+ sslen=sizeof(struct sockaddr_in6);
+ }else{
+ to4->sin_addr=mypacket->target->getIPv4Address();
+ to4->sin_family = AF_INET;
+ to4->sin_port = htons( mypacket->dstport );
+ sslen=sizeof(struct sockaddr_in);
+ }
+
+ /* We need to keep many IODs open in parallel but we don't allocate
+ * millions, just as many as the OS let us (max number of open files).
+ * If we run out of them, we just start overwriting the oldest one.
+ * If we don't have a response by that time we probably aren't gonna
+ * get any, so it shouldn't be a big problem. */
+ if( packetno>(u32)max_iods ){
+ nsock_iod_delete(fds[packetno%max_iods], NSOCK_PENDING_SILENT);
+ }
+ /* Create new IOD for connects */
+ if ((fds[packetno%max_iods] = nsock_iod_new(nsp, NULL)) == NULL)
+ nping_fatal(QT_3, "tcpconnect_event_handler(): Failed to create new nsock_iod.\n");
+
+ /* Set socket source address. This allows setting things like custom source port */
+ struct sockaddr_storage ss;
+ nsock_iod_set_localaddr(fds[packetno%max_iods], o.getSourceSockAddr(&ss), sizeof(sockaddr_storage));
+ /*Set socket options for REUSEADDR*/
+ //setsockopt(nsock_iod_get_sd(fds[packetno%max_iods]),SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
+
+ nsock_connect_tcp(nsp, fds[packetno%max_iods], tcpconnect_event_handler, 100000, mypacket, (struct sockaddr *)&to, sslen, mypacket->dstport);
+ if( o.showSentPackets() ){
+ if ( mypacket->target->getSuppliedHostName() )
+ nping_print(VB_0,"SENT (%.4fs) Starting TCP Handshake > %s:%d (%s:%d)", o.stats.elapsedRuntime(NULL), mypacket->target->getSuppliedHostName(), mypacket->dstport ,mypacket->target->getTargetIPstr(), mypacket->dstport);
+ else
+ nping_print(VB_0,"SENT (%.4fs) Starting TCP Handshake > %s:%d", o.stats.elapsedRuntime(NULL), mypacket->target->getTargetIPstr(), mypacket->dstport);
+ }
+ packetno++;
+ o.stats.addSentPacket(80); /* Estimation Src>Dst 1 TCP SYN && TCP ACK */
+ mypacket->target->setProbeSentTCP(0, mypacket->dstport);
+ break;
+
+ case NSE_TYPE_WRITE:
+ case NSE_TYPE_READ:
+ case NSE_TYPE_PCAP_READ:
+ case NSE_TYPE_CONNECT_SSL:
+ nping_warning(QT_2,"tcpconnect_event_handler(): Unexpected behaviour, %s event received . Please report this bug.", nse_type2str(type));
+ break;
+
+ default:
+ nping_fatal(QT_3, "tcpconnect_event_handler(): Bogus event type (%d). Please report this bug.", type);
+ break;
+
+ } /* switch(type) */
+
+
+ } else if (status == NSE_STATUS_EOF) {
+ nping_print(DBG_4, "tcpconnect_event_handler(): Unexpected behaviour: Got EOF. Please report this bug.\n");
+ } else if (status == NSE_STATUS_ERROR) {
+ /** In my tests with Nping and Wireshark, I've seen that we get NSE_STATUS_ERROR
+ * whenever we start a TCP handshake but our peer sends a TCP RST packet back
+ * denying the connection. So in this case, we inform the user (as opposed
+ * to saying nothing, that's what we do when we don't get responses, e.g:
+ * when trying to connect to filtered ports). This is not 100% accurate
+ * because there may be other reasons why ge get NSE_STATUS_ERROR so that's
+ * why we say "Possible TCP RST received". */
+ if ( type == NSE_TYPE_CONNECT ){
+ nsock_iod_get_communication_info(nsi, NULL, &family, NULL, (struct sockaddr*)&peer, sizeof(struct sockaddr_storage) );
+ if(family==AF_INET6){
+ inet_ntop(AF_INET6, &peer6->sin6_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer6->sin6_port);
+ }else{
+ inet_ntop(AF_INET, &peer4->sin_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer4->sin_port);
+ }
+ nping_print(VB_0,"RCVD (%.4fs) Possible TCP RST received from %s:%d --> %s", o.stats.elapsedRuntime(t),ipstring, peerport, strerror(nse_errorcode(nse)) );
+ }
+ else
+ nping_warning(QT_2,"ERR: (%.4fs) %s to %s:%d failed: %s", o.stats.elapsedRuntime(t), nse_type2str(type), ipstring, peerport, strerror(socket_errno()));
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ nping_print(DBG_4, "tcpconnect_event_handler(): %s timeout: %s\n", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_CANCELLED) {
+ nping_print(DBG_4, "tcpconnect_event_handler(): %s canceled: %s", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_KILL) {
+ nping_print(DBG_4, "tcpconnect_event_handler(): %s killed: %s", nse_type2str(type), strerror(socket_errno()));
+ } else{
+ nping_warning(QT_2, "tcpconnect_event_handler(): Unknown status code %d. Please report this bug.", status);
+ }
+ return;
+
+} /* End of tcpconnect_event_handler() */
+
+
+
+
+
+/** This function handles nsock events related to UDP_UNPRIV mode.
+ * Basically the handler receives nsock events and takes the appropriate
+ * action based on event type. This is basically what it does for each event:
+ *
+ * TIMERS: normalProbeMode() schedules UDP packet transmissions through timers,
+ * that's how we manage to send the packets at a given rate. When the alarm
+ * goes off, nsock generates a timer event so, in this function, we take the
+ * supplied "mydata" pointer, convert it to a sendpkt_t pointer and, from
+ * the info stored there, we schedule a nsock_connect_udp() event. This means
+ * that nsock will perform the necessary system calls to obtain a UDP socket
+ * suitable to transmit information to our target host. We also schedule
+ * a write operation, since the connect_udp() doesn't do anything useful
+ * really and what we want to do is to actually send a TCP packet.
+ *
+ *
+ * CONNECTS: These events generated by nsock for consistency with the
+ * behavior in TCP connects. They are pretty useless. They merely indicate
+ * that nsock successfully obtained a UDP socket ready to allow sending
+ * packets to the appropriate target. We basically don't do anything when
+ * that event is received, just print a message if we are un debugging mode.
+ *
+ * WRITES: When we get event WRITE it means that nsock actually managed to
+ * get our data sent to the target. In this case, we inform the user that
+ * the packet has been sent, and we schedule a READ operation, to see
+ * if our peer actually returns any data.
+ *
+ * READS: When we get this event it means that the other end actually sent
+ * some data back to us. What we do is read that data, tell the user that
+ * we received some bytes and update statistics.
+ *
+ * */
+void ProbeMode::probe_udpunpriv_event_handler(nsock_pool nsp, nsock_event nse, void *mydata) {
+
+ nsock_iod nsi; /**< Current nsock IO descriptor. */
+ enum nse_status status; /**< Current nsock event status. */
+ enum nse_type type; /**< Current nsock event type. */
+ sendpkt_t *mypacket=NULL; /**< Info about the current probe. */
+ struct timeval *t=NULL; /**< Current time obtained through nsock. */
+ struct sockaddr_storage to; /**< Stores destination address for Tx. */
+ struct sockaddr_in *to4=NULL; /**< |_ Sockaddr for IPv4. */
+ struct sockaddr_in6 *to6=NULL; /**< |_ Sockaddr for IPv6. */
+ struct sockaddr_storage peer; /**< Stores source address for Rx. */
+ struct sockaddr_in *peer4=NULL; /**< |_ Sockaddr for IPv4. */
+ struct sockaddr_in6 *peer6=NULL; /**< |_ Sockaddr for IPv6. */
+ int family=0; /**< Hill hold Rx address family. */
+ char ipstring[128]; /**< To print IP Addresses. */
+ u16 peerport=0; /**< To hold peer's port number. */
+ size_t sslen=0; /**< To store length of sockaddr structs. */
+ static nsock_iod *fds=NULL; /**< IODs for multiple parallel connections*/
+ static int max_iods=0; /**< Number of IODS in "fds" */
+ static u32 packetno=0; /**< Packets sent from this handler. */
+ int readbytes=0; /**< Bytes read in total. */
+ char *readbuff=NULL; /**< Hill hold read data. */
+ static size_t sentbytes=0; /**< Payload bytes sent in each UDP packet */
+ NpingTarget *trg=NULL; /**< Target we look up in NpingTargets:: */
+
+ /* Initializations */
+ nsi = nse_iod(nse);
+ status = nse_status(nse);
+ type = nse_type(nse);
+ mypacket = (sendpkt_t *)mydata;
+ t = (struct timeval *)nsock_gettimeofday();
+ to6=(struct sockaddr_in6 *)&to;
+ to4=(struct sockaddr_in *)&to;
+ peer4=(struct sockaddr_in *)&peer;
+ peer6=(struct sockaddr_in6 *)&peer;
+ memset(&to, 0, sizeof(struct sockaddr_storage));
+ memset(&peer, 0, sizeof(struct sockaddr_storage));
+
+ /* Try to determine the max number of opened descriptors. If the limit is
+ * less than than we need, try to increase it. */
+ if(fds==NULL){
+ max_iods=get_max_open_descriptors()-RESERVED_DESCRIPTORS;
+ if( o.getTotalProbes() > max_iods ){
+ max_iods=set_max_open_descriptors( o.getTotalProbes() )-RESERVED_DESCRIPTORS;
+ }
+ /* If we couldn't determine the limit, just use a predefined value */
+ if(max_iods<=0)
+ max_iods=DEFAULT_MAX_DESCRIPTORS-RESERVED_DESCRIPTORS;
+ /* Allocate space for nsock_iods */
+ if( (fds=(nsock_iod *)calloc(max_iods, sizeof(nsock_iod)))==NULL ){
+ /* If we can't allocate for that many descriptors, reduce our requirements */
+ max_iods=DEFAULT_MAX_DESCRIPTORS-RESERVED_DESCRIPTORS;
+ if( (fds=(nsock_iod *)calloc(max_iods, sizeof(nsock_iod)))==NULL ){
+ nping_fatal(QT_3, "ProbeMode:probe_udpunpriv_event_handler(): Not enough memory");
+ }
+ }
+ nping_print(DBG_7, "%d descriptors needed, %d available", o.getTotalProbes(), max_iods);
+ }
+
+ nping_print(DBG_4, "udpunpriv_event_handler(): Received callback of type %s with status %s", nse_type2str(type), nse_status2str(status));
+
+ if (status == NSE_STATUS_SUCCESS ) {
+
+ switch(type) {
+
+
+ /* This is a bit stupid but, for consistency, Nsock creates an event of
+ * type NSE_TYPE_CONNECT after a call to nsock_connect_udp() is made.
+ * Basically this just means that nsock successfully obtained a UDP socket
+ * ready to allow sending packets to the appropriate target. */
+ case NSE_TYPE_CONNECT:
+ nping_print(DBG_3,"Nsock UDP \"connection\" completed successfully.");
+ break;
+
+
+
+ /* We need to start an scheduled UDP packet transmission. */
+ case NSE_TYPE_TIMER:
+ if( mypacket==NULL )
+ nping_fatal(QT_3, "udpunpriv_event_handler():: NULL value supplied.");
+
+ /* Fill the appropriate sockaddr for the connect() call */
+ if( o.getIPVersion() == IP_VERSION_6 ){
+ to6->sin6_addr=mypacket->target->getIPv6Address();
+ to6->sin6_family = AF_INET6;
+ to6->sin6_port = htons( mypacket->dstport );
+ sslen=sizeof(struct sockaddr_in6);
+ }else{
+ to4->sin_addr=mypacket->target->getIPv4Address();
+ to4->sin_family = AF_INET;
+ to4->sin_port = htons( mypacket->dstport );
+ sslen=sizeof(struct sockaddr_in);
+ }
+
+ /* We need to keep many IODs open in parallel but we don't allocate
+ * millions, just as many as the OS let us (max number of open files).
+ * If we run out of them, we just start overwriting the oldest one.
+ * If we don't have a response by that time we probably aren't gonna
+ * get any, so it shouldn't be a big problem. */
+ if( packetno>(u32)max_iods ){
+ nsock_iod_delete(fds[packetno%max_iods], NSOCK_PENDING_SILENT);
+ }
+ /* Create new IOD for connects */
+ if ((fds[packetno%max_iods] = nsock_iod_new(nsp, NULL)) == NULL)
+ nping_fatal(QT_3, "Failed to create new nsock_iod. QUITTING.\n");
+
+ /* Set socket source address. This allows setting things like custom source port */
+ struct sockaddr_storage ss;
+ nsock_iod_set_localaddr(fds[packetno%max_iods], o.getSourceSockAddr(&ss), sizeof(sockaddr_storage));
+
+
+ /* I dunno if it's safe to schedule an nsock_write before we
+ * receive a NSE_TYPE_CONNECT event. The call to nsock_connect_udp()
+ * calls inheritable_socket() before returning which should mean
+ * an actual socket() call has been made before we nsock_write().
+ * However, if the way nsock behaves changes in the future it may
+ * break this so we may need to place nsock_write() in
+ * "case NSE_TYPE_CONNECT:". We could do it right now but it may
+ * be a bit complicated due to the "packetno" index.
+ */
+ nsock_connect_udp(nsp, fds[packetno%max_iods], udpunpriv_event_handler, mypacket, (struct sockaddr *)&to, sslen, mypacket->dstport);
+ nsock_write(nsp, fds[packetno%max_iods], udpunpriv_event_handler,100000, mypacket, (const char*)mypacket->pkt, mypacket->pktLen);
+ sentbytes=mypacket->pktLen;
+ packetno++;
+ break;
+
+
+
+
+ /* We get this event as a result of the nsock_write() call performed by
+ * the code in charge of dealing with the timer event. When we get this
+ * even it means that nsock successfully wrote data to the UDP socket so
+ * here we basically just print that we did send some data and we schedule
+ * a read operation.
+ */
+ case NSE_TYPE_WRITE:
+ /* Determine which target are we dealing with */
+ nsock_iod_get_communication_info(nsi, NULL, &family, NULL, (struct sockaddr*)&peer, sizeof(struct sockaddr_storage) );
+ if(family==AF_INET6){
+ inet_ntop(AF_INET6, &peer6->sin6_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer6->sin6_port);
+ }else{
+ inet_ntop(AF_INET, &peer4->sin_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer4->sin_port);
+ }
+
+ /* We cannot trust "mydata" pointer because it's contents may have
+ * been overwritten by the time we get the WRITE event, (this is
+ * unlikely but it may happen when sending probes at a very high rate).
+ * As a consequence, we have to look up the target by its IP address. */
+ trg=o.targets.findTarget( &peer );
+ if(trg!=NULL){
+ if ( trg->getSuppliedHostName() )
+ nping_print(VB_0,"SENT (%.4fs) UDP packet with %lu bytes to %s:%d (%s:%d)", o.stats.elapsedRuntime(NULL), (unsigned long int)sentbytes, trg->getSuppliedHostName(), peerport, ipstring, peerport );
+ else
+ nping_print(VB_0,"SENT (%.4fs) UDP packet with %lu bytes to %s:%d", o.stats.elapsedRuntime(NULL), (unsigned long int)sentbytes, ipstring, peerport );
+ trg->setProbeSentUDP( 0, peerport);
+ }else{
+ nping_print(VB_0,"SENT (%.4fs) UDP packet with %lu bytes to %s:%d", o.stats.elapsedRuntime(t), (unsigned long int)sentbytes, ipstring, peerport );
+ }
+ o.stats.addSentPacket(sentbytes); /* Here we don't count the headers, just payload bytes */
+
+ /* If user did not disable packet capture, schedule a read operation */
+ if( !o.disablePacketCapture() )
+ nsock_read(nsp, nsi, udpunpriv_event_handler, DEFAULT_UDP_READ_TIMEOUT_MS, mypacket);
+ break;
+
+
+
+ /* We get this event when we've written some data to a UDP socket and
+ * the other end has sent some data back. In this case we read the data and
+ * inform the user of how many bytes we got.
+ */
+ case NSE_TYPE_READ:
+ /* Do an actual read() of the recv data */
+ readbuff=nse_readbuf(nse, &readbytes);
+ if(readbuff==NULL){
+ nping_fatal(QT_3, "Error: nse_readbuff failed to read in the from the probe");
+ }
+ /* Determine which target are we dealing with */
+ nsock_iod_get_communication_info(nsi, NULL, &family, NULL, (struct sockaddr*)&peer, sizeof(struct sockaddr_storage) );
+ if(family==AF_INET6){
+ inet_ntop(AF_INET6, &peer6->sin6_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer6->sin6_port);
+ }else{
+ inet_ntop(AF_INET, &peer4->sin_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer4->sin_port);
+ }
+
+ /* Lookup our peer's NpingTarget entry */
+ trg=o.targets.findTarget( &peer );
+ if(trg!=NULL){
+ if ( trg->getSuppliedHostName() )
+ nping_print(VB_0,"RCVD (%.4fs) UDP packet with %d bytes from %s:%d (%s:%d)", o.stats.elapsedRuntime(NULL), readbytes, trg->getSuppliedHostName(), peerport, ipstring, peerport );
+ else
+ nping_print(VB_0,"RCVD (%.4fs) UDP packet with %d bytes from %s:%d", o.stats.elapsedRuntime(NULL), readbytes, ipstring, peerport );
+ trg->setProbeRecvUDP(peerport, 0);
+ }else{
+ nping_print(VB_0,"RCVD (%.4fs) UDP packet with %d bytes from %s:%d", o.stats.elapsedRuntime(t), readbytes, ipstring, peerport );
+ }
+ o.stats.addRecvPacket(readbytes);
+ break;
+
+
+ case NSE_TYPE_PCAP_READ:
+ case NSE_TYPE_CONNECT_SSL:
+ nping_warning(QT_2,"udpunpriv_event_handler(): Unexpected behavior, %s event received . Please report this bug.", nse_type2str(type));
+ break;
+
+ default:
+ nping_fatal(QT_3, "udpunpriv_event_handler(): Bogus event type (%d). Please report this bug.", type);
+ break;
+
+ } /* switch(type) */
+
+
+ } else if (status == NSE_STATUS_EOF) {
+ nping_print(DBG_4, "udpunpriv_event_handler(): Unexpected behaviour: Got EOF. Please report this bug.\n");
+ } else if (status == NSE_STATUS_ERROR) {
+ nsock_iod_get_communication_info(nsi, NULL, &family, NULL, (struct sockaddr*)&peer, sizeof(struct sockaddr_storage) );
+ if(family==AF_INET6){
+ inet_ntop(AF_INET6, &peer6->sin6_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer6->sin6_port);
+ }else{
+ inet_ntop(AF_INET, &peer4->sin_addr, ipstring, sizeof(ipstring));
+ peerport=ntohs(peer4->sin_port);
+ }
+ nping_warning(QT_2,"ERR: (%.4fs) %s to %s:%d failed: %s", o.stats.elapsedRuntime(t), nse_type2str(type), ipstring, peerport, strerror(socket_errno()));
+ } else if (status == NSE_STATUS_TIMEOUT) {
+ nping_print(DBG_4, "udpunpriv_event_handler(): %s timeout: %s\n", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_CANCELLED) {
+ nping_print(DBG_4, "udpunpriv_event_handler(): %s canceled: %s", nse_type2str(type), strerror(socket_errno()));
+ } else if (status == NSE_STATUS_KILL) {
+ nping_print(DBG_4, "udpunpriv_event_handler(): %s killed: %s", nse_type2str(type), strerror(socket_errno()));
+ }
+ else{
+ nping_warning(QT_2, "udpunpriv_event_handler(): Unknown status code %d. Please report this bug.", status);
+ }
+ return;
+
+} /* End of udpunpriv_event_handler() */
+
+
+
+/* This handler is a wrapper for the ProbeMode::probe_nping_event_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void nping_event_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ProbeMode::probe_nping_event_handler(nsp, nse, arg);
+ return;
+} /* End of nping_event_handler() */
+
+
+/* This handler is a wrapper for the ProbeMode::probe_tcpconnect_event_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void tcpconnect_event_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ProbeMode::probe_tcpconnect_event_handler(nsp, nse, arg);
+ return;
+} /* End of tcpconnect_event_handler() */
+
+
+/* This handler is a wrapper for the ProbeMode::probe_udpunpriv_event_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void udpunpriv_event_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ProbeMode::probe_udpunpriv_event_handler(nsp, nse, arg);
+ return;
+} /* End of udpunpriv_event_handler() */
+
+
+
+/* This handler is a wrapper for the ProbeMode::probe_delayed_output_handler()
+ * method. We need this because C++ does not allow to use class methods as
+ * callback functions for things like signal() or the Nsock lib. */
+void delayed_output_handler(nsock_pool nsp, nsock_event nse, void *arg){
+ nping_print(DBG_4, "%s()", __func__);
+ ProbeMode::probe_delayed_output_handler(nsp, nse, arg);
+ return;
+} /* End of udpunpriv_event_handler() */
diff --git a/nping/ProbeMode.h b/nping/ProbeMode.h
new file mode 100644
index 0000000..f609978
--- /dev/null
+++ b/nping/ProbeMode.h
@@ -0,0 +1,133 @@
+
+/***************************************************************************
+ * ProbeMode.h -- Probe Mode is nping's default working mode. Basically, *
+ * it involves sending the packets that the user requested at regular *
+ * intervals and capturing responses from the wire. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+#ifndef __PROBEMODE_H__
+#define __PROBEMODE_H__ 1
+
+
+
+#include "nping.h"
+#include "nsock.h"
+#include "NpingTarget.h"
+#include "utils_net.h"
+#include "utils.h"
+
+#define PKT_TYPE_TCP_CONNECT 1
+#define PKT_TYPE_UDP_NORMAL 2
+#define PKT_TYPE_TCP_RAW 3
+#define PKT_TYPE_UDP_RAW 4
+#define PKT_TYPE_ICMP_RAW 5
+#define PKT_TYPE_ARP_RAW 6
+
+/* The sendpkt structure is the data normalProbeMode() function passes to
+ * the nsock event handler. It contains the necessary information so a
+ * handler can send one probe. */
+typedef struct sendpkt{
+ int type;
+ u8 *pkt;
+ int pktLen;
+ int rawfd;
+ u32 seq;
+ NpingTarget *target;
+ u16 dstport;
+}sendpkt_t;
+
+
+class ProbeMode {
+
+ private:
+
+ nsock_pool nsp; /**< Internal Nsock pool */
+ bool nsock_init; /**< True if nsock pool has been initialized */
+
+ public:
+
+ ProbeMode();
+ ~ProbeMode();
+ void reset();
+ int init_nsock();
+ int start();
+ int cleanup();
+ nsock_pool getNsockPool();
+
+ static int createIPv4(IPv4Header *i, PacketElement *next_element, const char *next_proto, NpingTarget *target);
+ static int createIPv6(IPv6Header *i, PacketElement *next_element, const char *next_proto, NpingTarget *target);
+ static int doIPv6ThroughSocket(int rawfd);
+ static int fillPacket(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd);
+ static int fillPacketTCP(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd);
+ static int fillPacketUDP(NpingTarget *target, u16 port, u8 *buff, int bufflen, int *filledlen, int rawfd);
+ static int fillPacketICMP(NpingTarget *target, u8 *buff, int bufflen, int *filledlen, int rawfd);
+ static int fillPacketARP(NpingTarget *target, u8 *buff, int bufflen, int *filledlen, int rawfd);
+ static char *getBPFFilterString();
+ static void probe_nping_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ static void probe_delayed_output_handler(nsock_pool nsp, nsock_event nse, void *mydata);
+ static void probe_tcpconnect_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+ static void probe_udpunpriv_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+
+}; /* End of class ProbeMode */
+
+
+/* Handler wrappers */
+void nping_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void tcpconnect_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void udpunpriv_event_handler(nsock_pool nsp, nsock_event nse, void *arg);
+void delayed_output_handler(nsock_pool nsp, nsock_event nse, void *arg);
+
+#endif /* __PROBEMODE_H__ */
diff --git a/nping/common.cc b/nping/common.cc
new file mode 100644
index 0000000..b580dc8
--- /dev/null
+++ b/nping/common.cc
@@ -0,0 +1,65 @@
+
+/***************************************************************************
+ * common.cc -- This file holds all those functions and classes that have *
+ * been copied verbatim from Nmap's source code *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* THIS FILE HAS ALL THE FUNCTIONS THAT I'VE COPIED VERBATIM FROM NMAP'S
+ * SOURCE CODE. */
+
+#include "nping.h"
+#include "common.h"
diff --git a/nping/common.h b/nping/common.h
new file mode 100644
index 0000000..46454ca
--- /dev/null
+++ b/nping/common.h
@@ -0,0 +1,69 @@
+
+/***************************************************************************
+ * common.h -- This file holds all those functions and classes that have *
+ * been copied verbatim from Nmap's source code *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* THIS FILE HAS ALL THE FUNCTIONS THAT I'VE COPIED VERBATIM FROM NMAP'S
+ * SOURCE CODE. */
+
+#ifndef COMMON_H
+#define COMMON_H 1
+
+#include "nping.h"
+
+#endif /* COMMON_H */
diff --git a/nping/common_modified.cc b/nping/common_modified.cc
new file mode 100644
index 0000000..abed5c5
--- /dev/null
+++ b/nping/common_modified.cc
@@ -0,0 +1,782 @@
+
+/***************************************************************************
+ * common_modified.cc -- This file holds all those functions and classes *
+ * that have been reused from Nmap's code but that needed to be modified *
+ * in order to reuse them. *
+ * *
+ ***********************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 "common.h"
+#include "common_modified.h"
+#include "output.h"
+#include "../libnetutil/netutil.h"
+/*****************************************************************************
+ * STUFF FROM TargetGroup.cc
+ ****************************************************************************
+
+ CHANGES:
+ Modified parse_expr.
+ Modified get_next_host:
+
+*/
+
+
+TargetGroup::TargetGroup() {
+ Initialize();
+}
+
+// Bring back (or start with) original state
+void TargetGroup::Initialize() {
+ targets_type = TYPE_NONE;
+ memset(addresses, 0, sizeof(addresses));
+ memset(current, 0, sizeof(current));
+ memset(last, 0, sizeof(last));
+ ipsleft = 0;
+}
+
+/* take the object back to the beginning without (mdmcl)
+ * reinitializing the data structures */
+int TargetGroup::rewind() {
+
+ /* For netmasks we must set the current address to the
+ * starting address and calculate the ips by distance */
+ if (targets_type == IPV4_NETMASK) {
+ currentaddr = startaddr;
+ if (startaddr.s_addr <= endaddr.s_addr) {
+ ipsleft = ((unsigned long long) (endaddr.s_addr - startaddr.s_addr)) + 1;
+ return 0;
+ }
+ else
+ assert(0);
+ }
+ /* For ranges, we easily set current to zero and calculate
+ * the ips by the number of values in the columns */
+ else if (targets_type == IPV4_RANGES) {
+ memset((char *)current, 0, sizeof(current));
+ ipsleft = (unsigned long long) (last[0] + 1) *
+ (unsigned long long) (last[1] + 1) *
+ (unsigned long long) (last[2] + 1) *
+ (unsigned long long) (last[3] + 1);
+ return 0;
+ }
+#if HAVE_IPV6
+ /* For IPV6 there is only one address, this function doesn't
+ * make much sense for IPv6 does it? */
+ else if (targets_type == IPV6_ADDRESS) {
+ ipsleft = 1;
+ return 0;
+ }
+#endif
+
+ /* If we got this far there must be an error, wrong type */
+ return -1;
+}
+
+
+
+/* For ranges, skip all hosts in an octet, (mdmcl)
+ * get_next_host should be used for skipping the last octet :-)
+ * returns: number of hosts skipped */
+int TargetGroup::skip_range(_octet_nums octet) {
+ u32 hosts_skipped = 0, /* number of hosts skipped */
+ oct = 0; /* octect number */
+ int i = 0; /* simple lcv */
+
+ /* This function is only supported for RANGES! */
+ if (targets_type != IPV4_RANGES)
+ return -1;
+
+ switch (octet) {
+ case FIRST_OCTET:
+ oct = 0;
+ hosts_skipped = (u32)(last[1] + 1) * (last[2] + 1) * (last[3] + 1);
+ break;
+ case SECOND_OCTET:
+ oct = 1;
+ hosts_skipped = (u32)(last[2] + 1) * (last[3] + 1);
+ break;
+ case THIRD_OCTET:
+ oct = 2;
+ hosts_skipped = (last[3] + 1);
+ break;
+ default: /* Hmm, how did you do that? */
+ return -1;
+ }
+
+ /* catch if we try to take more than are left */
+ assert(ipsleft + 1>= hosts_skipped);
+
+ /* increment the next octect that we can above us */
+ for (i = oct; i >= 0; i--) {
+ if (current[i] < last[i]) {
+ current[i]++;
+ break;
+ }
+ else
+ current[i] = 0;
+ }
+
+ /* reset all the ones below us to zero */
+ for (i = oct+1; i <= 3; i++) {
+ current[i] = 0;
+ }
+
+ /* we actually don't skip the current, it was accounted for
+ * by get_next_host */
+ ipsleft -= hosts_skipped - 1;
+
+ return hosts_skipped;
+}
+
+ /* Grab the next host from this expression (if any) and updates its internal
+ state to reflect that the IP was given out. Returns 0 and
+ fills in ss if successful. ss must point to a pre-allocated
+ sockaddr_storage structure */
+int TargetGroup::get_next_host(struct sockaddr_storage *ss, size_t *sslen) {
+
+ int octet;
+ struct sockaddr_in *sin = (struct sockaddr_in *) ss;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) ss;
+
+ /* CHANGE: Commented out. See note at the end of the method */
+ //startover: /* to handle nmap --resume where I have already
+ // * scanned many of the IPs */
+ assert(ss);
+ assert(sslen);
+
+
+ if (ipsleft == 0)
+ return -1;
+
+ if (targets_type == IPV4_NETMASK) {
+ memset(sin, 0, sizeof(struct sockaddr_in));
+ sin->sin_family = AF_INET;
+ *sslen = sizeof(struct sockaddr_in);
+#if HAVE_SOCKADDR_SA_LEN
+ sin->sin_len = *sslen;
+#endif
+
+ if (currentaddr.s_addr <= endaddr.s_addr) {
+ sin->sin_addr.s_addr = htonl(currentaddr.s_addr++);
+ } else {
+ error("Bogus target structure passed to %s", __func__);
+ ipsleft = 0;
+ return -1;
+ }
+ }
+ else if (targets_type == IPV4_RANGES) {
+ memset(sin, 0, sizeof(struct sockaddr_in));
+ sin->sin_family = AF_INET;
+ *sslen = sizeof(struct sockaddr_in);
+#if HAVE_SOCKADDR_SA_LEN
+ sin->sin_len = *sslen;
+#endif
+ //if (o.debugging > 2) { /* CHANGE: Do not use NmapOps and do not use log_Write*/
+ // log_write(LOG_STDOUT, "doing %d.%d.%d.%d = %d.%d.%d.%d\n", current[0], current[1], current[2], current[3], addresses[0][current[0]],addresses[1][current[1]],addresses[2][current[2]],addresses[3][current[3]]);
+ //}
+ //nping_print(DBG_2, "doing %d.%d.%d.%d = %d.%d.%d.%d", current[0], current[1], current[2], current[3], addresses[0][current[0]],addresses[1][current[1]],addresses[2][current[2]],addresses[3][current[3]]);
+
+
+ /* Set the IP to the current value of everything */
+ sin->sin_addr.s_addr = htonl(addresses[0][current[0]] << 24 |
+ addresses[1][current[1]] << 16 |
+ addresses[2][current[2]] << 8 |
+ addresses[3][current[3]]);
+
+ /* Now we nudge up to the next IP */
+ for(octet = 3; octet >= 0; octet--) {
+ if (current[octet] < last[octet]) {
+ /* OK, this is the column I have room to nudge upwards */
+ current[octet]++;
+ break;
+ } else {
+ /* This octet is finished so I reset it to the beginning */
+ current[octet] = 0;
+ }
+ }
+ if (octet == -1) {
+ /* It didn't find anything to bump up, I must have taken the last IP */
+ assert(ipsleft == 1);
+ /* So I set current to last with the very final octet up one ... */
+ /* Note that this may make current[3] == 256 */
+ current[0] = last[0]; current[1] = last[1];
+ current[2] = last[2]; current[3] = last[3] + 1;
+ } else {
+ assert(ipsleft > 1); /* There must be at least one more IP left */
+ }
+ } else {
+ assert(targets_type == IPV6_ADDRESS);
+ assert(ipsleft == 1);
+#if HAVE_IPV6
+ *sslen = sizeof(struct sockaddr_in6);
+ memset(sin6, 0, *sslen);
+ sin6->sin6_family = AF_INET6;
+#ifdef SIN_LEN
+ sin6->sin6_len = *sslen;
+#endif /* SIN_LEN */
+ memcpy(sin6->sin6_addr.s6_addr, ip6.sin6_addr.s6_addr, 16);
+ sin6->sin6_scope_id = ip6.sin6_scope_id;
+#else
+ fatal("IPV6 not supported on this platform");
+#endif // HAVE_IPV6
+ }
+ ipsleft--;
+
+
+ /* CHANGE: These lines have been commented out to make this code
+ * independent from NmapOps */
+ /* If we are resuming from a previous scan, we have already finished
+ scans up to o.resume_ip. */
+ // if (sin->sin_family == AF_INET && o.resume_ip.s_addr) {
+ // if (o.resume_ip.s_addr == sin->sin_addr.s_addr)
+ // o.resume_ip.s_addr = 0; /* So that we will KEEP the next one */
+ // goto startover; /* Try again */
+ // }
+
+ return 0;
+}
+
+/* Returns the last given host, so that it will be given again next
+ time get_next_host is called. Obviously, you should only call
+ this if you have fetched at least 1 host since parse_expr() was
+ called */
+int TargetGroup::return_last_host() {
+ int octet;
+
+ ipsleft++;
+ if (targets_type == IPV4_NETMASK) {
+ assert(currentaddr.s_addr > startaddr.s_addr);
+ currentaddr.s_addr--;
+ } else if (targets_type == IPV4_RANGES) {
+ for(octet = 3; octet >= 0; octet--) {
+ if (current[octet] > 0) {
+ /* OK, this is the column I have room to nudge downwards */
+ current[octet]--;
+ break;
+ } else {
+ /* This octet is already at the beginning, so I set it to the end */
+ current[octet] = last[octet];
+ }
+ }
+ assert(octet != -1);
+ } else {
+ assert(targets_type == IPV6_ADDRESS);
+ assert(ipsleft == 1);
+ }
+ return 0;
+}
+
+
+
+
+
+/* TODO: WARNING: This functions has been modified for portability. Check
+ * for label "CHANGE:" in the code to see the actual changes.
+ *
+ * UPDATE: Added support for DNS resolution caching. Using function
+ * gethostbynameCached() instead of gethostbyname()
+ */
+ /* Initializes (or reinitializes) the object with a new expression, such
+ as 192.168.0.0/16 , 10.1.0-5.1-254 , or fe80::202:e3ff:fe14:1102 .
+ Returns 0 for success */
+int TargetGroup::parse_expr(const char * const target_expr, int af) {
+
+ int i=0,j=0,k=0;
+ int start, end;
+ char *r,*s, *target_net;
+ char *addy[5];
+ char *hostexp = strdup(target_expr);
+ struct hostent *target;
+ namedhost = 0;
+
+ if (targets_type != TYPE_NONE)
+ Initialize();
+
+ ipsleft = 0;
+
+ if (af == AF_INET) {
+
+ if (strchr(hostexp, ':'))
+ fatal("Invalid host expression: %s -- colons only allowed in IPv6 addresses, and then you need the -6 switch", hostexp);
+
+ /*struct in_addr current_in;*/
+ addy[0] = addy[1] = addy[2] = addy[3] = addy[4] = NULL;
+ addy[0] = r = hostexp;
+ /* First we break the expression up into the four parts of the IP address
+ + the optional '/mask' */
+ target_net = hostexp;
+ s = strchr(hostexp, '/'); /* Find the slash if there is one */
+ if (s) {
+ char *tail;
+ long netmask_long;
+
+ *s = '\0'; /* Make sure target_net is terminated before the /## */
+ s++; /* Point s at the netmask */
+ if (!isdigit(*s)) {
+ error("Illegal netmask value, must be /0 - /32 . Assuming /32 (one host)");
+ netmask = 32;
+ } else {
+ netmask_long = strtol(s, (char**) &tail, 10);
+ if (*tail != '\0' || tail == s || netmask_long < 0 || netmask_long > 32) {
+ error("Illegal netmask value, must be /0 - /32 . Assuming /32 (one host)");
+ netmask = 32;
+ } else
+ netmask = (u32) netmask_long;
+ }
+ } else
+ netmask = 32;
+ for(i=0; *(hostexp + i); i++)
+ if (isupper((int) *(hostexp +i)) || islower((int) *(hostexp +i))) {
+ namedhost = 1;
+ break;
+ }
+ if (netmask != 32 || namedhost) {
+ targets_type = IPV4_NETMASK;
+ if (!inet_pton(AF_INET, target_net, &(startaddr))) {
+
+ /* There is a bug report on the use of gethostbynameCached()
+ * <http://seclists.org/nmap-dev/2010/q1/803>
+ * I haven't been able to find any problem with that code but
+ * still, the fact that DNS queries are cached does not improve
+ * performance a lot. It may save one DNS query per execution
+ * in those cases where NpingOps::validateOptions() grabs the
+ * first target and uses it to determine output network interface.
+ * It would also save some queries in the case where a user
+ * specified the same host twice in the commandlined, something
+ * that does not make much sense anyway. However, since the call
+ * to gethostbynameCached() seems to cause denial of service
+ * for some people, I think it's ok to disable its use for now
+ * and enable it later if there is a good reason for it.
+ *
+ * Luis MartinGarcia. */
+ //if ((target = gethostbynameCached(target_net))) {
+ if ((target = gethostbyname(target_net))) {
+ int count=0;
+
+ memcpy(&(startaddr), target->h_addr_list[0], sizeof(struct in_addr));
+
+ while (target->h_addr_list[count]) count++;
+
+ if (count > 1)
+ nping_print(DBG_2,"Warning: Hostname %s resolves to %d IPs. Using %s.", target_net, count, inet_ntoa(*((struct in_addr *)target->h_addr_list[0])));
+ } else {
+ error("Failed to resolve given hostname/IP: %s. Note that you can't use '/mask' AND '1-4,7,100-' style IP ranges", target_net);
+ free(hostexp);
+ return 1;
+ }
+ }
+ if (netmask) {
+ unsigned long longtmp = ntohl(startaddr.s_addr);
+ startaddr.s_addr = longtmp & (unsigned long) (0 - (1<<(32 - netmask)));
+ endaddr.s_addr = longtmp | (unsigned long) ((1<<(32 - netmask)) - 1);
+ } else {
+ /* The above calculations don't work for a /0 netmask, though at first
+ * glance it appears that they would
+ */
+ startaddr.s_addr = 0;
+ endaddr.s_addr = 0xffffffff;
+ }
+ currentaddr = startaddr;
+ if (startaddr.s_addr <= endaddr.s_addr) {
+ ipsleft = ((unsigned long long) (endaddr.s_addr - startaddr.s_addr)) + 1;
+ free(hostexp);
+ return 0;
+ }
+ fprintf(stderr, "Host specification invalid");
+ free(hostexp);
+ return 1;
+ }
+ else {
+ targets_type = IPV4_RANGES;
+ i=0;
+
+ while(*r) {
+ if (*r == '.' && ++i < 4) {
+ *r = '\0';
+ addy[i] = r + 1;
+ }
+ else if (*r != '*' && *r != ',' && *r != '-' && !isdigit((int)*r))
+ fatal("Invalid character in host specification. Note in particular that square brackets [] are no longer allowed. They were redundant and can simply be removed.");
+ r++;
+ }
+ if (i != 3) fatal("Invalid target host specification: %s", target_expr);
+
+ for(i=0; i < 4; i++) {
+ j=0;
+ do {
+ s = strchr(addy[i],',');
+ if (s) *s = '\0';
+ if (*addy[i] == '*') { start = 0; end = 255; }
+ else if (*addy[i] == '-') {
+ start = 0;
+ if (*(addy[i] + 1) == '\0') end = 255;
+ else end = atoi(addy[i]+ 1);
+ }
+ else {
+ start = end = atoi(addy[i]);
+ if ((r = strchr(addy[i],'-')) && *(r+1) ) end = atoi(r + 1);
+ else if (r && !*(r+1)) end = 255;
+ }
+ /* if (o.debugging > 2)
+ * log_write(LOG_STDOUT, "The first host is %d, and the last one is %d\n", start, end); */
+ if (start < 0 || start > end || start > 255 || end > 255)
+ fatal("Your host specifications are illegal!");
+ if (j + (end - start) > 255)
+ fatal("Your host specifications are illegal!");
+ for(k=start; k <= end; k++)
+ addresses[i][j++] = k;
+ last[i] = j-1;
+ if (s) addy[i] = s + 1;
+ } while (s);
+ }
+ }
+ memset((char *)current, 0, sizeof(current));
+ ipsleft = (unsigned long long) (last[0] + 1) *
+ (unsigned long long) (last[1] + 1) *
+ (unsigned long long) (last[2] + 1) *
+ (unsigned long long) (last[3] + 1);
+ }
+ else {
+#if HAVE_IPV6
+ int rc = 0;
+ assert(af == AF_INET6);
+ if (strchr(hostexp, '/')) {
+ fatal("Invalid host expression: %s -- slash not allowed. IPv6 addresses can currently only be specified individually", hostexp);
+ }
+ targets_type = IPV6_ADDRESS;
+ struct addrinfo hints;
+ struct addrinfo *result = NULL;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_INET6;
+ rc = getaddrinfo(hostexp, NULL, &hints, &result);
+ if (rc != 0 || result == NULL) {
+ error("Failed to resolve given IPv6 hostname/IP: %s. Note that you can't use '/mask' or '[1-4,7,100-]' style ranges for IPv6. Error code %d: %s", hostexp, rc, gai_strerror(rc));
+ free(hostexp);
+ if (result) freeaddrinfo(result);
+ return 1;
+ }
+ assert(result->ai_addrlen == sizeof(struct sockaddr_in6));
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) result->ai_addr;
+ memcpy(&ip6, sin6, sizeof(struct sockaddr_in6));
+ ipsleft = 1;
+ freeaddrinfo(result);
+#else // HAVE_IPV6
+ fatal("IPv6 not supported on your platform");
+#endif // HAVE_IPV6
+ }
+
+ free(hostexp);
+ return 0;
+}
+
+/*****************************************************************************/
+/* getpts() and getpts_simple() (see above) are wrappers for this function */
+void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int *portwarning) {
+ long rangestart = -2343242, rangeend = -9324423;
+ const char *current_range;
+ char *endptr;
+ //char servmask[128]; // A protocol name can be up to 127 chars + nul byte
+ //int i;
+
+ /* An example of proper syntax to use in error messages. */
+ const char *syntax_example;
+ //if (change_range_type)
+ // syntax_example = "-100,200-1024,T:3000-4000,U:60000-";
+ //else
+ syntax_example = "-100,200-1024,3000-4000,60000-";
+
+ current_range = origexpr;
+ do {
+ while(isspace((int) *current_range))
+ current_range++; /* I don't know why I should allow spaces here, but I will */
+
+ //if (change_range_type) {
+ //if (*current_range == 'T' && *++current_range == ':') {
+ //current_range++;
+ //range_type = SCAN_TCP_PORT;
+ //continue;
+ //}
+ //if (*current_range == 'U' && *++current_range == ':') {
+ //current_range++;
+ //range_type = SCAN_UDP_PORT;
+ //continue;
+ //}
+ //if (*current_range == 'S' && *++current_range == ':') {
+ //current_range++;
+ //range_type = SCAN_SCTP_PORT;
+ //continue;
+ //}
+ //if (*current_range == 'P' && *++current_range == ':') {
+ //current_range++;
+ //range_type = SCAN_PROTOCOLS;
+ //continue;
+ //}
+ //}
+
+ if (*current_range == '[') {
+ if (nested)
+ fatal("Can't nest [] brackets in port/protocol specification");
+
+ //getpts_aux(++current_range, 1, porttbl, range_type, portwarning);
+ getpts_aux(++current_range, 1, porttbl, portwarning); // ADDED
+
+ // Skip past the ']'. This is OK because we can't nest []s
+ while(*current_range != ']') current_range++;
+ current_range++;
+
+ // Skip over a following ',' so we're ready to keep parsing
+ if (*current_range == ',') current_range++;
+
+ continue;
+ } else if (*current_range == ']') {
+ if (!nested)
+ fatal("Unexpected ] character in port/protocol specification");
+
+ return;
+ } else if (*current_range == '-') {
+ //if (range_type & SCAN_PROTOCOLS)
+ // rangestart = 0;
+ //else
+ rangestart = 1;
+ }
+ else if (isdigit((int) *current_range)) {
+ rangestart = strtol(current_range, &endptr, 10);
+ //if (range_type & SCAN_PROTOCOLS) {
+ // if (rangestart < 0 || rangestart > 255)
+ //fatal("Protocols to be scanned must be between 0 and 255 inclusive");
+ //} else {
+ if (rangestart < 0 || rangestart > 65535)
+ fatal("Ports to be scanned must be between 0 and 65535 inclusive");
+ //}
+ current_range = endptr;
+ while(isspace((int) *current_range)) current_range++;
+ } //else if (islower((int) *current_range) || *current_range == '*' || *current_range == '?') {
+ //i = 0;
+
+ //while (*current_range && !isspace((int)*current_range) && *current_range != ',' && *current_range != ']') {
+ // servmask[i++] = *(current_range++);
+ // if (i >= ((int)sizeof(servmask)-1))
+ // fatal("A service mask in the port/protocol specification is either malformed or too long");
+ // }
+
+ // if (*current_range && *current_range != ']') current_range++; // We want the '] character to be picked up on the next pass
+ // servmask[i] = '\0'; // Finish the string
+
+ //i = addportsfromservmask(servmask, porttbl, range_type);
+ //if (range_type & SCAN_PROTOCOLS) i += addprotocolsfromservmask(servmask, porttbl);
+
+ //if (i == 0)
+ // fatal("Found no matches for the service mask '%s' and your specified protocols", servmask);
+
+ //continue;
+
+ /*}*/ else {
+ fatal("Error #485: Your port specifications are illegal. Example of proper form: \"%s\"", syntax_example);
+ }
+ /* Now I have a rangestart, time to go after rangeend */
+ if (!*current_range || *current_range == ',' || *current_range == ']') {
+ /* Single port specification */
+ rangeend = rangestart;
+ } else if (*current_range == '-') {
+ current_range++;
+ if (!*current_range || *current_range == ',' || *current_range == ']') {
+ /* Ended with a -, meaning up until the last possible port */
+ //if (range_type & SCAN_PROTOCOLS)
+ // rangeend = 255;
+ //else
+ rangeend = 65535;
+ } else if (isdigit((int) *current_range)) {
+ rangeend = strtol(current_range, &endptr, 10);
+ // if (range_type & SCAN_PROTOCOLS) {
+// if (rangeend < 0 || rangeend > 255)
+// fatal("Protocols to be scanned must be between 0 and 255 inclusive");
+// } else {
+ if (rangeend < 0 || rangeend > 65535)
+ fatal("Ports to be scanned must be between 0 and 65535 inclusive");
+// }
+ current_range = endptr;
+ } else {
+ fatal("Error #486: Your port specifications are illegal. Example of proper form: \"%s\"", syntax_example);
+ }
+ if (rangeend < rangestart) {
+ //fatal("Your %s range %ld-%ld is backwards. Did you mean %ld-%ld?",
+ // (range_type & SCAN_PROTOCOLS) ? "protocol" : "port",
+ // rangestart, rangeend, rangeend, rangestart);
+ fatal("Your port range %ld-%ld is backwards. Did you mean %ld-%ld?",
+ rangestart, rangeend, rangeend, rangestart); // ADDED
+
+
+ }
+ } else {
+ fatal("Error #487: Your port specifications are illegal. Example of proper form: \"%s\"", syntax_example);
+ }
+
+ /* Now I have a rangestart and a rangeend, so I can add these ports */
+ while(rangestart <= rangeend) {
+ if (porttbl[rangestart]) {
+ if (!(*portwarning)) {
+ error("WARNING: Duplicate port number(s) specified. Are you alert enough to be using Nping? Have some coffee or grab a RedBull(tm).");
+ (*portwarning)++;
+ }
+ } else {
+ //if (nested) {
+ //if ((range_type & SCAN_TCP_PORT) &&
+ //nmap_getservbyport(rangestart, "tcp")) {
+ //porttbl[rangestart] |= SCAN_TCP_PORT;
+ //}
+ //if ((range_type & SCAN_UDP_PORT) &&
+ //nmap_getservbyport(rangestart, "udp")) {
+ //porttbl[rangestart] |= SCAN_UDP_PORT;
+ //}
+ //if ((range_type & SCAN_SCTP_PORT) &&
+ //nmap_getservbyport(rangestart, "sctp")) {
+ //porttbl[rangestart] |= SCAN_SCTP_PORT;
+ //}
+ //if ((range_type & SCAN_PROTOCOLS) &&
+ //nmap_getprotbynum(rangestart)) {
+ //porttbl[rangestart] |= SCAN_PROTOCOLS;
+ //}
+ //} else {
+ //porttbl[rangestart] |= range_type;
+ //}
+
+ porttbl[rangestart]=1; // ADDED for NPING
+ }
+ rangestart++;
+ }
+
+ /* Find the next range */
+ while(isspace((int) *current_range)) current_range++;
+
+ if (*current_range == ']') {
+ if (!nested) fatal("Unexpected ] character in port specification");
+ return;
+ }
+
+ if (*current_range && *current_range != ',') {
+ fatal("Error #488: Your port specifications are illegal. Example of proper form: \"%s\"", syntax_example);
+ }
+ if (*current_range == ',')
+ current_range++;
+ } while(current_range && *current_range);
+
+}
+/*****************************************************************************/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* For systems without SCTP in netinet/in.h, such as MacOS X */
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+
+
+
+
+/* IPv6 compatible version of Nmap's devname2ipaddr()
+ * @warning For this to work we need getinterfaces() not to skip IPv6 */
+int devname2ipaddr_alt(char *dev, struct sockaddr_storage *addr) {
+struct interface_info *mydevs;
+struct sockaddr_storage *s=NULL;
+struct sockaddr_in *s4=NULL;
+struct sockaddr_in6 *s6=NULL;
+int numdevs;
+int i;
+mydevs = getinterfaces(&numdevs, NULL, 0);
+
+if (!mydevs) return -1;
+
+if( !addr || !dev )
+ fatal("devname2ipaddr(): NULL values supplied.");
+
+ for(i=0; i < numdevs; i++) {
+ s=(struct sockaddr_storage *)&mydevs[i].addr;
+ s4=(struct sockaddr_in *)&mydevs[i].addr;
+ s6=(struct sockaddr_in6 *)&mydevs[i].addr;
+ if (s4->sin_family==AF_INET || s6->sin6_family==AF_INET6){
+ if (!strcmp(dev, mydevs[i].devfullname)) {
+ memcpy(addr, s, sizeof(struct sockaddr_storage));
+ return 0;
+ }
+ } else{ /* Unknown family, skipping it... */
+ continue;
+ }
+ }
+ return -1;
+
+} /* End of devname2ipaddr() */
+
+
+
+
+
+
+
+
+
diff --git a/nping/common_modified.h b/nping/common_modified.h
new file mode 100644
index 0000000..fa2b323
--- /dev/null
+++ b/nping/common_modified.h
@@ -0,0 +1,140 @@
+
+/***************************************************************************
+ * common_modified.h -- This file holds all those functions and classes *
+ * that have been reused from Nmap's code but that needed to be modified *
+ * in order to reuse them. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef COMMON_MODIFIED_H
+#define COMMON_MODIFIED_H 1
+
+#include "nping.h"
+#include "common.h"
+
+/*****************************************************************************
+ * STUFF FROM TargetGroup.h
+ ****************************************************************************/
+
+class TargetGroup {
+ public:
+ /* used by get_target_types */
+ enum _targets_types { TYPE_NONE, IPV4_NETMASK, IPV4_RANGES, IPV6_ADDRESS };
+ /* used as input to skip range */
+ enum _octet_nums { FIRST_OCTET, SECOND_OCTET, THIRD_OCTET };
+ TargetGroup();
+
+ /* Initializes (or reinitializes) the object with a new expression,
+ such as 192.168.0.0/16 , 10.1.0-5.1-254 , or
+ fe80::202:e3ff:fe14:1102 . The af parameter is AF_INET or
+ AF_INET6 Returns 0 for success */
+ int parse_expr(const char * const target_expr, int af);
+ /* Reset the object without reinitializing it */
+ int rewind();
+ /* Grab the next host from this expression (if any). Returns 0 and
+ fills in ss if successful. ss must point to a pre-allocated
+ sockaddr_storage structure */
+ int get_next_host(struct sockaddr_storage *ss, size_t *sslen);
+ /* Returns the last given host, so that it will be given again next
+ time get_next_host is called. Obviously, you should only call
+ this if you have fetched at least 1 host since parse_expr() was
+ called */
+ int return_last_host();
+ /* return the target type */
+ char get_targets_type() {return targets_type;};
+ /* get the netmask */
+ int get_mask() {return netmask;};
+ /* is the current expression a named host */
+ int get_namedhost() {return namedhost;};
+ /* Skip an octet in the range array */
+ int skip_range(_octet_nums octet);
+ private:
+ enum _targets_types targets_type;
+ void Initialize();
+
+#if HAVE_IPV6
+ struct sockaddr_in6 ip6;
+#endif
+
+ /* These 4 are used for the '/mask' style of specifying target
+ net (IPV4_NETMASK) */
+ u32 netmask;
+ struct in_addr startaddr;
+ struct in_addr currentaddr;
+ struct in_addr endaddr;
+
+ // These three are for the '138.[1-7,16,91-95,200-].12.1' style (IPV4_RANGES)
+ u8 addresses[4][256];
+ unsigned int current[4];
+ u8 last[4];
+
+/* Number of IPs left in this structure -- set to 0 if
+ the fields are not valid */
+ unsigned long long ipsleft;
+
+ // is the current target expression a named host
+ int namedhost;
+};
+
+
+
+/*****************************************************************************
+ * STUFF FROM tcpip.cc
+ ****************************************************************************/
+int devname2ipaddr_alt(char *dev, struct sockaddr_storage *addr);
+void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int *portwarning);
+
+#endif
diff --git a/nping/config.guess b/nping/config.guess
new file mode 100755
index 0000000..dbfb978
--- /dev/null
+++ b/nping/config.guess
@@ -0,0 +1,1421 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2015 Free Software Foundation, Inc.
+
+timestamp='2015-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2015 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo ${UNAME_MACHINE}-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ cris:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ exit ;;
+ frv:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ hexagon:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:Linux:*:*)
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-${LIBC}
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-${LIBC}
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+ PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+ *) echo hppa-unknown-linux-${LIBC} ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-${LIBC}
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-${LIBC}
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-${LIBC}
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-${LIBC}
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ exit ;;
+ x86_64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval $set_cc_for_build
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/nping/config.sub b/nping/config.sub
new file mode 100755
index 0000000..6d2e94c
--- /dev/null
+++ b/nping/config.sub
@@ -0,0 +1,1807 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2015 Free Software Foundation, Inc.
+
+timestamp='2015-01-01'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2015 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+ | avr | avr32 \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | we32k \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pyramid-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/nping/configure b/nping/configure
new file mode 100755
index 0000000..940996f
--- /dev/null
+++ b/nping/configure
@@ -0,0 +1,7714 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="nping.cc"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+enable_option_checking=no
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+DNET_DIST_CLEAN
+DNET_CLEAN
+DNET_BUILD
+DNET_DEPENDS
+LIBDNETDIR
+LIBDNET_LIBS
+subdirs
+LIBPCAP_LIBS
+PCAP_DIST_CLEAN
+PCAP_CLEAN
+PCAP_BUILD
+PCAP_DEPENDS
+OPENSSL_LIBS
+EGREP
+GREP
+CPP
+STRIP
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+pcredir
+libpcapdir
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_localdirs
+with_openssl
+with_libpcap
+with_libdnet
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+ac_subdirs_all='libpcap
+libdnet-stripped '
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-localdirs Explicitly ask compiler to use
+ /usr/local/{include,libs} if they exist
+ --with-openssl=DIR Use optional openssl libs and includes from
+ [DIR]/lib/ and [DIR]/include/openssl/)
+ --with-libpcap=DIR Look for pcap in DIR/include and DIR/libs.
+ --with-libpcap=included Always use version included with Nmap
+ --with-libdnet=DIR Use an existing (compiled) dnet lib from DIR/include
+ and DIR/lib.
+ --with-libdnet=included Use the libdnet version included with Nmap (default)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-localdirs was given.
+if test "${with_localdirs+set}" = set; then :
+ withval=$with_localdirs; case "$with_localdirs" in
+ yes)
+ user_localdirs=1
+ ;;
+ no)
+ user_localdirs=0
+ ;;
+ esac
+
+else
+ user_localdirs=0
+fi
+
+
+if test "$user_localdirs" = 1; then
+ if test -d /usr/local/lib; then
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ fi
+ if test -d /usr/local/include; then
+ CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+ fi
+fi
+
+libpcapdir=../libpcap
+
+
+pcredir=libpcre
+
+
+ac_config_headers="$ac_config_headers nping_config.h"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+ if test -n "$GXX"; then
+ CXXFLAGS="$CXXFLAGS -Wall "
+ fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler is gcc 4 or greater" >&5
+$as_echo_n "checking whether the compiler is gcc 4 or greater... " >&6; }
+if test x"$GXX" = xno; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+ # On some distros, there are snapshots available as gcc4
+ if test -z "$ac_cv_prog_CC" || test x"$CC" = xgcc4; then
+ our_gcc="$CC"
+ else
+ our_gcc="$ac_cv_prog_CC"
+ fi
+
+ nping_gcc_major_version=0
+ case `$our_gcc --version | sed -e 's,\..*,.,' -e q` in
+ *4.)
+ nping_gcc_major_version=4
+ ;;
+ esac
+
+ if test 4 -ge $nping_gcc_major_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+fi
+
+# Remember that all following tests will run with this CXXFLAGS by default
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __func__" >&5
+$as_echo_n "checking for __func__... " >&6; }
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+
+int
+main ()
+{
+printf ("%s", __func__);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ have_func=yes
+else
+ have_func=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x$have_func" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __FUNCTION__" >&5
+$as_echo_n "checking for __FUNCTION__... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+
+int
+main ()
+{
+printf ("%s", __FUNCTION__);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ have_function=yes
+else
+ have_function=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test "x$have_function" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ $as_echo "#define __func__ __FUNCTION__" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ $as_echo "#define __func__ __FILE__" >>confdefs.h
+
+ fi
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $STRIP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_STRIP="$STRIP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+STRIP=$ac_cv_path_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_STRIP"; then
+ ac_pt_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_STRIP in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_STRIP="$ac_pt_STRIP" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_STRIP="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_STRIP=$ac_cv_path_ac_pt_STRIP
+if test -n "$ac_pt_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_STRIP" >&5
+$as_echo "$ac_pt_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_STRIP" = x; then
+ STRIP="/bin/true"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_pt_STRIP
+ fi
+else
+ STRIP="$ac_cv_path_STRIP"
+fi
+
+
+needs_cpp_precomp=no
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in pwd.h termios.h sys/sockio.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setsockopt" >&5
+$as_echo_n "checking for library containing setsockopt... " >&6; }
+if ${ac_cv_search_setsockopt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char setsockopt ();
+int
+main ()
+{
+return setsockopt ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_setsockopt=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_setsockopt+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_setsockopt+:} false; then :
+
+else
+ ac_cv_search_setsockopt=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_setsockopt" >&5
+$as_echo "$ac_cv_search_setsockopt" >&6; }
+ac_res=$ac_cv_search_setsockopt
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if ${ac_cv_search_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_gethostbyname+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_gethostbyname+:} false; then :
+
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+# OpenSSL and NSE C modules can require dlopen
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_dlopen+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+# libpcap can require libnl
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nl_handle_alloc" >&5
+$as_echo_n "checking for library containing nl_handle_alloc... " >&6; }
+if ${ac_cv_search_nl_handle_alloc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_handle_alloc ();
+int
+main ()
+{
+return nl_handle_alloc ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_nl_handle_alloc=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_nl_handle_alloc+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_nl_handle_alloc+:} false; then :
+
+else
+ ac_cv_search_nl_handle_alloc=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nl_handle_alloc" >&5
+$as_echo "$ac_cv_search_nl_handle_alloc" >&6; }
+ac_res=$ac_cv_search_nl_handle_alloc
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+# We test whether they specified openssl desires explicitly
+use_openssl="yes"
+specialssldir=""
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then :
+ withval=$with_openssl; case "$with_openssl" in
+ yes)
+ ;;
+ no)
+ use_openssl="no"
+ ;;
+ *)
+ specialssldir="$with_openssl"
+ CPPFLAGS="$CPPFLAGS -I$with_openssl/include"
+ LDFLAGS="$LDFLAGS -L$with_openssl/lib"
+ ;;
+ esac
+
+fi
+
+
+# If they didn't specify it, we try to find it
+if test "$use_openssl" = "yes" -a -z "$specialssldir"; then
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
+
+else
+ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ as_fn_error $? "OpenSSL was explicitly requested but openssl/ssl.h was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl." "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find openssl/ssl.h so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find openssl/ssl.h so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&2;}
+
+fi
+
+
+
+# use_openssl="yes" given explicitly in next 2 rules to avoid adding lib to $LIBS
+ if test "$use_openssl" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_int_ctrl in -lcrypto" >&5
+$as_echo_n "checking for BIO_int_ctrl in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_BIO_int_ctrl+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char BIO_int_ctrl ();
+int
+main ()
+{
+return BIO_int_ctrl ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_crypto_BIO_int_ctrl=yes
+else
+ ac_cv_lib_crypto_BIO_int_ctrl=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_int_ctrl" >&5
+$as_echo "$ac_cv_lib_crypto_BIO_int_ctrl" >&6; }
+if test "x$ac_cv_lib_crypto_BIO_int_ctrl" = xyes; then :
+ use_openssl="yes"
+else
+ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ as_fn_error $? "OpenSSL was explicitly requested but libcrypto was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl." "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libcrypto so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find libcrypto so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&2;}
+
+fi
+
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5
+$as_echo_n "checking for SSL_new in -lssl... " >&6; }
+if ${ac_cv_lib_ssl_SSL_new+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char SSL_new ();
+int
+main ()
+{
+return SSL_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ssl_SSL_new=yes
+else
+ ac_cv_lib_ssl_SSL_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5
+$as_echo "$ac_cv_lib_ssl_SSL_new" >&6; }
+if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then :
+ use_openssl="yes"
+else
+ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ as_fn_error $? "OpenSSL was explicitly requested but libssl was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl." "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Failed to find libssl so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&5
+$as_echo "$as_me: WARNING: Failed to find libssl so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument" >&2;}
+fi
+
+ fi
+fi
+
+OPENSSL_LIBS=
+if test "$use_openssl" = "yes"; then
+
+$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ OPENSSL_LIBS="-lssl -lcrypto"
+ LIBS_TMP="$LIBS"
+ LIBS="$OPENSSL_LIBS $LIBS"
+ # Check whether the installed OpenSSL supports SHA-256 (ver 0.9.8 or later).
+ ac_fn_c_check_func "$LINENO" "EVP_sha256" "ac_cv_func_EVP_sha256"
+if test "x$ac_cv_func_EVP_sha256" = xyes; then :
+
+else
+ as_fn_error $? "Your version of OpenSSL does not support SHA-256. Please install OpenSSL 0.9.8 or later." "$LINENO" 5
+fi
+
+ LIBS="$LIBS_TMP"
+fi
+
+
+
+have_libpcap=no
+
+# By default, search for pcap library
+test "${with_libpcap+set}" != "set" && with_libpcap=yes
+
+
+# Check whether --with-libpcap was given.
+if test "${with_libpcap+set}" = set; then :
+ withval=$with_libpcap; case "$with_libpcap" in
+ yes)
+ ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_create in -lpcap" >&5
+$as_echo_n "checking for pcap_create in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_create ();
+int
+main ()
+{
+return pcap_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_create=yes
+else
+ ac_cv_lib_pcap_pcap_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_create" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_create" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_create" = xyes; then :
+ have_libpcap=yes
+fi
+
+fi
+
+
+ ;;
+ included)
+ have_libpcap=no
+ ;;
+ *)
+ _cppflags=$CPPFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$with_libpcap/include $CPPFLAGS"
+ LDFLAGS="-L$with_libpcap/lib $LDFLAGS"
+
+ ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_h" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_create in -lpcap" >&5
+$as_echo_n "checking for pcap_create in -lpcap... " >&6; }
+if ${ac_cv_lib_pcap_pcap_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pcap_create ();
+int
+main ()
+{
+return pcap_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pcap_pcap_create=yes
+else
+ ac_cv_lib_pcap_pcap_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_create" >&5
+$as_echo "$ac_cv_lib_pcap_pcap_create" >&6; }
+if test "x$ac_cv_lib_pcap_pcap_create" = xyes; then :
+ have_libpcap=yes
+ LIBPCAP_INC=$with_libpcap/include
+ LIBPCAP_LIB=$with_libpcap/lib
+fi
+
+fi
+
+
+
+ LDFLAGS=$_ldflags
+ CPPFLAGS=$_cppflags
+ ;;
+ esac
+
+fi
+
+
+if test $needs_cpp_precomp = yes; then
+ CXXFLAGS="-no-cpp-precomp $CXXFLAGS"
+fi
+
+if test $have_libpcap = yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ CPPFLAGS="-I$LIBPCAP_INC $CPPFLAGS"
+ LDFLAGS="-L$LIBPCAP_LIB $LDFLAGS"
+ fi
+
+ # link with -lpcap for the purposes of this test
+ LIBS_OLD="$LIBS"
+ LIBS="$LIBS -lpcap"
+
+ for ac_header in sys/ioccom.h sys/time.h net/bpf.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libpcap is suitable" >&5
+$as_echo_n "checking if libpcap is suitable... " >&6; }
+ if test "$cross_compiling" = yes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling -- assuming yes" >&5
+$as_echo "cross-compiling -- assuming yes" >&6; }; have_libpcap=yes
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+extern char pcap_version[];
+int main() {
+ int major, minor1, minor2;
+ sscanf(pcap_version,"%d.%d.%d", &major, &minor1, &minor2);
+ if (major > 0)
+ return 0;
+ if (minor1 < 9)
+ return 1;
+ if (minor2 < 4)
+ return 1;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_NET_BPF_H
+#include <net/bpf.h>
+#endif
+extern char pcap_version[];
+int main() {
+ int major, minor;
+ sscanf(pcap_version,"%d.%d", &major, &minor);
+ if ((major == 1 && minor >= 1) || major > 1)
+ return 0;
+#ifdef BIOCSRTIMEOUT
+#ifdef IOCPARM_LEN
+ if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval))
+ return 1;
+#endif
+#endif
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+ ac_fn_c_check_decl "$LINENO" "pcap_get_selectable_fd" "ac_cv_have_decl_pcap_get_selectable_fd" "#include <pcap.h>
+"
+if test "x$ac_cv_have_decl_pcap_get_selectable_fd" = xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }; have_libpcap=yes
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- pcap_get_selectable_fd not declared" >&5
+$as_echo "no -- pcap_get_selectable_fd not declared" >&6; }; have_libpcap=no
+fi
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no -- BPF_TIMEOUT BIOCSRTIMEOUT bug (64-bit OS X)" >&5
+$as_echo "no -- BPF_TIMEOUT BIOCSRTIMEOUT bug (64-bit OS X)" >&6; }; have_libpcap=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }; have_libpcap=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+ LIBS="$LIBS_OLD"
+fi
+
+if test $have_libpcap != yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ LDFLAGS="-L$libpcapdir $_ldflags"
+ CPPFLAGS="$CPPFLAGS -I$LIBPCAP_INC"
+ else
+ LDFLAGS="-L$libpcapdir $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$libpcapdir"
+ fi
+ LIBPCAP_LIBS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_DEPENDS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_BUILD="build-pcap"
+ PCAP_CLEAN="clean-pcap"
+ PCAP_DIST_CLEAN="distclean-pcap"
+else
+
+$as_echo "#define HAVE_LIBPCAP 1" >>confdefs.h
+
+ LIBPCAP_LIBS="-lpcap"
+ PCAP_DEPENDS=""
+ PCAP_BUILD=""
+ PCAP_CLEAN=""
+ PCAP_DIST_CLEAN=""
+fi
+
+
+
+
+
+
+
+if test $have_libpcap != yes ; then
+
+
+subdirs="$subdirs libpcap"
+
+fi
+
+
+have_dnet=no
+requested_included_dnet=no
+LIBDNETDIR=../libdnet-stripped
+
+# First we test whether they specified libdnet explicitly.
+# Unlike the other included libraries (pcap, pcre, lua), we prefer our local
+# copy of libdnet. That is, with the other libraries we check for a system
+# version by default, whereas with dnet we use the local version unless
+# specifically asked to use a system version.
+
+# Check whether --with-libdnet was given.
+if test "${with_libdnet+set}" = set; then :
+ withval=$with_libdnet; case "$with_libdnet" in
+ yes)
+ ;;
+ included)
+ ;;
+ *)
+ CPPFLAGS="-I$with_libdnet/include $CPPFLAGS"
+ LDFLAGS="-L$with_libdnet/lib $LDFLAGS"
+ have_dnet=yes
+ ;;
+ esac
+
+fi
+
+
+# If they didn't provide location, we use the included one
+if test $have_dnet != yes ; then
+ subdirs="$subdirs libdnet-stripped"
+
+ CPPFLAGS="-I$LIBDNETDIR/include $CPPFLAGS"
+ LIBDNET_LIBS="$LIBDNETDIR/src/.libs/libdnet.a"
+ DNET_DEPENDS="$LIBDNETDIR/src/.libs/libdnet.a"
+ DNET_BUILD="build-dnet"
+ DNET_CLEAN="clean-dnet"
+ DNET_DIST_CLEAN="distclean-dnet"
+else
+ LIBDNET_LIBS="-ldnet"
+ DNET_DEPENDS=""
+ DNET_BUILD=""
+ DNET_CLEAN=""
+ DNET_DIST_CLEAN=""
+fi
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr{} has sa_len member" >&5
+$as_echo_n "checking if sockaddr{} has sa_len member... " >&6; }
+if ${ac_cv_sockaddr_has_sa_len+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+unsigned int i = sizeof(((struct sockaddr *)0)->sa_len)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sockaddr_has_sa_len=yes
+else
+ ac_cv_sockaddr_has_sa_len=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sockaddr_has_sa_len" >&5
+$as_echo "$ac_cv_sockaddr_has_sa_len" >&6; }
+if test $ac_cv_sockaddr_has_sa_len = yes ; then
+
+$as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in{} has sin_len member" >&5
+$as_echo_n "checking if sockaddr_in{} has sin_len member... " >&6; }
+if ${ac_cv_sockaddr_in_has_sin_len+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+unsigned int i = sizeof(((struct sockaddr_in *)0)->sin_len)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sockaddr_in_has_sin_len=yes
+else
+ ac_cv_sockaddr_in_has_sin_len=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sockaddr_in_has_sin_len" >&5
+$as_echo "$ac_cv_sockaddr_in_has_sin_len" >&6; }
+if test $ac_cv_sockaddr_in_has_sin_len = yes ; then
+
+$as_echo "#define HAVE_SOCKADDR_IN_SIN_LEN 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr_in6{} has sin6_len member" >&5
+$as_echo_n "checking if sockaddr_in6{} has sin6_len member... " >&6; }
+if ${ac_cv_sockaddr_in6_has_sin6_len+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+unsigned int i = sizeof(((struct sockaddr_in6 *)0)->sin6_len)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sockaddr_in6_has_sin6_len=yes
+else
+ ac_cv_sockaddr_in6_has_sin6_len=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sockaddr_in6_has_sin6_len" >&5
+$as_echo "$ac_cv_sockaddr_in6_has_sin6_len" >&6; }
+if test $ac_cv_sockaddr_in6_has_sin6_len = yes ; then
+
+$as_echo "#define HAVE_SOCKADDR_IN6_SIN6_LEN 1" >>confdefs.h
+
+fi
+
+
+#dnl check endedness
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct in_addr is a wacky huge structure (some Sun boxes)" >&5
+$as_echo_n "checking if struct in_addr is a wacky huge structure (some Sun boxes)... " >&6; }
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netinet/in.h>
+int
+main ()
+{
+struct in_addr i; i._S_un._S_addr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ \
+ $as_echo "#define IN_ADDR_DEEPSTRUCT 1" >>confdefs.h
+ \
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ \
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <netinet/in.h>
+int
+main ()
+{
+struct in_addr i; i.S_un.S_addr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ \
+ $as_echo "#define IN_ADDR_DEEPSTRUCT 1" >>confdefs.h
+ \
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ \
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; };
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+#AC_CACHE_CHECK(if struct icmp exists, ac_cv_struct_icmp_exists,
+ #AC_TRY_COMPILE([
+ ##include <sys/types.h>
+ ##include <sys/param.h>
+ ##include <netinet/in_systm.h>
+ ##include <netinet/in.h>
+ ##define __USE_BSD
+ ##define __FAVOR_BSD
+ ##define _BSD_SOURCE
+ ##include <netinet/ip.h>
+ ##include <netinet/ip_icmp.h>],
+ #[unsigned int i = sizeof(struct icmp)],
+ #ac_cv_struct_icmp_exists=yes,
+ #ac_cv_struct_icmp_exists=no))
+#if test $ac_cv_struct_icmp_exists = yes ; then
+ #AC_DEFINE(HAVE_STRUCT_ICMP)
+#fi
+
+#AC_CACHE_CHECK(if struct ip exists, ac_cv_struct_ip_exists,
+ #AC_TRY_COMPILE([
+ ##include <sys/types.h>
+ ##include <sys/param.h>
+ ##include <netinet/in_systm.h>
+ ##include <netinet/in.h>
+ ##define __USE_BSD
+ ##define __FAVOR_BSD
+ ##define _BSD_SOURCE
+ ##include <netinet/ip.h>],
+ #[unsigned int i = sizeof(struct ip)],
+ #ac_cv_struct_ip_exists=yes,
+ #ac_cv_struct_ip_exists=no))
+#if test $ac_cv_struct_ip_exists = yes ; then
+ #AC_DEFINE(HAVE_STRUCT_IP)
+#fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if struct ip has ip_sum member" >&5
+$as_echo_n "checking if struct ip has ip_sum member... " >&6; }
+if ${ac_cv_ip_has_ip_sum+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #define __USE_BSD
+ #define __FAVOR_BSD
+ #define _BSD_SOURCE
+ #include <netinet/ip.h>
+ #include <netinet/ip_icmp.h>
+int
+main ()
+{
+unsigned int i = sizeof(((struct ip *)0)->ip_sum)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_ip_has_ip_sum=yes
+else
+ ac_cv_ip_has_ip_sum=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ip_has_ip_sum" >&5
+$as_echo "$ac_cv_ip_has_ip_sum" >&6; }
+if test $ac_cv_ip_has_ip_sum = yes ; then
+
+$as_echo "#define HAVE_IP_IP_SUM 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if function signal is accessible" >&5
+$as_echo_n "checking if function signal is accessible... " >&6; }
+if ${ac_cv_have_signal+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <signal.h>
+
+int
+main ()
+{
+
+ void handler(int signo){
+ int a=0;
+ }
+
+ int main () {
+ ssignal(SIGINT, handler);
+ return 0;
+ }
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_have_signal=yes
+else
+ ac_cv_have_signal=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_signal" >&5
+$as_echo "$ac_cv_have_signal" >&6; }
+if test $ac_cv_have_signal = yes ; then
+
+$as_echo "#define HAVE_SIGNAL 1" >>confdefs.h
+
+fi
+
+
+
+
+
+
+case "$host" in
+ *alpha-dec-osf*)
+
+$as_echo "#define DEC 1" >>confdefs.h
+
+ ;;
+ *-netbsd* | *-knetbsd*-gnu)
+
+$as_echo "#define NETBSD 1" >>confdefs.h
+
+ ;;
+ *-openbsd*)
+
+$as_echo "#define OPENBSD 1" >>confdefs.h
+
+ ;;
+ *-freebsd* | *-kfreebsd*-gnu | *-dragonfly*)
+
+$as_echo "#define FREEBSD 1" >>confdefs.h
+
+ ;;
+ *-bsdi*)
+
+$as_echo "#define BSDI 1" >>confdefs.h
+
+ ;;
+ *-sgi-irix5* | *-sgi-irix6*)
+
+$as_echo "#define IRIX 1" >>confdefs.h
+
+ ;;
+ *-hpux*)
+
+$as_echo "#define HPUX 1" >>confdefs.h
+
+ # To link with libnet and NM (/usr/lib/libnm.sl) library
+ # on HP-UX 11.11 (other versions?) Mikhail Zakharov (zmey20000@yahoo.com)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for open_mib in -lnm" >&5
+$as_echo_n "checking for open_mib in -lnm... " >&6; }
+if ${ac_cv_lib_nm_open_mib+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char open_mib ();
+int
+main ()
+{
+return open_mib ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nm_open_mib=yes
+else
+ ac_cv_lib_nm_open_mib=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nm_open_mib" >&5
+$as_echo "$ac_cv_lib_nm_open_mib" >&6; }
+if test "x$ac_cv_lib_nm_open_mib" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNM 1
+_ACEOF
+
+ LIBS="-lnm $LIBS"
+
+fi
+
+ ;;
+ *-aix*)
+ # use some AIX specific libraries
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for odm_initialize in -lodm" >&5
+$as_echo_n "checking for odm_initialize in -lodm... " >&6; }
+if ${ac_cv_lib_odm_odm_initialize+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lodm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char odm_initialize ();
+int
+main ()
+{
+return odm_initialize ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_odm_odm_initialize=yes
+else
+ ac_cv_lib_odm_odm_initialize=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_odm_odm_initialize" >&5
+$as_echo "$ac_cv_lib_odm_odm_initialize" >&6; }
+if test "x$ac_cv_lib_odm_odm_initialize" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBODM 1
+_ACEOF
+
+ LIBS="-lodm $LIBS"
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _system_configuration in -lcfg" >&5
+$as_echo_n "checking for _system_configuration in -lcfg... " >&6; }
+if ${ac_cv_lib_cfg__system_configuration+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcfg $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _system_configuration ();
+int
+main ()
+{
+return _system_configuration ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_cfg__system_configuration=yes
+else
+ ac_cv_lib_cfg__system_configuration=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cfg__system_configuration" >&5
+$as_echo "$ac_cv_lib_cfg__system_configuration" >&6; }
+if test "x$ac_cv_lib_cfg__system_configuration" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCFG 1
+_ACEOF
+
+ LIBS="-lcfg $LIBS"
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt_r in -lcrypt" >&5
+$as_echo_n "checking for crypt_r in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt_r+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt_r ();
+int
+main ()
+{
+return crypt_r ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_crypt_crypt_r=yes
+else
+ ac_cv_lib_crypt_crypt_r=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt_r" >&5
+$as_echo "$ac_cv_lib_crypt_crypt_r" >&6; }
+if test "x$ac_cv_lib_crypt_crypt_r" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPT 1
+_ACEOF
+
+ LIBS="-lcrypt $LIBS"
+
+fi
+
+ ;;
+ *-solaris2.0*)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.[1-9][0-9]*)
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.1*)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.2*)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.3*)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.4*)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris2.5.1)
+ $as_echo "#define STUPID_SOLARIS_CHECKSUM_BUG 1" >>confdefs.h
+
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-solaris*)
+ $as_echo "#define SOLARIS 1" >>confdefs.h
+
+ ;;
+ *-sunos4*)
+
+$as_echo "#define SUNOS 1" >>confdefs.h
+
+
+$as_echo "#define SPRINTF_RETURNS_STRING 1" >>confdefs.h
+
+ ;;
+ *-linux*)
+
+$as_echo "#define LINUX 1" >>confdefs.h
+
+ ;;
+ *-apple-darwin*)
+
+$as_echo "#define MACOSX 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5
+$as_echo_n "checking for main in -lm... " >&6; }
+if ${ac_cv_lib_m_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_m_main=yes
+else
+ ac_cv_lib_m_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5
+$as_echo "$ac_cv_lib_m_main" >&6; }
+if test "x$ac_cv_lib_m_main" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+ LIBS="-lm $LIBS"
+
+fi
+
+ needs_cpp_precomp=yes
+ ;;
+esac
+
+
+
+
+
+
+
+for ac_func in strerror
+do :
+ ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+done
+
+#RECVFROM_ARG6_TYPE
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "nping_config.h") CONFIG_HEADERS="$CONFIG_HEADERS nping_config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+
+#
+# CONFIG_SUBDIRS section.
+#
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file, --srcdir, and --disable-option-checking arguments
+ # so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ eval "set x $ac_configure_args"
+ shift
+ for ac_arg
+ do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case $ac_arg in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* \
+ | --c=*)
+ ;;
+ --config-cache | -C)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ ;;
+ --disable-option-checking)
+ ;;
+ *)
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_sub_configure_args " '$ac_arg'" ;;
+ esac
+ done
+
+ # Always prepend --prefix to ensure using the same prefix
+ # in subdir configurations.
+ ac_arg="--prefix=$prefix"
+ case $ac_arg in
+ *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args"
+
+ # Pass --silent
+ if test "$silent" = yes; then
+ ac_sub_configure_args="--silent $ac_sub_configure_args"
+ fi
+
+ # Always prepend --disable-option-checking to silence warnings, since
+ # different subdirs can have different --enable and --with options.
+ ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args"
+
+ ac_popdir=`pwd`
+ for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ test -d "$srcdir/$ac_dir" || continue
+
+ ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
+ $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5
+ $as_echo "$ac_msg" >&6
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ cd "$ac_dir"
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ ac_sub_configure=$ac_srcdir/configure.gnu
+ elif test -f "$ac_srcdir/configure"; then
+ ac_sub_configure=$ac_srcdir/configure
+ elif test -f "$ac_srcdir/configure.in"; then
+ # This should be Cygnus configure.
+ ac_sub_configure=$ac_aux_dir/configure
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5
+$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+ # Make the cache file name correct relative to the subdirectory.
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
+ *) # Relative name.
+ ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+ # The eval makes quoting arguments work.
+ eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
+ --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+ as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5
+ fi
+
+ cd "$ac_popdir"
+ done
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+# Some ASCII ART#!#@$!@#$
+if test -f docs/leet-nping-ascii-art.txt; then
+ cat docs/leet-nping-ascii-art.txt
+fi
+echo "Configuration complete. Type make (or gmake on some *BSD machines) to compile."
diff --git a/nping/configure.ac b/nping/configure.ac
new file mode 100644
index 0000000..00c3ec4
--- /dev/null
+++ b/nping/configure.ac
@@ -0,0 +1,562 @@
+# Require autoconf 2.13 -*- mode: fundamental; -*-
+AC_PREREQ(2.13)
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(nping.cc)
+
+m4_include([../acinclude.m4])
+
+AC_ARG_WITH(localdirs,
+AC_HELP_STRING([--with-localdirs], [Explicitly ask compiler to use /usr/local/{include,libs} if they exist ]),
+ [ case "$with_localdirs" in
+ yes)
+ user_localdirs=1
+ ;;
+ no)
+ user_localdirs=0
+ ;;
+ esac
+ ],
+ [ user_localdirs=0 ] )
+
+if test "$user_localdirs" = 1; then
+ if test -d /usr/local/lib; then
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+ fi
+ if test -d /usr/local/include; then
+ CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+ fi
+fi
+
+libpcapdir=../libpcap
+AC_SUBST(libpcapdir)
+
+pcredir=libpcre
+AC_SUBST(pcredir)
+
+dnl use nping_config.h instead of -D macros
+AC_CONFIG_HEADER(nping_config.h)
+
+dnl Host specific hacks
+AC_CANONICAL_HOST
+AC_C_INLINE
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+
+ if test -n "$GXX"; then
+ CXXFLAGS="$CXXFLAGS -Wall "
+ fi
+
+AC_MSG_CHECKING([whether the compiler is gcc 4 or greater])
+if test x"$GXX" = xno; then
+ AC_MSG_RESULT([no])
+else
+ # On some distros, there are snapshots available as gcc4
+ if test -z "$ac_cv_prog_CC" || test x"$CC" = xgcc4; then
+ our_gcc="$CC"
+ else
+ our_gcc="$ac_cv_prog_CC"
+ fi
+
+ nping_gcc_major_version=0
+ case `$our_gcc --version | sed -e 's,\..*,.,' -e q` in
+ *4.)
+ nping_gcc_major_version=4
+ ;;
+ esac
+
+ if test 4 -ge $nping_gcc_major_version; then
+ AC_MSG_RESULT([yes])
+ CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
+ else
+ AC_MSG_RESULT([no])
+ fi
+fi
+
+# Remember that all following tests will run with this CXXFLAGS by default
+AC_MSG_CHECKING(for __func__)
+AH_TEMPLATE(__func__, [C99-specified function identifier])
+AC_TRY_COMPILE([
+#include <stdio.h>
+],[printf ("%s", __func__);],
+have_func=yes, have_func=no)
+if test "x$have_func" = "xyes"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+ AC_MSG_CHECKING(for __FUNCTION__)
+ AC_TRY_COMPILE([
+#include <stdio.h>
+],[printf ("%s", __FUNCTION__);],
+have_function=yes, have_function=no)
+ if test "x$have_function" = "xyes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(__func__, __FUNCTION__)
+ else
+ AC_MSG_RESULT(no)
+ AC_DEFINE(__func__, __FILE__)
+ fi
+fi
+
+AC_PATH_TOOL([STRIP], [strip], [/bin/true])
+
+needs_cpp_precomp=no
+
+dnl Checks for header files.
+AC_CHECK_HEADERS(pwd.h termios.h sys/sockio.h)
+
+dnl If any socket libraries needed
+AC_SEARCH_LIBS(setsockopt, socket)
+AC_SEARCH_LIBS(gethostbyname, nsl)
+
+# OpenSSL and NSE C modules can require dlopen
+AC_SEARCH_LIBS(dlopen, dl)
+
+# libpcap can require libnl
+AC_SEARCH_LIBS(nl_handle_alloc, nl)
+
+# We test whether they specified openssl desires explicitly
+use_openssl="yes"
+specialssldir=""
+AC_ARG_WITH(openssl,
+AC_HELP_STRING([--with-openssl=DIR],[Use optional openssl libs and includes from [DIR]/lib/ and [DIR]/include/openssl/)]),
+[ case "$with_openssl" in
+ yes)
+ ;;
+ no)
+ use_openssl="no"
+ ;;
+ *)
+ specialssldir="$with_openssl"
+ CPPFLAGS="$CPPFLAGS -I$with_openssl/include"
+ LDFLAGS="$LDFLAGS -L$with_openssl/lib"
+ ;;
+ esac]
+)
+
+# If they didn't specify it, we try to find it
+if test "$use_openssl" = "yes" -a -z "$specialssldir"; then
+ AC_CHECK_HEADER(openssl/ssl.h,,
+ [ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ AC_MSG_ERROR([OpenSSL was explicitly requested but openssl/ssl.h was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl.])
+ fi
+ AC_MSG_WARN([Failed to find openssl/ssl.h so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument])
+ ])
+
+# use_openssl="yes" given explicitly in next 2 rules to avoid adding lib to $LIBS
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_LIB(crypto, BIO_int_ctrl,
+ [ use_openssl="yes"],
+ [ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ AC_MSG_ERROR([OpenSSL was explicitly requested but libcrypto was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl.])
+ fi
+ AC_MSG_WARN([Failed to find libcrypto so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument])
+ ])
+ fi
+
+ if test "$use_openssl" = "yes"; then
+ AC_CHECK_LIB(ssl, SSL_new,
+ [ use_openssl="yes" ],
+ [ use_openssl="no"
+ if test "$with_openssl" = "yes"; then
+ AC_MSG_ERROR([OpenSSL was explicitly requested but libssl was not found. Try the --with-openssl=DIR argument to give the location of OpenSSL or run configure with --without-openssl.])
+ fi
+ AC_MSG_WARN([Failed to find libssl so OpenSSL will not be used. If it is installed you can try the --with-openssl=DIR argument]) ],
+ [ -lcrypto ])
+ fi
+fi
+
+OPENSSL_LIBS=
+if test "$use_openssl" = "yes"; then
+ AC_DEFINE(HAVE_OPENSSL, 1, [Have OpenSSL library])
+ OPENSSL_LIBS="-lssl -lcrypto"
+ LIBS_TMP="$LIBS"
+ LIBS="$OPENSSL_LIBS $LIBS"
+ # Check whether the installed OpenSSL supports SHA-256 (ver 0.9.8 or later).
+ AC_CHECK_FUNC(EVP_sha256,, AC_MSG_ERROR([Your version of OpenSSL does not support SHA-256. Please install OpenSSL 0.9.8 or later.]))
+ LIBS="$LIBS_TMP"
+fi
+
+AC_SUBST(OPENSSL_LIBS)
+
+dnl Check whether libpcap is already available
+have_libpcap=no
+
+# By default, search for pcap library
+test "${with_libpcap+set}" != "set" && with_libpcap=yes
+
+AC_ARG_WITH(libpcap,
+AC_HELP_STRING([--with-libpcap=DIR], [Look for pcap in DIR/include and DIR/libs.])
+AC_HELP_STRING([--with-libpcap=included], [Always use version included with Nmap]),
+[ case "$with_libpcap" in
+ yes)
+ AC_CHECK_HEADER(pcap.h,[
+ AC_CHECK_LIB(pcap, pcap_create,
+ [have_libpcap=yes ])])
+ ;;
+ included)
+ have_libpcap=no
+ ;;
+ *)
+ _cppflags=$CPPFLAGS
+ _ldflags=$LDFLAGS
+
+ CPPFLAGS="-I$with_libpcap/include $CPPFLAGS"
+ LDFLAGS="-L$with_libpcap/lib $LDFLAGS"
+
+ AC_CHECK_HEADER(pcap.h,[
+ AC_CHECK_LIB(pcap, pcap_create,
+ [have_libpcap=yes
+ LIBPCAP_INC=$with_libpcap/include
+ LIBPCAP_LIB=$with_libpcap/lib])])
+
+ LDFLAGS=$_ldflags
+ CPPFLAGS=$_cppflags
+ ;;
+ esac]
+)
+
+if test $needs_cpp_precomp = yes; then
+ CXXFLAGS="-no-cpp-precomp $CXXFLAGS"
+fi
+
+if test $have_libpcap = yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ CPPFLAGS="-I$LIBPCAP_INC $CPPFLAGS"
+ LDFLAGS="-L$LIBPCAP_LIB $LDFLAGS"
+ fi
+
+ # link with -lpcap for the purposes of this test
+ LIBS_OLD="$LIBS"
+ LIBS="$LIBS -lpcap"
+ PCAP_IS_SUITABLE([have_libpcap=yes], [have_libpcap=no], [have_libpcap=yes])
+ LIBS="$LIBS_OLD"
+fi
+
+if test $have_libpcap != yes; then
+ if test "${LIBPCAP_INC+set}" = "set"; then
+ LDFLAGS="-L$libpcapdir $_ldflags"
+ CPPFLAGS="$CPPFLAGS -I$LIBPCAP_INC"
+ else
+ LDFLAGS="-L$libpcapdir $LDFLAGS"
+ CPPFLAGS="$CPPFLAGS -I$libpcapdir"
+ fi
+ LIBPCAP_LIBS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_DEPENDS='$(LIBPCAPDIR)/libpcap.a'
+ PCAP_BUILD="build-pcap"
+ PCAP_CLEAN="clean-pcap"
+ PCAP_DIST_CLEAN="distclean-pcap"
+else
+ AC_DEFINE(HAVE_LIBPCAP, 1, [Have libpcap library])
+ LIBPCAP_LIBS="-lpcap"
+ PCAP_DEPENDS=""
+ PCAP_BUILD=""
+ PCAP_CLEAN=""
+ PCAP_DIST_CLEAN=""
+fi
+
+AC_SUBST(PCAP_DEPENDS)
+AC_SUBST(PCAP_BUILD)
+AC_SUBST(PCAP_CLEAN)
+AC_SUBST(PCAP_DIST_CLEAN)
+AC_SUBST(LIBPCAP_LIBS)
+
+if test $have_libpcap != yes ; then
+ AC_CONFIG_SUBDIRS(libpcap)
+fi
+
+
+have_dnet=no
+requested_included_dnet=no
+LIBDNETDIR=../libdnet-stripped
+
+# First we test whether they specified libdnet explicitly.
+# Unlike the other included libraries (pcap, pcre, lua), we prefer our local
+# copy of libdnet. That is, with the other libraries we check for a system
+# version by default, whereas with dnet we use the local version unless
+# specifically asked to use a system version.
+AC_ARG_WITH(libdnet,
+AC_HELP_STRING([--with-libdnet=DIR], [Use an existing (compiled) dnet lib from DIR/include and DIR/lib.])
+AC_HELP_STRING([--with-libdnet=included], [Use the libdnet version included with Nmap (default)]),
+[ case "$with_libdnet" in
+ yes)
+ ;;
+ included)
+ ;;
+ *)
+ CPPFLAGS="-I$with_libdnet/include $CPPFLAGS"
+ LDFLAGS="-L$with_libdnet/lib $LDFLAGS"
+ have_dnet=yes
+ ;;
+ esac]
+)
+
+# If they didn't provide location, we use the included one
+if test $have_dnet != yes ; then
+ AC_CONFIG_SUBDIRS( libdnet-stripped )
+ CPPFLAGS="-I$LIBDNETDIR/include $CPPFLAGS"
+ LIBDNET_LIBS="$LIBDNETDIR/src/.libs/libdnet.a"
+ DNET_DEPENDS="$LIBDNETDIR/src/.libs/libdnet.a"
+ DNET_BUILD="build-dnet"
+ DNET_CLEAN="clean-dnet"
+ DNET_DIST_CLEAN="distclean-dnet"
+else
+ LIBDNET_LIBS="-ldnet"
+ DNET_DEPENDS=""
+ DNET_BUILD=""
+ DNET_CLEAN=""
+ DNET_DIST_CLEAN=""
+fi
+
+AC_SUBST(LIBDNET_LIBS)
+AC_SUBST(LIBDNETDIR)
+AC_SUBST(DNET_DEPENDS)
+AC_SUBST(DNET_BUILD)
+AC_SUBST(DNET_CLEAN)
+AC_SUBST(DNET_DIST_CLEAN)
+
+
+dnl This test is from the configure.in of Unix Network Programming second
+dnl edition example code by W. Richard Stevens
+dnl ##################################################################
+dnl Check if sockaddr{} has sa_len member.
+dnl
+AC_CACHE_CHECK(if sockaddr{} has sa_len member, ac_cv_sockaddr_has_sa_len,
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>],
+ [unsigned int i = sizeof(((struct sockaddr *)0)->sa_len)],
+ ac_cv_sockaddr_has_sa_len=yes,
+ ac_cv_sockaddr_has_sa_len=no))
+if test $ac_cv_sockaddr_has_sa_len = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, [struct sockaddr has sa_len member])
+fi
+
+
+dnl Check if the sockaddr_in implementation has member sin_len
+dnl ##################################################################
+dnl Check if sockaddr_in{} has sin_len member.
+dnl
+AC_CACHE_CHECK(if sockaddr_in{} has sin_len member, ac_cv_sockaddr_in_has_sin_len,
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>],
+ [unsigned int i = sizeof(((struct sockaddr_in *)0)->sin_len)],
+ ac_cv_sockaddr_in_has_sin_len=yes,
+ ac_cv_sockaddr_in_has_sin_len=no))
+if test $ac_cv_sockaddr_in_has_sin_len = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_IN_SIN_LEN, 1, [struct sockaddr_in has sin_len member])
+fi
+
+
+dnl Check if the sockaddr_in6 implementation has member sin6_len
+dnl ##################################################################
+dnl Check if sockaddr_in6{} has sin6_len member.
+dnl
+AC_CACHE_CHECK(if sockaddr_in6{} has sin6_len member, ac_cv_sockaddr_in6_has_sin6_len,
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <netinet/in.h>
+ #include <sys/socket.h>],
+ [unsigned int i = sizeof(((struct sockaddr_in6 *)0)->sin6_len)],
+ ac_cv_sockaddr_in6_has_sin6_len=yes,
+ ac_cv_sockaddr_in6_has_sin6_len=no))
+if test $ac_cv_sockaddr_in6_has_sin6_len = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_IN6_SIN6_LEN, 1, [struct sockaddr_in6 has sin6_len member])
+fi
+
+
+#dnl check endedness
+AC_C_BIGENDIAN
+
+AC_MSG_CHECKING([if struct in_addr is a wacky huge structure (some Sun boxes)])
+AH_TEMPLATE(IN_ADDR_DEEPSTRUCT, [], [struct in_addr is a wacky huge structure (some Sun boxes)])
+
+AC_TRY_COMPILE([#include <netinet/in.h>], struct in_addr i; i._S_un._S_addr;, \
+ AC_DEFINE(IN_ADDR_DEEPSTRUCT) \
+ AC_MSG_RESULT(yes) , \
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <netinet/in.h>], struct in_addr i; i.S_un.S_addr;, \
+ AC_DEFINE(IN_ADDR_DEEPSTRUCT) \
+ AC_MSG_RESULT(yes) , \
+ AC_MSG_RESULT(no);))
+
+#AC_CACHE_CHECK(if struct icmp exists, ac_cv_struct_icmp_exists,
+ #AC_TRY_COMPILE([
+ ##include <sys/types.h>
+ ##include <sys/param.h>
+ ##include <netinet/in_systm.h>
+ ##include <netinet/in.h>
+ ##define __USE_BSD
+ ##define __FAVOR_BSD
+ ##define _BSD_SOURCE
+ ##include <netinet/ip.h>
+ ##include <netinet/ip_icmp.h>],
+ #[unsigned int i = sizeof(struct icmp)],
+ #ac_cv_struct_icmp_exists=yes,
+ #ac_cv_struct_icmp_exists=no))
+#if test $ac_cv_struct_icmp_exists = yes ; then
+ #AC_DEFINE(HAVE_STRUCT_ICMP)
+#fi
+
+#AC_CACHE_CHECK(if struct ip exists, ac_cv_struct_ip_exists,
+ #AC_TRY_COMPILE([
+ ##include <sys/types.h>
+ ##include <sys/param.h>
+ ##include <netinet/in_systm.h>
+ ##include <netinet/in.h>
+ ##define __USE_BSD
+ ##define __FAVOR_BSD
+ ##define _BSD_SOURCE
+ ##include <netinet/ip.h>],
+ #[unsigned int i = sizeof(struct ip)],
+ #ac_cv_struct_ip_exists=yes,
+ #ac_cv_struct_ip_exists=no))
+#if test $ac_cv_struct_ip_exists = yes ; then
+ #AC_DEFINE(HAVE_STRUCT_IP)
+#fi
+
+AC_CACHE_CHECK(if struct ip has ip_sum member, ac_cv_ip_has_ip_sum,
+ AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #define __USE_BSD
+ #define __FAVOR_BSD
+ #define _BSD_SOURCE
+ #include <netinet/ip.h>
+ #include <netinet/ip_icmp.h>],
+ [unsigned int i = sizeof(((struct ip *)0)->ip_sum)],
+ ac_cv_ip_has_ip_sum=yes,
+ ac_cv_ip_has_ip_sum=no))
+if test $ac_cv_ip_has_ip_sum = yes ; then
+ AC_DEFINE(HAVE_IP_IP_SUM, 1, [struct ip has ip_sum member])
+fi
+
+AC_CACHE_CHECK(if function signal is accessible, ac_cv_have_signal,
+ AC_TRY_COMPILE(
+ [
+ #include <signal.h>
+ ],
+ [
+ void handler(int signo){
+ int a=0;
+ }
+
+ int main () {
+ ssignal(SIGINT, handler);
+ return 0;
+ }
+ ],
+ ac_cv_have_signal=yes,
+ ac_cv_have_signal=no))
+if test $ac_cv_have_signal = yes ; then
+ AC_DEFINE(HAVE_SIGNAL, 1, [ssignal function is accessible])
+fi
+
+
+
+
+AH_TEMPLATE(SOLARIS, [Sun/Oracle Solaris])
+AH_TEMPLATE(STUPID_SOLARIS_CHECKSUM_BUG, [],
+ [A bug in Solaris causing incorrect IP checksums])
+case "$host" in
+ *alpha-dec-osf*)
+ AC_DEFINE(DEC, 1, [DEC Alpha])
+ ;;
+ *-netbsd* | *-knetbsd*-gnu)
+ AC_DEFINE(NETBSD, 1, [NetBSD])
+ ;;
+ *-openbsd*)
+ AC_DEFINE(OPENBSD, 1, [OpenBSD])
+ ;;
+ *-freebsd* | *-kfreebsd*-gnu | *-dragonfly*)
+ AC_DEFINE(FREEBSD, 1, [FreeBSD])
+ ;;
+ *-bsdi*)
+ AC_DEFINE(BSDI, 1, [BSD/OS])
+ ;;
+ *-sgi-irix5* | *-sgi-irix6*)
+ AC_DEFINE(IRIX, 1, [IRIX])
+ ;;
+ *-hpux*)
+ AC_DEFINE(HPUX, 1, [HP-UX])
+ # To link with libnet and NM (/usr/lib/libnm.sl) library
+ # on HP-UX 11.11 (other versions?) Mikhail Zakharov (zmey20000@yahoo.com)
+ AC_CHECK_LIB(nm, open_mib)
+ ;;
+ *-aix*)
+ # use some AIX specific libraries
+ AC_CHECK_LIB(odm, odm_initialize)
+ AC_CHECK_LIB(cfg, _system_configuration)
+ AC_CHECK_LIB(crypt, crypt_r)
+ ;;
+ *-solaris2.0*)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.[[1-9]][[0-9]]*)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.1*)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.2*)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.3*)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.4*)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris2.5.1)
+ AC_DEFINE(STUPID_SOLARIS_CHECKSUM_BUG)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-solaris*)
+ AC_DEFINE(SOLARIS)
+ ;;
+ *-sunos4*)
+ AC_DEFINE(SUNOS, 1, [SunOS 4])
+ AC_DEFINE(SPRINTF_RETURNS_STRING, 1,
+ [sprintf(9f) returns its first argument, not the number of characters printed])
+ ;;
+ *-linux*)
+ AC_DEFINE(LINUX, 1, [Linux])
+ ;;
+ *-apple-darwin*)
+ AC_DEFINE(MACOSX, 1, [Apple OS X])
+ dnl on Mac OSX the math library seems to contain unwanted getopt cruft
+ AC_CHECK_LIB(m, main)
+ needs_cpp_precomp=yes
+ ;;
+esac
+
+
+
+
+
+
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(strerror)
+#RECVFROM_ARG6_TYPE
+
+AC_OUTPUT(Makefile)
+# Some ASCII ART#!#@$!@#$
+if test -f docs/leet-nping-ascii-art.txt; then
+ cat docs/leet-nping-ascii-art.txt
+fi
+echo "Configuration complete. Type make (or gmake on some *BSD machines) to compile."
diff --git a/nping/docs/AUTHORS b/nping/docs/AUTHORS
new file mode 100644
index 0000000..cef394b
--- /dev/null
+++ b/nping/docs/AUTHORS
@@ -0,0 +1,16 @@
+Nping AUTHORS
+===============
+
+Nping was originally written from the ground up by Luis MartinGarcia
+(luis.mgarc@gmail.com), during the Google Summer of Code program in 2009. Luis
+was mentored by Fyodor.
+
+Further development was done in the Google Summer of Code 2010 by Luis
+once again mentored by Fyodor.
+
+Many helpful comments, suggestions and other useful information were taken from
+the dev@nmap.org list as well as other contributors via email.
+
+Nping shares the Nmap infrastructure libraries (Nsock and Nbase) which were
+originally written by Fyodor.
+
diff --git a/nping/docs/EchoProtoRFC.txt b/nping/docs/EchoProtoRFC.txt
new file mode 100644
index 0000000..e819411
--- /dev/null
+++ b/nping/docs/EchoProtoRFC.txt
@@ -0,0 +1,1158 @@
++-----------------------------------------------------------------------------+
+
+
+
+
+
+
+ NPING ECHO PROTOCOL
+
+
+
+
+ PROTOCOL SPECIFICATION
+
+ Request for Comments
+
+ August 2010
+
+
+
+
+
+ Luis MartinGarcia
+ (luis.mgarc@gmail.com)
+
+
+
+
+
+
++-----------------------------------------------------------------------------+
+
+Status of this document: DRAFT
+First version: May 29, 2009.
+Last revision date: April 27, 2011.
+
++-----------------------------------------------------------------------------+
+
+
+
+ PREFACE
+
+This documents presents the technical specification of the Nping Echo Protocol.
+
+
+
+
+ TABLE OF CONTENTS
+
+1. INTRODUCTION ..................................................... x
+
+2. NPING ECHO PROTOCOL SPECIFICATION................................. x
+
+ 2.1 General Message Format......................................... x
+ 2.2 Field Description.............................................. x
+ 2.3 Message type codes............................................. x
+ 2.4 Message NEP_HANDSHAKE_SERVER................................... x
+ 2.5 Message NEP_HANDSHAKE_CLIENT................................... x
+ 2.6 Message NEP_HANDSHAKE_FINAL.................................... x
+ 2.7 Operation NEP_PACKET_SPEC...................................... x
+ 2.8 Operation NEP_READY............................................ x
+ 2.9 Operation NEP_ECHO............................................. x
+ 2.10 Operation NEP_ERROR............................................ x
+ 2.11 Flow diagrams.................................................. x
+ 2.12 Security....................................................... x
+ 2.13 Cryptographic key derivation................................... x
+ 2.14 Encryption process............................................. x
+ 2.15 Additional considerations...................................... x
+
+3. GLOSSARY .......................................................... x
+
+4. REFERENCES ........................................................ x
+
+
+
+
+
+
+
+
+
+
+
+
+
+1. INTRODUCTION
+
+ Troubleshooting routing and firewall issues is a common task nowadays.
+ The scenario is generally that some network traffic should be flowing
+ but isn't. The causes of problem can range from routing issues to
+ network firewall to host-based firewalls to all sorts of other strange
+ things. It is usually the "middle box" problem that is the hardest to
+ find.
+
+ Suppose there is some host with a TCP service listening that you can't
+ connect to for an unknown reason. If a Nmap -sS scan doesn't show the
+ port as open there are a multitude of possible problems. Maybe the SYN
+ packet never made it because of some firewall in the middle. Maybe the
+ SYN did make it but the SYN+ACK got dropped on its way back to you.
+ Maybe the TTL expired in transit but the ICMP message got blocked by
+ another firewall before making it back to you. Maybe the SYN made it
+ but some intermediate host forged a reset packet to snipe the connection
+ before the SYN+ACK made it back to you.
+
+ When things like the above are going on it is often the case that even
+ nping can't track down the problem alone. One generally has to turn to
+ Wireshark/tcpdump on one station and nping on the other but sometimes
+ it may be quite difficult to coordinate, specially when the person at
+ the remote host does not even know what an IP address is.
+
+ To solve this problem, Nping implements a new mode of operation, called
+ "Echo mode", which provides a combination of a packet generator and a
+ remote sniffer.
+
+ The Echo mode is based on a client/server architecture. Both ends run Nping,
+ one of them in server mode and the other in client mode. The way it works
+ is: the Nping client performs an initial handshake with the server over some
+ standard port (creating a side-channel). Then it notifies the server
+ what packets are about to be sent. The server sets up a liberal BPF
+ filter that captures those packets, and starts listening. When the server
+ receives a packet it encapsulates it (including the link layer frame)
+ into our own protocol packet and sends it back to the nping client.
+ This would be essentially like running tcpdump on the remote machine
+ and having it report back the packets you sent to it with Nping.
+
+ By having the side-channel to talk to the server, things like NAT would
+ become immediately apparent because you'd see your source IP (and
+ sometimes port) change. Things like "packet shapers" that change TCP
+ window sizes transparently between hosts would turn up. It would be
+ easy to tell if the traffic is being dropped in transit and never gets
+ to the box. It would also be easy to tell if the traffic does make it
+ to the box but the reply never makes it back to you.
+
+ In general, it would be like sending a postal package to someone and
+ having them email you a photo of the package when they get it. If you
+ think your packages are being abused by the parcel service then having
+ someone on the other end to send information back is a great way to
+ uncover what is going on.
+
+
+
+2. NPING ECHO PROTOCOL SPECIFICATION
+
+
+ 2.1 General Message Format
+
+ The following diagram describes the general format of the NEP messages.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . DATA .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . Message Authentication Code .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ There are 7 different kinds of packets:
+
+ NEP_HANDSHAKE_SERVER (S->C)
+ Informs the client of the highest version it supports and sends
+ the server's authentication parameters.
+
+ NEP_HANDSHAKE_CLIENT (C->S)
+ Informs the server of the highest version it supports and sends
+ the initial authentication parameters.
+
+ NEP_HANDSHAKE_FINAL (S->C)
+ Echoes server nonce back to the server.
+
+ NEP_PACKET_SPEC: (C->S):
+ Tells the server what kind of packets we are planning to send.
+
+ NEP_READY: (S->C):
+ Tells the client that the server is ready to start receiving
+ packets.
+
+ NEP_ECHO: (S->C):
+ Contains the packet that the server receives from the client.
+
+ NEP_ERROR: (C->S or S->C):
+ Indicates an error and terminates the session.
+
+
+
+ 2.2 Field Description
+
+ Version: 8 bits
+ Current version of the protocol. This document covers version 0x01.
+
+
+ Message type: 8 bits
+ Integer that indicates the type of packet. It must be one of the
+ type codes defined in section 2.3.
+
+
+ Total Length: 16 bits
+ Length of the entire packet, measured in 32bit words. Value must
+ be in NETWORK byte order.
+
+
+ Sequence Number: 32 bits
+ Packet sequence number, relative to the sender. Initially this
+ field is set to a random value, and then it is incremented by one
+ for each packet that is sent in a given session. The counter must
+ wrap back to zero after it reaches (2^32)-1. This field is intended
+ to provide flow tracking and basic protection against replay
+ attacks.
+
+ Timestamp: 32 bits
+ Current time of the sender. This time is expressed as the number
+ of seconds elapsed since 00:00, 01/01/1970 UTC (epoch time).
+
+ Reserved: 32 bits
+ Reserved for future use. Reserved fields have been added for two
+ reasons: to allow future extension of the protocol and to make
+ the header a multiple of 128 bits needed to satisfy AES encryption
+ requirements in block size.
+
+
+ Data: variable length
+ Message specific data.
+
+
+ Message Authentication Code : 256 bits
+ Code that provides integrity and authentication to the rest of the
+ packet. For this, the HMAC-SHA256 suite must be used. The
+ computation of the code includes the whole plain-text message until
+ the first byte of the Message Authentication Code field.
+
+
+ 2.3 Message type codes
+
+ Message NEP_HANDSHAKE_SERVER: 0x01
+ Message NEP_HANDSHAKE_CLIENT: 0x02
+ Message NEP_HANDSHAKE_FINAL: 0x03
+ Message NEP_PACKET_SPEC: 0x04
+ Message NEP_READY: 0x05
+ Message NEP_ECHO: 0x06
+ Message NEP_ERROR: 0x07
+
+
+ 2.4 Message NEP_HANDSHAKE_SERVER
+
+ The NEP_HANDSHAKE_SERVER message is sent by the server and it requests
+ client's authentication. The packet informs the client of the latest
+ version of the protocol that the server supports and provides the
+ appropriate information for the client authentication process.
+
+ The NEP_HANDSHAKE_SERVER message establishes the following:
+
+ - The identity of the server and that the message was generated
+ by that server.
+ - That the message was intended for the client.
+ - The integrity and originality of the message.
+
+
+ The format of the NEP_HANDSHAKE_SERVER message is the following:
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 5 +-- --+
+ | |
+ 6 +-- --+
+ | |
+ 7 +-- --+
+ | Server Nonce |
+ 8 +-- --+
+ | |
+ 9 +-- --+
+ | |
+ 10 +-- --+
+ | |
+ 11 +-- --+
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 13 + --+
+ | |
+ 14 +-- Reserved --+
+ | |
+ 15 +-- --+
+ | |
+ 16 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+
+ . . .
+ | |
+ 24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ Server Nonce: 256 bits
+ Random number. This number must be generated using a
+ cryptographically secure PRNG and must not be reused. This is
+ the data that should be used by the client to construct its
+ cipher block initialization vector.
+
+ Reserved: 120 bits
+ Reserved for future use.
+
+ HMAC-SHA256: 256 bits
+ Message authentication code that covers the entire packet, from
+ byte 0 to the last byte of the last reserved field. The code is
+ computed over the plaintext, before the encryption is applied to
+ part of the packet.
+
+
+
+ 2.5 Message NEP_HANDSHAKE_CLIENT
+
+
+ The NEP_HANDSHAKE_CLIENT message is sent by the client and it provides
+ the appropriate information for client-side authentication. This type
+ of message is generated only if the previous NEP_HANDSHAKE_CLIENT
+ message contains a valid message authentication code.
+
+ The NEP_HANDSHAKE_CLIENT message establishes the following:
+
+ - The identity of the client and that reply message has been
+ generated by the client.
+ - That the message was intended for the server.
+ - The integrity and originaltity of the reply.
+
+
+ The format of the NEP_HANDSHAKE_CLIENT message is the following:
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 5 +-- --+
+ | |
+ 6 +-- --+
+ | |
+ 7 +-- --+
+ | Server Nonce |
+ 8 +-- --+
+ | |
+ 9 +-- --+
+ | |
+ 10 +-- --+
+ | |
+ 11 +-- --+
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 13 +-- --+
+ | |
+ 14 +-- --+
+ | |
+ 15 +-- --+
+ | Client Nonce |
+ 16 +-- --+
+ | |
+ 17 +-- --+
+ | |
+ 18 +-- --+
+ | |
+ 19 +-- --+
+ | |
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ###################### ENCRYPTION STARTS HERE #######################
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 21 +-- --+
+ | |
+ 22 +-- Partner IP address --+
+ | |
+ 23 +-- --+
+ | |
+ 24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | IP Version | |
+ 25 +---------------+ --+
+ | |
+ 26 +-- Reserved --+
+ | |
+ 27 +-- --+
+ | |
+ 28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE #######################
+ 28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ 36 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ Server Nonce: 256 bits
+ Nonce value received from the server in the previous
+ NEP_HANDSHAKE_SERVER message. This allows the server to ensure that
+ the received reply is fresh and was generated as a result of its
+ NEP_HANDSHAKE_SERVER message.
+
+ Client Nonce: 256 bits
+ Random number. This number must be generated using a
+ cryptographically secure PRNG and must not be reused. This is
+ the data that should be used by the server to construct its
+ cipher block initialization vector.
+
+ Partner IP address: 128 bits
+ This is the server's IP address as seen by the client. This field
+ has 128 bits to allow use of both IPv4 and IPv6 addresses. When
+ IPv4 is used, only the first four bytes are used. The rest may be
+ set to zero or filled with random data.
+
+ IP version: 8-bits
+ Version of the address in the "Partner IP address" field. It should
+ take one of the following values:
+
+ 0x04 : for IP version 4.
+ 0x06 : for IP version 6.
+
+ 2.6 Message NEP_HANDSHAKE_FINAL
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 5 +-- --+
+ | |
+ 6 +-- --+
+ | |
+ 7 +-- --+
+ | Client Nonce |
+ 8 +-- --+
+ | |
+ 9 +-- --+
+ | |
+ 10 +-- --+
+ | |
+ 11 +-- --+
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ###################### ENCRYPTION STARTS HERE #######################
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 13 +-- --+
+ | |
+ 14 +-- Partner IP address --+
+ | |
+ 15 +-- --+
+ | |
+ 16 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | IP Version | |
+ 17 +---------------+ --+
+ | |
+ 18 +-- Reserved --+
+ | |
+ 19 +-- --+
+ | |
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE ########################
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ 28 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ Client Nonce: 256 bits
+ Nonce value received from the client in the preceding
+ NEP_HANDSHAKE_CLIENT message.
+
+ Partner IP address: 128 bits
+ This is the clients's IP address as seen by the server. This field
+ has 128 bits to allow use of both IPv4 and IPv6 addresses. When
+ IPv4 is used, only the first four bytes are used. The rest may be
+ set to zero or filled with random data. The inclusion of this
+ information lets the client immediately detect the presence of
+ some intermediate devices that change his source IP (e.g a NAT box).
+ This is a modification of the original X.509 three way
+ authentication protocol, provided, among other things, in order to
+ make the man-in-the-middle attack described in [1] more difficult.
+
+ IP version: 8 bits
+ Version of the address in the "Partner IP address" field. It should
+ take one of the following values:
+
+ 0x04 : for IP version 4.
+ 0x06 : for IP version 6.
+
+
+ 2.7 Operation NEP_PACKET_SPEC
+
+ The NEP_PACKET_SPEC message is sent by the client to tell the server
+ what kind of packets it should expect.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ ###################### ENCRYPTION STARTS HERE #######################
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | IP version | Protocol | Packet Count |
+ 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . | |
+ . . .
+ . . PacketSpec .
+ n . .
+ | |
+ 32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE ########################
+ 32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ 40 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ IP version: 8 bits
+ Specifies which is the expected IP version. It must contain one
+ of the following values:
+
+ 0x04 (IP version 4)
+
+ 0x06 (IP version 6)
+
+ 0xFF (Any version)
+
+ Protocol: 8 bits.
+ Specifies which kind of packets will be sent to the server. It
+ must contain one of the following values:
+
+ 0x06 (Protocol TCP)
+ Tells the server to listen to TCP packets coming from
+ the client's IP address.
+
+ 0x11 (Protocol UDP)
+ Tells the server to listen to UDP packets coming from
+ the client's IP address.
+
+ 0x01 (Protocol ICMP)
+ Tells the server to listen to ICMP packets coming from
+ the client's IP address.
+
+ Packet count: 16 bits.
+ Specifies how many packets will be sent. It must be in NETWORK
+ byte order.
+
+ PacketSpec: 864 bits.
+ Tells the server which header fields should be checked to match
+ a captured packet with the client that sent it. This is necessary
+ as the server supports multiple user sessions at a time, and needs
+ a way to distinguish the packets.
+
+ The PacketSpec field consists of a list of protocol fields and
+ their expected value. Every item on that list has the following
+ format:
+
+ {Field Code, Field Value}
+
+ Where "Field Code" is an 8-bit numeric identifier of the field (see
+ definitions below) and "Field Value" is the expected value, that
+ the server should try to match. The length of "Field Value" depends
+ on the "Field Code" (see table below for details) and, in general,
+ it matches the usual length for that field int its original
+ protocol header.
+
+ Items on the PacketSpec list are specified sequentially. However,
+ the final length of the list must be 108 bytes, so null bytes must
+ be added after the last item.
+
+ The following table lists the available field specifiers, their
+ code and the length of their values.
+
+ ====NAME======== ==CODE== ==LENGTH==
+ +----------------+--------+----------+
+ | IPv4_TOS | 0xA0 | 8 bits |
+ +----------------+--------+----------+
+ | IPv4_ID | 0xA1 | 16 bits |
+ +----------------+--------+----------+
+ | IPv4_FRAGOFF | 0xA2 | 16 bits |
+ +----------------+--------+----------+
+ | IPv4_PROTO | 0xA3 | 8 bits |
+ +----------------+--------+----------+
+
+ +----------------+--------+----------+
+ | IPv6_TCLASS | 0xB0 | 8 bits |
+ +----------------+--------+----------+
+ | IPv6_FLOW | 0xB1 | 24 bits |
+ +----------------+--------+----------+
+ | IPv6_NHDR | 0xB2 | 8 bits |
+ +----------------+--------+----------+
+
+ +----------------+--------+----------+
+ | TCP_SPORT | 0xC0 | 16 bits |
+ +----------------+--------+----------+
+ | TCP_DPORT | 0xC1 | 16 bits |
+ +----------------+--------+----------+
+ | TCP_SEQ | 0xC2 | 32 bits |
+ +----------------+--------+----------+
+ | TCP_ACK | 0xC3 | 32 bits |
+ +----------------+--------+----------+
+ | TCP_FLAGS | 0xC4 | 8 bits |
+ +----------------+--------+----------+
+ | TCP_WIN | 0xC5 | 16 bits |
+ +----------------+--------+----------+
+ | TCP_URP | 0xC6 | 16 bits |
+ +----------------+--------+----------+
+
+ +----------------+--------+----------+
+ | ICMP_TYPE | 0xD0 | 8 bits |
+ +----------------+--------+----------+
+ | ICMP_CODE | 0xD1 | 8 bits |
+ +----------------+--------+----------+
+
+ +----------------+--------+----------+
+ | UDP_SPORT | 0xE0 | 16 bits |
+ +----------------+--------+----------+
+ | UDP_DPORT | 0xE1 | 16 bits |
+ +----------------+--------+----------+
+ | UDP_LEN | 0xE2 | 16 bits |
+ +----------------+--------+----------+
+
+ +----------------+--------+----------+
+ | PAYLOAD_MAGIC | 0xFF | Variable |
+ +----------------+--------+----------+
+
+
+ The PAYLOAD_MAGIC type lets the client specify some magic number
+ included in the packet's payload. This can be used when all other
+ specifiers fail (e.g: in IPv4-to-IPv6 tunnels). The length of
+ its field data is variable and must be specified right after the
+ field code. Note that the length can never be higher than the
+ remaining space in the PacketSpec field. If no other field
+ specifiers are set, "length" can never be higher than 106 bytes.
+ Servers should carefully check the structure of the PacketSpec
+ field and close the session established with the sender if it
+ does not meet the requirements specified in this document.
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | PAYLOAD_MAGIC | Length | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Value +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ PAYLOAD_MAGIC: 8 bits.
+ Field code. MUST be set to 0xFF.
+
+ Length: 8 bits.
+ Length of the data in the "Value" field. MUST be greater
+ than zero; MUST NOT be greater than the remaining space in
+ the PacketSpec field and MUST NEVER exceed 106 bytes.
+
+ Value: variable length.
+ Payload data. Its length must be the one specified in the
+ "Length" field. It may contain any binary value. Comparisons
+ at the server side should be made at the bit level so the
+ encoding should match the one used at the application layer
+ in the packets that are produced and sent by the client.
+
+
+ Here is an example of how a typical specifier list looks like:
+
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | IPv4_TOS | 0x00 | IPv4_ID | 0xCA |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xFE | IPv4_PROTO | 0x06 | TCP_SPORT |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0x4432 | TCP_DPORT | 0x00 |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0x50 | TCP_FLAGS | 0x08 | TCP_SEQ |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0x5D33FA6D |
+ 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0x00 | 0x00 | 0x00 | 0x00 |
+ 6 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . .
+ . .
+ . .
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0x00 | 0x00 | 0x00 | 0x00 |
+ 27 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ All packet specifications MUST include the IPv4_ID specifier
+ (or IPv6_Flow for IPv6) and at least three other fields specifiers.
+ Additionally, clients MUST NEVER specify the same field specifier
+ more than once in a NEP_PACKET_SPEC message. Clients that send
+ messages that do not meet these requirements MUST be rejected by the
+ server.
+
+
+ 2.8 Operation NEP_READY
+
+ The READY packet is sent by the server to indicate the client that
+ his SPECS packet was accepted and that everything is ready to start
+ receiving and echoing packets.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ ###################### ENCRYPTION STARTS HERE #######################
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE ########################
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+
+
+ 2.9 Operation NEP_ECHO
+
+ The NEP_ECHO message is sent by the server and it contains an echoed
+ network packet.
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ ###################### ENCRYPTION STARTS HERE #######################
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DLT Type | Packet Length |
+ 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . .
+ . . Packet .
+ . . .
+ . . +-+-+-+-+-+-+-+-+
+ | | Padding |
+ n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE ########################
+ n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ n+8 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ DLT Type: 16 bits.
+ Specifies the type of link layer device used in the server side.
+ Since the server includes link layer frames in echoed packets,
+ the client needs to know the DLT in order to process link layer
+ header information. Values used in this field must match DLT types
+ defined in libpcap and must be transmitted in NETWORK byte order.
+ Servers may use the special value 0x0000 to indicate that no link
+ layer header is included.
+
+ Packet Length: 16 bits.
+ Specifies the length of the echoed packet measured in bytes.
+ The value stored in this field must be in NETWORK byte order and
+ must never be greater than 9212, as that is the maximum number of
+ bytes that can be echoed per packet.
+
+ Packet: variable length.
+ This corresponds to the packet being echoed. Servers should
+ store the packet exactly as it was received. No byte order
+ conversions or any other alteration should be performed.
+ The whole NEP_ECHO packet must have a length that is a multiple of
+ 16 bytes, so if (packet_len+4)mod16 is not zero, the packet field
+ must be padded with NULL bytes. As noted before, the maximum length
+ for an echoed packet is 9212 bytes. Any packet that exceeds that
+ length must be truncated.
+
+
+
+ 2.10 Operation NEP_ERROR
+
+ The NEP_ERROR packet is sent by client or server when an error occurs,
+ and informs the other end that the sender is terminating the NEP
+ session and closing the TCP connection. This message includes an error
+ description string that should explain the reason why the session is
+ being terminated (e.g. authentication failed, invalid message format).
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ ###################### ENCRYPTION STARTS HERE #######################
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | Message Type | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Timestamp |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . .
+ . . Error Message .
+ . . .
+ . . .
+ | |
+ 24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ ####################### ENCRYPTION ENDS HERE ########################
+ 24 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . Message Authentication Code .
+ . . .
+ | |
+ 32 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ Error Message: 640 bits.
+ Contains a NULL-terminated ASCII string that describes the reason
+ why the session is being terminated by the sender. The string MUST
+ contain a NULL character (0x00) at the end of it. The remaining
+ bytes, if any, must also be set to zero.
+
+
+ 2.11 Flow diagrams
+
+
+ The following diagram shows a typical client/server session:
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | NEP_HANDSHAKE_SERVER |
+ |<<---------------------|
+ | |
+ | |
+ | NEP_HANDSHAKE_CLIENT |
+ |--------------------->>|
+ | |
+ | |
+ | NEP_HANDSHAKE_FINAL |
+ |<<---------------------|
+ | |
+ | |
+ | |
+ | NEP_PACKET_SPEC |
+ |--------------------->>|
+ | |
+ | |
+ | |
+ | NEP_READY |
+ |<<---------------------|
+ | |
+ | |
+ | |
+ | |
+ | NEP_ECHO |
+ |<<---------------------|
+ | |
+ | NEP_ECHO |
+ |<<---------------------|
+ | |
+ | NEP_ECHO |
+ |<<---------------------|
+ | . |
+ | . |
+ | . |
+ | NEP_ECHO |
+ |<<---------------------|
+ | |
+ | |
+ | |
+ | TCP Connection Close |
+ |<<------------------->>|
+
+
+
+
+
+ The following diagram represents a session where the client sends an
+ invalid PacketSpec message.
+
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | NEP_HANDSHAKE_SERVER |
+ |<<---------------------|
+ | |
+ | |
+ | NEP_HANDSHAKE_CLIENT |
+ |--------------------->>|
+ | |
+ | |
+ | NEP_HANDSHAKE_FINAL |
+ |<<---------------------|
+ | |
+ | |
+ | |
+ | NEP_PACKET_SPEC |
+ |--------------------->>|
+ | |
+ | |
+ | NEP_ERROR |
+ |<<---------------------|
+ | |
+ | TCP Connection Close |
+ |<<------------------->>|
+
+
+ The following diagram represents a session where the server fails to
+ provide a valid NEP_HANDSHAKE_SERVER message.
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | NEP_HANDSHAKE_SERVER |
+ |<<---------------------|
+ | |
+ | |
+ | TCP Connection Close |
+ |<<------------------->>|
+
+
+
+ The following diagram represents a session where the client fails to
+ provide a valid NEP_HANDSHAKE_CLIENT message.
+
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | NEP_HANDSHAKE_SERVER |
+ |<<---------------------|
+ | |
+ | |
+ | NEP_HANDSHAKE_CLIENT |
+ |--------------------->>|
+ | |
+ | |
+ | TCP Connection Close |
+ |<<------------------->>|
+
+
+
+ 2.12 Security
+
+ The NEP client/server authentication process is based on the three-way
+ authentication protocol, described in CITT recommendation X.509 [2].
+ However, it has been slightly modified:
+
+ - Messages are not signed using public-key cryptography but a
+ symmetric encryption key known by both client and server. This
+ provides the same authentication as the original specification
+ but it does not provide non-repudiation.
+
+ - Ciphertext is encrypted using the secret key shared by client and
+ server, instead of using the receiver's public key.
+
+ The cipher suite to be used for data encryption is AES-128.
+
+ When one of the two participating entities receives a fully encrypted
+ message (any message other than NEP_HANDSHAKE_SERVER, NEP_HANDSHAKE_CLIENT
+ or NEP_HANDSHAKE_FINAL), it performs the following steps:
+
+ 1. Reads 128 bits and decrypts them.
+ 2. Checks that version equals 0x01
+ 3. Checks that the value in the message type field corresponds to a
+ valid message type code.
+ 4. If message type is not one of NEP_HANDSHAKE_CLIENT or
+ NEP_HANDSHAKE_SERVER, it checks that the received sequence number
+ matches the last received sequence number from the same sender plus
+ one.
+ 5. It checks that the received timestamp is inside a "reasonable" time
+ window (where "reasonable" is left undefined on purpose, as it may
+ vary depending on the nature of the implementation or the host
+ system).
+ 6. Checks the received total length. For messages whose length is
+ fixed, it should check whether the received length matches the
+ expected length of the message. For variable length messages, it
+ should check that the length is at least, higher than or equal to the
+ minimum length for that kind of message.
+ 7. If all tests succeed, then the remaining bits are read
+ (remaining = TotalLength - 128bits)
+ 8. Any remaining ciphertext is decrypted.
+ 9. An alternative message authentication code is computed over the
+ unencrypted data and matched against the received one. If both codes
+ match, then the message is considered valid (its integrity has been
+ verified and its contents are to be trusted), authentic (the creator
+ of the message is someone who knows the secret) and fresh (the
+ message is new and has not been replayed).
+
+
+ 2.13 Cryptographic key derivation.
+
+ Five cryptographic keys are generated for each client session. All of
+ them are derived from a single shared secret (a passphrase), known by
+ client and server. The key derivation process is the following:
+
+ h=SHA256( "passphrase" + NONCES + KEY_TYPE_ID )
+ do(1000 times){
+ h=SHA256(h);
+ }
+
+ Where 'h' is a 256bit buffer that holds the final key, 'SHA256' is the
+ hash computation function for the SHA-256 algorithm, 'NONCES' is the
+ combination of server's and client's nonce values, exchanged during
+ handshake, and KEY_TYPE_ID is a string that varies depending on the
+ type of key being derived. (See below for its definitions).
+
+ As mentioned above, a total of 5 symmetric keys are used. Those keys
+ are:
+
+ NEP_KEY_MAC_S2C : Key used by the server to sign its messages.
+ For this type of key, KEY_TYPE_ID="NEPkeyforMACServer2Client"
+ (unquoted) and NONCES equals the server nonce in the
+ NEP_HANDSHAKE_SERVER message, concatenated with the client nonce
+ in the NEP_HANDSHAKE_CLIENT message (SERVER_NONCE + CLIENT_NONCE).
+
+ NEP_KEY_MAC_S2C_INITIAL : Key used by the server to sign its
+ NEP_HANDSHAKE_SERVER messages. This is a special case key because
+ it needs to be generated before a client nonce is received (this is
+ the only key that is not influenced by the client's nonce). For
+ this type of key, KEY_TYPE_ID="NEPkeyforMACServer2ClientInitial"
+ (unquoted) and NONCES equals the nonce in the NEP_HANDSHAKE_SERVER
+ message, concatenated with an empty client nonce, in other words,
+ a nonce with all its bits set to zero (SERVER_NONCE + ZEROED_NONCE).
+
+ NEP_KEY_MAC_C2S : Key used by the client to sign its messages.
+ For this type of key, KEY_TYPE_ID="NEPkeyforMACClient2Server"
+ (unquoted) and NONCES equals the server nonce in the
+ NEP_HANDSHAKE_SERVER message, concatenated with the client nonce
+ in the NEP_HANDSHAKE_CLIENT message (SERVER_NONCE + CLIENT_NONCE).
+
+ NEP_KEY_CIPHERTEXT_C2S : Key used by the client to encrypt its
+ messages. For this type of key, KEY_TYPE_ID=
+ "NEPkeyforCiphertextClient2Server" (unquoted) and NONCES equals the
+ server nonce in the NEP_HANDSHAKE_SERVER message, concatenated with
+ the client nonce in the NEP_HANDSHAKE_CLIENT message
+ (SERVER_NONCE + CLIENT_NONCE).
+
+ NEP_KEY_CIPHERTEXT_S2C : Key used by the server to encrypt its
+ messages. For this type of key, KEY_TYPE_ID=
+ "NEPkeyforCiphertextServer2Client" (unquoted) and NONCES equals the
+ server nonce in the NEP_HANDSHAKE_SERVER message, concatenated with
+ the client nonce in the NEP_HANDSHAKE_CLIENT message
+ (SERVER_NONCE + CLIENT_NONCE).
+
+ When not all 256 bits are required, the last 256-N bits of key material
+ may be discarded, where N is the desired key length. This is, if less
+ than 256 of key material is needed, discarded bits must be the least
+ significant ones.
+
+ 2.14 Encryption process.
+
+ Encryption must be performed using AES-128-CBC. This is, using the AES
+ encryption algorithm in CBC mode, with 128-bit keys.
+
+ For each party producing encrypted data, the first initialization
+ vector should be the nonce that this same party generated during the
+ authentication handshake phase. If the nonce has more bits than needed,
+ only the necessary number of bits should be used. These bits should be
+ the most significant ones.
+
+ The initialization vector for subsequent encryption operations should
+ be the last ciphertext block produced by the same entitiy. This is, to
+ encrypt the Nth message, the last ciphertext block of the (N-1)th
+ message should be used as the initialization vector for message N. Same
+ rule applies for decryption operations, where the initialization vector
+ should be the last ciphertext block received from the other end.
+
+
+ 2.15 Additional considerations.
+
+ - By default, the server side will listen for incoming connections on
+ TCP port 9929.
+
+
+3. GLOSSARY
+
+ C->S : Indicates that a given message is sent from the client to the server
+ S->C : Indicates that a given message is sent from the server to the client
+ NEP : Acronym for Nping Echo Protocol
+
+
+4. REFERENCES
+
+ [1] I'Anson, C. and Mitchell, C. (1990). "Security defects in CCITT
+ recommendation X.509: the directory authentication framework". ACM
+ SIGCOMM Computer Communication Review, Volume 20, Issue 2. United
+ States.
+
+ [2] C.C.I.T.T. (1988). "Recommendation X .509, The Directory -
+ Authentication Framework"
diff --git a/nping/docs/leet-nping-ascii-art.txt b/nping/docs/leet-nping-ascii-art.txt
new file mode 100644
index 0000000..1721094
--- /dev/null
+++ b/nping/docs/leet-nping-ascii-art.txt
@@ -0,0 +1,18 @@
+ o
+ o
+ o
+ o o
+ o o
+ o o
+ o o o
+ o o o
+ 888b 888 o o o
+ 8888b 888 o o o
+ 88888b 888 o o o
+ 888Y88b 888 o
+ 888 Y88b888 o
+ 888 Y88888
+ 888 Y8888
+ 888 Y888
+
+ --[NPING]--
diff --git a/nping/docs/nping-man.xml b/nping/docs/nping-man.xml
new file mode 100644
index 0000000..d416f72
--- /dev/null
+++ b/nping/docs/nping-man.xml
@@ -0,0 +1,3575 @@
+<refentry id="npingman">
+ <refmeta>
+ <refentrytitle>nping</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo class="source">Nping</refmiscinfo>
+ <refmiscinfo class="manual">Nping Reference Guide</refmiscinfo>
+ </refmeta>
+ <refnamediv id="nping-man-name">
+ <refname>nping</refname>
+ <refpurpose>Network packet generation tool / ping utility</refpurpose>
+ </refnamediv>
+ <!-- body begins here -->
+ <refsynopsisdiv id="nping-man-synopsis">
+ <cmdsynopsis sepchar=" ">
+ <command>nping</command>
+ <arg choice="opt" rep="norepeat">
+ <replaceable>Options</replaceable>
+ </arg>
+ <arg choice="req" rep="norepeat">
+ <replaceable>targets</replaceable>
+ </arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1 id="nping-man-description">
+ <title>Description</title>
+ <indexterm><primary>Nping</primary><secondary>description of</secondary></indexterm>
+ <web>
+ <note><para>This document describes the very latest version of
+ Nping available from <ulink url="https://nmap.org/nping"/> Please
+ ensure you are using the latest version before reporting that a
+ feature doesn't work as described.</para></note>
+ </web>
+ <para>Nping is an open-source tool for network packet generation,
+ response analysis and response time measurement. Nping allows
+ users to generate network packets of a wide range of protocols,
+ letting them tune virtually any field of the protocol
+ headers. While Nping can be used as a simple ping utility to
+ detect active hosts, it can also be used as a raw packet generator
+ for network stack stress tests, ARP poisoning, Denial of Service
+ attacks, route tracing, and other purposes.</para>
+
+ <para>Additionally, Nping offers a special mode of operation called
+ the "Echo Mode", that lets users see how the generated probes change
+ in transit, revealing the differences between the transmitted packets and
+ the packets received at the other end. See section "Echo Mode" for details.
+ </para>
+
+ <para>The output from Nping is a list of the packets that are being sent
+ and received. The level of detail depends on the options used.</para>
+<!--
+ <para>Additionally, Nping can provide further information on targets,
+ including reverse DNS names and MAC addresses.</para>
+-->
+
+ <para>A typical Nping execution is shown in <xref linkend="nping-man-ex-repping" xrefstyle="select: label nopage"/>. The only Nping arguments used in
+ this example are <option>-c</option>, to specify the number of times to
+ target each host, <option>--tcp</option> to specify TCP Probe Mode,
+ <option>-p 80,433</option> to specify the target ports; and then the two
+ target hostnames.</para>
+
+<example id="nping-man-ex-repping"><title>A representative Nping execution</title>
+<indexterm><primary><option>-c</option> (Nping option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>--tcp</option> (Nping option)</primary><secondary>example of</secondary></indexterm>
+<indexterm><primary><option>-p</option> (Nping option)</primary><secondary>example of</secondary></indexterm>
+<screen format="linespecific">
+# <userinput>nping -c 1 --tcp -p 80,433 scanme.nmap.org google.com</userinput>
+
+Starting Nping ( https://nmap.org/nping )
+SENT (0.0120s) TCP 96.16.226.135:50091 &gt; 64.13.134.52:80 S ttl=64 id=52072 iple<continuation/>n=40 seq=1077657388 win=1480
+RCVD (0.1810s) TCP 64.13.134.52:80 &gt; 96.16.226.135:50091 SA ttl=53 id=0 iplen=4<continuation/>4 seq=4158134847 win=5840 &lt;mss 1460&gt;
+SENT (1.0140s) TCP 96.16.226.135:50091 &gt; 74.125.45.100:80 S ttl=64 id=13932 ipl<continuation/>en=40 seq=1077657388 win=1480
+RCVD (1.1370s) TCP 74.125.45.100:80 &gt; 96.16.226.135:50091 SA ttl=52 id=52913 ip<continuation/>len=44 seq=2650443864 win=5720 &lt;mss 1430&gt;
+SENT (2.0140s) TCP 96.16.226.135:50091 &gt; 64.13.134.52:433 S ttl=64 id=8373 iple<continuation/>n=40 seq=1077657388 win=1480
+SENT (3.0140s) TCP 96.16.226.135:50091 &gt; 74.125.45.100:433 S ttl=64 id=23624 ip<continuation/>len=40 seq=1077657388 win=1480
+
+Statistics for host scanme.nmap.org (64.13.134.52):
+ | Probes Sent: 2 | Rcvd: 1 | Lost: 1 (50.00%)
+ |_ Max rtt: 169.720ms | Min rtt: 169.720ms | Avg rtt: 169.720ms
+Statistics for host google.com (74.125.45.100):
+ | Probes Sent: 2 | Rcvd: 1 | Lost: 1 (50.00%)
+ |_ Max rtt: 122.686ms | Min rtt: 122.686ms | Avg rtt: 122.686ms
+Raw packets sent: 4 (160B) | Rcvd: 2 (92B) | Lost: 2 (50.00%)
+Tx time: 3.00296s | Tx bytes/s: 53.28 | Tx pkts/s: 1.33
+Rx time: 3.00296s | Rx bytes/s: 30.64 | Rx pkts/s: 0.67
+Nping done: 2 IP addresses pinged in 4.01 seconds
+</screen>
+</example>
+
+<!-- This para is a bit jumbled together for man page rendering reasons -->
+<para>The newest version of Nping can be obtained with Nmap at <ulink url="https://nmap.org"/>. The newest version of this man page
+is available at <ulink url="https://nmap.org/book/nping-man.html"/>.</para>
+-->
+ </refsect1>
+
+ <refsect1 id="nping-man-briefoptions">
+ <title>Options Summary</title>
+
+
+<para>This options summary is printed when Nping is run
+with no arguments. It helps people remember the most common options,
+but is no substitute for the in-depth documentation in the rest of this manual.
+Some obscure options aren't even included here.</para>
+
+<!-- sortas="#" puts it before the entries that start with '-' in the options
+ section. -->
+<indexterm class="startofrange" id="nping-usage-indexterm"><primary sortas="#">summary of options (Nping)</primary></indexterm>
+<indexterm class="startofrange" id="nping-usage-nping-indexterm"><primary>command-line options</primary><secondary>of Nping</secondary></indexterm>
+
+&nping-usage;
+
+<indexterm class="endofrange" startref="nping-usage-nping-indexterm"/>
+<indexterm class="endofrange" startref="nping-usage-indexterm"/>
+
+ </refsect1>
+
+
+ <refsect1 id="nping-man-target-specification">
+ <title>Target Specification</title>
+ <indexterm><primary>target specification</primary><secondary>in Nping</secondary></indexterm>
+
+ <para>Everything on the Nping command line that isn't an option or an
+ option argument is treated as a target host specification. Nping
+ uses the same syntax for target specifications that Nmap does. The
+ simplest case is a single target given by IP address or hostname.
+ </para>
+
+
+ <para>Nping supports
+ CIDR-style<indexterm><primary>CIDR (Classless Inter-Domain Routing)</primary></indexterm>
+ addressing. You can append <literal>/<replaceable>numbits</replaceable></literal> to an
+ IPv4 address or hostname and Nping will send probes to every IP
+ address for which the first <replaceable>numbits</replaceable> are the same as for the
+ reference IP or hostname given. For example, <literal>192.168.10.0/24</literal> would
+ send probes to the 256 hosts between 192.168.10.0
+ (binary: <literal>11000000 10101000 00001010 00000000</literal>)
+ and 192.168.10.255
+ (binary: <literal>11000000 10101000 00001010 11111111</literal>),
+ inclusive. <literal>192.168.10.40/24</literal> would ping exactly the same targets.
+ Given that the host scanme.nmap.org<indexterm><primary>scanme.nmap.org</primary></indexterm>
+ is at the IP address 64.13.134.52, the specification
+ <literal>scanme.nmap.org/16</literal> would send probes to the 65,536 IP addresses
+ between 64.13.0.0 and 64.13.255.255. The smallest allowed value is
+ <literal>/0</literal>, which targets the whole Internet. The largest value is <literal>/32</literal>,
+ which targets just the named host or IP address because all address
+ bits are fixed.
+ </para>
+
+ <indexterm><primary>address ranges</primary></indexterm>
+ <para>CIDR notation is short but not always flexible enough. For example,
+ you might want to send probes to 192.168.0.0/16 but skip any IPs
+ ending with .0 or .255 because they may be used as subnet network
+ and broadcast addresses. Nping supports this through octet range
+ addressing. Rather than specify a normal IP address, you can specify
+ a comma-separated list of numbers or ranges for each octet. For
+ example, <literal>192.168.0-255.1-254</literal> will skip all addresses in the range
+ that end in .0 or .255, and <literal>192.168.3-5,7.1</literal> will target the four
+ addresses 192.168.3.1, 192.168.4.1, 192.168.5.1, and 192.168.7.1.
+ Either side of a range may be omitted; the default values are 0 on
+ the left and 255 on the right. Using
+ <literal>-</literal> by itself is the same as <literal>0-255</literal>,
+ but remember to use <literal>0-</literal> in the first octet so the target
+ specification doesn't look like a command-line option. Ranges need
+ not be limited to the final octets: the specifier <literal>0-.-.13.37</literal> will send probes
+ to all IP addresses on the Internet ending in .13.37. This sort of
+ broad sampling can be useful for Internet surveys and research.
+ </para>
+
+ <para>IPv6 addresses can only be specified by their fully qualified IPv6
+ address or hostname. CIDR and octet ranges aren't supported for
+ IPv6 because they are rarely useful.</para>
+
+ <para>Nping accepts multiple host specifications on the command line,
+ and they don't need to be the same type. The command
+ <command>nping scanme.nmap.org
+ 192.168.0.0/8 10.0.0,1,3-7.-</command> does what you would expect.
+ </para>
+
+ </refsect1>
+
+
+ <refsect1 id="nping-man-option-specification">
+ <title>Option Specification</title>
+
+ <para>
+ Nping is designed to be very flexible and fit a wide variety of needs.
+ As with most command-line tools, its behavior can be adjusted using
+ command-line options. These general principles apply to option
+ arguments, unless stated otherwise.
+ </para>
+
+ <para>
+ Options that take integer numbers can accept values specified in
+ decimal, octal or hexadecimal base. When a number starts with <literal>0x</literal>,
+ it will be treated as hexadecimal; when it simply starts with <literal>0</literal>, it
+ will be treated as octal. Otherwise, Nping will assume the number has
+ been specified in base 10. Virtually all numbers that can be supplied
+ from the command line are unsigned so, as a general rule, the minimum
+ value is zero. Users may also specify the word <literal>random</literal> or <literal>rand</literal> to
+ make Nping generate a random value within the expected range.
+ </para>
+
+ <para>
+ IP addresses may be given as IPv4 addresses (e.g.
+ <literal>192.168.1.1</literal>), IPv6 addresses (e.g.
+ <literal>2001:db8:85a3::8e4c:760:7146</literal>), or hostnames, which
+ will be resolved using the default DNS server configured in the host
+ system.
+ </para>
+
+ <para>
+ Options that take MAC addresses accept the usual colon-separated 6 hex
+ byte format (e.g. <literal>00:50:56:d4:01:98</literal>). Hyphens may also be used instead
+ of colons (e.g. <literal>00-50-56-c0-00-08</literal>). The special
+ word <literal>random</literal> or <literal>rand</literal> sets a random
+ address and the word <literal>broadcast</literal>
+ or <literal>bcast</literal> sets ff:ff:ff:ff:ff:ff.
+ </para>
+
+ </refsect1>
+
+
+ <refsect1 id="nping-man-general-operation">
+ <title>General Operation</title>
+ <indexterm><primary>general operation</primary></indexterm>
+
+ <para>Unlike other ping and packet generation tools, Nping supports
+ multiple target host and port specifications. While
+ this provides great flexibility, it is not obvious how Nping handles
+ situations where there is more than one host and/or more than one
+ port to send probes to. This section explains how Nping behaves in
+ these cases.
+ </para>
+
+ <para>
+ When multiple target hosts are specified, Nping rotates among them
+ in round-robin fashion. This gives slow hosts more time to send
+ their responses before another probe is sent to them. Ports are
+ also scheduled using round robin. So, unless only one port is
+ specified, Nping never sends two probes to the same target host and
+ port consecutively.
+ </para>
+
+ <para>
+ The loop around targets is the <quote>inner loop</quote> and the
+ loop around ports is the <quote>outer loop</quote>. All targets
+ will be sent a probe for a given port before moving on to the next
+ port. Between probes, Nping waits a configurable amount of time
+ called the <quote>inter-probe delay</quote>, which is controlled by
+ the <option>--delay</option> option. These examples show how it
+ works.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ <para>One target, three ports, and two rounds.</para>
+ </term>
+ <listitem>
+<screen>
+# <userinput>nping --tcp -c 2 1.1.1.1 -p 100-102</userinput>
+
+Starting Nping ( https://nmap.org/nping )
+SENT (0.0210s) TCP 192.168.1.77 &gt; 1.1.1.1:100
+SENT (1.0230s) TCP 192.168.1.77 &gt; 1.1.1.1:101
+SENT (2.0250s) TCP 192.168.1.77 &gt; 1.1.1.1:102
+SENT (3.0280s) TCP 192.168.1.77 &gt; 1.1.1.1:100
+SENT (4.0300s) TCP 192.168.1.77 &gt; 1.1.1.1:101
+SENT (5.0320s) TCP 192.168.1.77 &gt; 1.1.1.1:102
+</screen>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <para>Three targets, one port, and two rounds.</para>
+ </term>
+ <listitem>
+<screen>
+# <userinput>nping --tcp -c 2 1.1.1.1 2.2.2.2 3.3.3.3 -p 8080</userinput>
+
+Starting Nping ( https://nmap.org/nping )
+SENT (0.0230s) TCP 192.168.0.21 &gt; 1.1.1.1:8080
+SENT (1.0240s) TCP 192.168.0.21 &gt; 2.2.2.2:8080
+SENT (2.0260s) TCP 192.168.0.21 &gt; 3.3.3.3:8080
+SENT (3.0270s) TCP 192.168.0.21 &gt; 1.1.1.1:8080
+SENT (4.0290s) TCP 192.168.0.21 &gt; 2.2.2.2:8080
+SENT (5.0310s) TCP 192.168.0.21 &gt; 3.3.3.3:8080
+</screen>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <para>Three hosts, three ports, one round, inter-probe delay of 500&nbsp;ms.</para>
+ </term>
+ <listitem>
+<screen>
+# <userinput>nping --tcp -c 1 --delay 500ms 1.1.1.1 2.2.2.2 3.3.3.3 -p 137-139</userinput>
+
+Starting Nping ( https://nmap.org/nping )
+SENT (0.0230s) TCP 192.168.0.21 &gt; 1.1.1.1:137
+SENT (0.5250s) TCP 192.168.0.21 &gt; 2.2.2.2:137
+SENT (1.0250s) TCP 192.168.0.21 &gt; 3.3.3.3:137
+SENT (1.5280s) TCP 192.168.0.21 &gt; 1.1.1.1:138
+SENT (2.0280s) TCP 192.168.0.21 &gt; 2.2.2.2:138
+SENT (2.5310s) TCP 192.168.0.21 &gt; 3.3.3.3:138
+SENT (3.0300s) TCP 192.168.0.21 &gt; 1.1.1.1:139
+SENT (3.5330s) TCP 192.168.0.21 &gt; 2.2.2.2:139
+SENT (4.0330s) TCP 192.168.0.21 &gt; 3.3.3.3:139
+</screen>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+
+ <refsect1 id="nping-man-probe-modes">
+ <title>Probe Modes</title>
+ <indexterm class="startofrange" id="nping-man-probe-modes-indexterm"><primary>probe modes</primary></indexterm>
+
+ <para>Nping supports a wide variety of protocols. Although in some cases
+ Nping can automatically determine the mode from the options used, it
+ is generally a good idea to specify it explicitly.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--tcp-connect</option> (TCP Connect mode)
+ <indexterm><primary><option>--tcp-connect</option> (Nping option)</primary></indexterm>
+ <indexterm><primary>TCP connect</primary><secondary>in Nping</secondary></indexterm>
+ <indexterm><primary>TCP connect</primary><seealso>connect scan</seealso></indexterm>
+ </term>
+ <listitem>
+ <para>TCP connect mode is the default mode when a user does not have
+ raw packet privileges. Instead of writing raw packets as most
+ other modes do, Nping asks the underlying operating system to
+ establish a connection with the target machine and port by
+ issuing the <literal>connect</literal> system call. This is the same high-level
+ system call that web browsers, P2P clients, and most other
+ network-enabled applications use to establish a connection.
+ It is part of a programming interface known as the Berkeley
+ Sockets API. Rather than read raw packet responses off the wire,
+ Nping uses this API to obtain status information on each
+ connection attempt. For this reason, you will not be able to
+ see the contents of the packets that are sent or received but
+ only status information about the TCP connection establishment
+ taking place.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--tcp</option> (TCP mode)
+ <indexterm><primary><option>--tcp</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>TCP is the mode that lets users create and send any kind of TCP
+ packet. TCP packets are sent embedded in IP packets that
+ can also be tuned. This mode can be used for many different
+ purposes. For example you could try to discover open ports by
+ sending TCP SYN messages without completing the three-way
+ handshake. This technique is often referred to as half-open
+ scanning, because you don't open a full TCP connection.
+ You send a SYN packet, as if you are going to open a real
+ connection and then wait for a response. A SYN/ACK indicates
+ the port is open, while a RST indicates it's closed. If no
+ response is received one could assume that some intermediate
+ network device is filtering the responses. Another use could be
+ to see how a remote TCP/IP stack behaves when it receives a
+ non-RFC-compliant packet, like one with both SYN and
+ RST flags set. One could also do some evil by creating custom
+ RST packets using an spoofed IP address with the intent of
+ closing an active TCP connection.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--udp</option> (UDP mode)
+ <indexterm><primary><option>--udp</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>UDP mode can have two different behaviours. Under normal
+ circumstances, it lets users create custom IP/UDP packets.
+ However, if Nping is run by a user without raw packet privileges
+ and no changes to the default protocol headers are requested,
+ then Nping enters the unprivileged UDP mode which basically sends
+ UDP packets to the specified target hosts and ports using the
+ <literal>sendto</literal> system call. Note that in this unprivileged mode it is
+ not possible to see low-level header information of the packets
+ on the wire but only status information about the amount of bytes
+ that are being transmitted and received. UDP mode can be used to
+ interact with any UDP-based server. Examples are DNS servers,
+ streaming servers, online gaming servers, and
+ port knocking/single-packet<indexterm><primary>port knocking</primary></indexterm>
+ authorization daemons.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp</option> (ICMP mode)
+ <indexterm><primary><option>--icmp</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>ICMP mode is the default mode when the user runs Nping with
+ raw packet privileges. Any kind of ICMP message can be created.
+ The default ICMP type is Echo, i.e., ping. ICMP mode can be used
+ for many different purposes, from a simple request for a
+ timestamp or a netmask to the transmission of fake destination
+ unreachable messages, custom redirects, and router
+ advertisements.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--arp</option> (ARP/RARP mode)
+ <indexterm><primary><option>--arp</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>ARP lets you create and send a few different ARP-related packets.
+ These include ARP, RARP, DRARP, and InARP requests and replies.
+ This mode can ban be used to perform low-level host discovery,
+ and conduct ARP-cache poisoning attacks.</para>
+ </listitem>
+ </varlistentry>
+
+
+
+ <varlistentry>
+ <term>
+ <option>--traceroute</option> (Traceroute mode)
+ <indexterm><primary><option>--tcp-connect</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>Traceroute is not a mode by itself but a complement to
+ TCP, UDP, and ICMP modes. When this option is specified Nping
+ will set the IP TTL value of the first probe to 1. When the
+ next router receives the packet it will drop it due to
+ the expiration of the TTL and it will generate an ICMP
+ destination unreachable message. The next probe will have a TTL
+ of 2 so now the first router will forward the packet while the
+ second router will be the one that drops the packet and
+ generates the ICMP message. The third probe will have a TTL value
+ of 3 and so on. By examining the source addresses of all
+ those ICMP Destination Unreachable messages it is possible to
+ determine the path that the probes take until they reach their
+ final destination.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ <indexterm class="endofrange" startref="nping-man-probe-modes-indexterm"/>
+ </refsect1>
+
+
+
+<!-- TCP CONNECT MODE ****************************************************** -->
+ <refsect1 id="nping-man-tcp-connect-mode">
+ <title>TCP Connect Mode</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>-p <replaceable>port_spec</replaceable></option>,
+ <option>--dest-port <replaceable>port_spec</replaceable></option> (Target ports)
+ <indexterm significance="preferred"><primary><option>--dest-port</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-p</option> (Nping option)</primary><see><option>--dest-port</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which ports you want to try to connect to.
+ It can be a single port, a comma-separated list of
+ ports (e.g. <literal>80,443,8080</literal>), a range
+ (e.g. <literal>1-1023</literal>), and any combination
+ of those (e.g. <literal>21-25,80,443,1024-2048</literal>).
+ The beginning and/or end values
+ of a range may be omitted, causing Nping to use 1 and 65535,
+ respectively. So you can specify <literal>-p-</literal> to target ports from 1 through
+ 65535. Using port zero is allowed if you specify it explicitly.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-g <replaceable>portnumber</replaceable></option>,
+ <option>--source-port <replaceable>portnumber</replaceable></option> (Spoof source port)
+ <indexterm significance="preferred"><primary><option>--source-port</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-g</option> (Nping option)</primary><see><option>--source-port</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks Nping to use the specified port as source port for
+ the TCP connections. Note that this might not work on all systems or
+ may require root privileges. Specified value must be an integer in
+ the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+<!-- TCP MODE ************************************************************** -->
+ <refsect1 id="nping-man-tcp-mode">
+ <title>TCP Mode</title>
+
+ <variablelist>
+
+
+ <varlistentry>
+ <term>
+ <option>-p <replaceable>port_spec</replaceable></option>,
+ <option>--dest-port <replaceable>port_spec</replaceable></option> (Target ports)
+ </term>
+ <listitem>
+ <para>
+ This option specifies which destination ports you want to send
+ probes to. It can be a single port, a comma-separated list of
+ ports (e.g. <literal>80,443,8080</literal>), a range
+ (e.g. <literal>1-1023</literal>), and any combination
+ of those (e.g. <literal>21-25,80,443,1024-2048</literal>).
+ The beginning and/or end values
+ of a range may be omitted, causing Nping to use 1 and 65535,
+ respectively. So you can specify <literal>-p-</literal> to target ports from 1 through
+ 65535. Using port zero is allowed if you specify it explicitly.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-g <replaceable>portnumber</replaceable></option>,
+ <option>--source-port <replaceable>portnumber</replaceable></option> (Spoof source port)
+ </term>
+ <listitem>
+ <para>
+ This option asks Nping to use the specified port as source port for
+ the TCP connections. Note that this might not work on all systems or
+ may require root privileges. Specified value must be an integer in
+ the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--seq <replaceable>seqnumber</replaceable></option> (Sequence Number)
+ <indexterm significance="preferred"><primary><option>--seq</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Specifies the TCP sequence number. In SYN packets this is the initial
+ sequence number (ISN). In a normal transmission this corresponds to
+ the sequence number of the first byte of data in the segment.
+ <replaceable>seqnumber</replaceable> must be a number in the range
+ [0&ndash;4294967295].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--flags <replaceable>flags</replaceable></option> (TCP Flags)
+ <indexterm significance="preferred"><primary><option>--flags</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which flags should be set in the TCP packet.
+ <replaceable>flags</replaceable> may be specified in three different
+ ways:
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>As a comma-separated list of flags, e.g. <option>--flags syn,ack,rst</option></para>
+ </listitem>
+ <listitem>
+ <para>As a list of one-character flag initials, e.g. <option>--flags SAR</option> tells Nping to set flags SYN, ACK, and RST.</para>
+ </listitem>
+ <listitem>
+ <para>As an 8-bit hexadecimal number, where the supplied number
+ is the exact value that will be placed in the flags field of the
+ TCP header. The number should start with the prefix
+ <literal>0x</literal> and should be in the range
+ [0x00&ndash;0xFF], e.g. <literal>--flags 0x20</literal> sets the
+ URG flag as 0x20 corresponds to binary 00100000 and the URG flag
+ is represented by the third bit.</para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ There are 8 possible flags to set:
+ <literal>CWR</literal>,
+ <literal>ECN</literal>,
+ <literal>URG</literal>,
+ <literal>ACK</literal>,
+ <literal>PSH</literal>,
+ <literal>RST</literal>,
+ <literal>SYN</literal>, and
+ <literal>FIN</literal>.
+ The special value <literal>ALL</literal> means to set all flags.
+ <literal>NONE</literal> means to set no flags. It is important that
+ if you don't want any flag to be set, you request it explicitly
+ because in some cases the SYN flag may be set by default. Here is a
+ brief description of the meaning of each flag:
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>
+ CWR (Congestion Window Reduced)
+ <indexterm><primary>CWR (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Set by an ECN-Capable sender
+ when it reduces its congestion window (due to a retransmit
+ timeout, a fast retransmit or in response to an ECN
+ notification.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ ECN (Explicit Congestion Notification)
+ <indexterm><primary>ECN (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ During the three-way
+ handshake it indicates that sender is capable of performing
+ explicit congestion notification. Normally it means that a
+ packet with the IP Congestion Experienced flag set was received
+ during normal transmission. See
+ RFC 3168<indexterm><primary>RFC 3168</primary></indexterm>
+ for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ URG (Urgent)
+ <indexterm><primary>URG (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Segment is urgent and the urgent pointer field
+ carries valid information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ ACK (Acknowledgement)
+ <indexterm><primary>ACK (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ The segment carries an acknowledgement
+ and the value of the acknowledgement number field is valid and
+ contains the next sequence number that is expected from the
+ receiver.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ PSH (Push)
+ <indexterm><primary>PSH (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ The data in this segment should be immediately
+ pushed to the application layer on arrival.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ RST (Reset)
+ <indexterm><primary>RST (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ There was some problem and the sender wants to
+ abort the connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ SYN (Synchronize)
+ <indexterm><primary>SYN (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ The segment is a request to synchronize
+ sequence numbers and establish a connection. The sequence
+ number field contains the sender's initial sequence
+ number.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ FIN (Finish)
+ <indexterm><primary>FIN (TCP flag)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ The sender wants to close the connection.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+
+
+
+ <varlistentry>
+ <term>
+ <option>--win <replaceable>size</replaceable></option> (Window Size)
+ <indexterm significance="preferred"><primary><option>--win</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Specifies the TCP window size, this is, the number of octets the
+ sender of the segment is willing to accept from the receiver at one
+ time. This is usually the size of the reception buffer that the OS
+ allocates for a given connection. <replaceable>size</replaceable>
+ must be a number in the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--badsum</option> (Invalid Checksum)
+ <indexterm significance="preferred"><primary><option>--badsum</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Asks Nping to use an invalid TCP checksum for the packets sent to
+ target hosts. Since virtually all host IP stacks properly drop these
+ packets, any responses received are likely coming from a firewall or
+ an IDS that didn't bother to verify the checksum. For more
+ details on this technique, see
+ <ulink url="https://nmap.org/p60-12.html"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+<!-- UDP MODE ************************************************************** -->
+ <refsect1 id="nping-man-udp-mode">
+ <title>UDP Mode</title>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>-p <replaceable>port_spec</replaceable></option>,
+ <option>--dest-port <replaceable>port_spec</replaceable></option> (Target ports)
+ <indexterm significance="preferred"><primary><option>--dest-port</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which ports you want UDP datagrams to be sent to.
+ It can be a single port, a comma-separated list of
+ ports (e.g. <literal>80,443,8080</literal>), a range
+ (e.g. <literal>1-1023</literal>), and any combination
+ of those (e.g. <literal>21-25,80,443,1024-2048</literal>).
+ The beginning and/or end values
+ of a range may be omitted, causing Nping to use 1 and 65535,
+ respectively. So you can specify <literal>-p-</literal> to target ports from 1 through
+ 65535. Using port zero is allowed if you specify it explicitly.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-g <replaceable>portnumber</replaceable></option>,
+ <option>--source-port <replaceable>portnumber</replaceable></option> (Spoof source port)
+ <indexterm significance="preferred"><primary><option>--source-port</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks Nping to use the specified port as source port for
+ the transmitted datagrams. Note that this might not work on all systems or
+ may require root privileges. Specified value must be an integer in
+ the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--badsum</option> (Invalid Checksum)
+ </term>
+ <listitem>
+ <para>
+ Asks Nping to use an invalid UDP checksum for the packets sent to
+ target hosts. Since virtually all host IP stacks properly drop these
+ packets, any responses received are likely coming from a firewall or
+ an IDS that didn't bother to verify the checksum. For more
+ details on this technique, see
+ <ulink url="https://nmap.org/p60-12.html"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+<!-- ICMP MODE ************************************************************* -->
+ <refsect1 id="nping-man-icmp-mode">
+ <title>ICMP Mode</title>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--icmp-type <replaceable>type</replaceable></option> (ICMP type)
+ <indexterm significance="preferred"><primary><option>--icmp-type</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which type of ICMP messages should be
+ generated. <replaceable>type</replaceable> can be supplied in
+ two different ways. You can use the
+ <ulink url="http://www.iana.org/assignments/icmp-parameters">official type numbers assigned by IANA</ulink>
+ (e.g. <option>--icmp-type 8</option> for ICMP Echo Request), or you
+ can use any of the mnemonics listed in
+ <xref linkend="nping-man-icmp-types"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-code <replaceable>code</replaceable></option> (ICMP code)
+ <indexterm significance="preferred"><primary><option>--icmp-code</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which ICMP code should be included in
+ the generated ICMP messages. <replaceable>code</replaceable> can be
+ supplied in two different ways. You can use the
+ <ulink url="http://www.iana.org/assignments/icmp-parameters">official code numbers assigned by IANA</ulink>
+ (e.g. <option>--icmp-code 1</option> for Fragment Reassembly Time
+ Exceeded), or you can use any of the mnemonics listed in
+ <xref linkend="nping-man-icmp-codes"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-id <replaceable>id</replaceable></option> (ICMP identifier)
+ <indexterm significance="preferred"><primary><option>--icmp-id</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies the value of the identifier used in some of
+ the ICMP messages. In general it is used to match request and
+ reply messages. <replaceable>id</replaceable> must be a number in
+ the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-seq <replaceable>seq</replaceable></option> (ICMP sequence)
+ <indexterm significance="preferred"><primary><option>--icmp-seq</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies the value of the sequence number field used
+ in some ICMP messages. In general it is used to match request and
+ reply messages. <replaceable>id</replaceable> must be a number in
+ the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-redirect-addr <replaceable>addr</replaceable></option> (ICMP Redirect address)
+ <indexterm significance="preferred"><primary><option>--icmp-redirect-addr</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the address field in ICMP Redirect messages. In
+ other words, it sets the IP address of the router that should be
+ used when sending IP datagrams to the original destination.
+ <replaceable>addr</replaceable> can be either an IPv4 address
+ or a hostname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-param-pointer <replaceable>pointer</replaceable></option> (ICMP Parameter Problem pointer)
+ <indexterm significance="preferred"><primary><option>--icmp-param-pointer</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies the pointer that indicates the location of
+ the problem in ICMP Parameter Problem messages. <replaceable>pointer</replaceable>
+ should be a number in the range [0&ndash;255]. Normally this option is
+ only used when ICMP code is set to 0 ("Pointer indicates the error").
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-advert-lifetime <replaceable>ttl</replaceable></option> (ICMP Router Advertisement Lifetime)
+ <indexterm significance="preferred"><primary><option>--icmp-advert-lifetime</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies the router advertisement lifetime, this is,
+ the number of seconds the information carried in an ICMP Router
+ Advertisement can be considered valid for. <replaceable>ttl</replaceable>
+ must be a positive integer in the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-advert-entry <replaceable>addr</replaceable>,<replaceable>pref</replaceable></option> (ICMP Router Advertisement Entry)
+ <indexterm significance="preferred"><primary><option>--icmp-advert-entry</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option adds a Router Advertisement entry to an ICMP Router
+ Advertisement message. The parameter must be two
+ values separated by a comma. <replaceable>addr</replaceable> is
+ the router's IP and can be specified either as an IP address in
+ dot-decimal notation or as a hostname. <replaceable>pref</replaceable>
+ is the preference level for the specified IP. It must be a number
+ in the range [0&ndash;4294967295]. An example is
+ <option>--icmp-advert-entry 192.168.128.1,3</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+
+ <varlistentry>
+ <term>
+ <option>--icmp-orig-time <replaceable>timestamp</replaceable></option> (ICMP Originate Timestamp)
+ <indexterm significance="preferred"><primary><option>--icmp-orig-time</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Originate Timestamp in ICMP Timestamp messages.
+ The Originate Timestamp is expressed as the number of milliseconds
+ since midnight UTC and it corresponds to the time the sender
+ last touched the Timestamp message before its transmission.
+ <replaceable>timestamp</replaceable> can be specified as a regular
+ time (e.g. <literal>10s</literal>, <literal>3h</literal>, <literal>1000ms</literal>), or the special string
+ <literal>now</literal>. You can add or subtract
+ values from <literal>now</literal>, for example
+ <option>--icmp-orig-time now-2s</option>,
+ <option>--icmp-orig-time now+1h</option>,
+ <option>--icmp-orig-time now+200ms</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--icmp-recv-time <replaceable>timestamp</replaceable></option> (ICMP Receive Timestamp)
+ <indexterm significance="preferred"><primary><option>--icmp-recv-time</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Receive Timestamp in ICMP Timestamp messages.
+ The Receive Timestamp is expressed as the number of milliseconds
+ since midnight UTC and it corresponds to the time the echoer
+ first touched the Timestamp message on receipt.
+ <replaceable>timestamp</replaceable> is as with
+ <option>--icmp-orig-time</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--icmp-trans-time <replaceable>timestamp</replaceable></option> (ICMP Transmit Timestamp)
+ <indexterm significance="preferred"><primary><option>--icmp-trans-time</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Transmit Timestamp in ICMP Timestamp messages.
+ The Transmit Timestamp is expressed as the number of milliseconds
+ since midnight UTC and it corresponds to the time the echoer
+ last touched the Timestamp message before its transmission.
+ <replaceable>timestamp</replaceable> is as with
+ <option>--icmp-orig-time</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <refsect2 id="nping-man-icmp-types">
+ <indexterm class="startofrange" id="nping-man-icmp-types-indexterm"><primary>ICMP types</primary><secondary>mnemonics of, in Nping</secondary></indexterm>
+ <title>ICMP Types</title>
+
+ <para>
+ These identifiers may be used as mnemonics for the ICMP type numbers given
+ to the
+ <option>--icmp-type</option><indexterm><primary><option>--icmp-type</option> (Nping option)</primary></indexterm>
+ option. In general there are three forms of each identifier: the full name
+ (e.g. <literal>destination-unreachable</literal>), the short name (e.g.
+ <literal>dest-unr</literal>), or the initials (e.g. <literal>du</literal>).
+ In ICMP types that request something, the word "request" is omitted.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>echo-reply</literal></term>
+ <term><literal>echo-rep</literal></term>
+ <term><literal>er</literal></term>
+ <listitem>
+ <para>
+ Echo Reply (type 0). This message is sent in response to an Echo
+ Request message.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>destination-unreachable</literal></term>
+ <term><literal>dest-unr</literal></term>
+ <term><literal>du</literal></term>
+ <listitem>
+ <para>
+ Destination Unreachable (type 3). This message indicates that
+ a datagram could not be delivered to its destination.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>source-quench</literal></term>
+ <term><literal>sour-que</literal></term>
+ <term><literal>sq</literal></term>
+ <listitem>
+ <para>
+ Source Quench (type 4). This message is used by a congested
+ IP device to tell other device that is sending packets too fast
+ and that it should slow down.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>redirect</literal></term>
+ <term><literal>redi</literal></term>
+ <term><literal>r</literal></term>
+ <listitem>
+ <para>
+ Redirect (type 5). This message is normally used by routers
+ to inform a host that there is a better route to use for sending
+ datagrams. See also the <option>--icmp-redirect-addr</option>
+ option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>echo-request</literal></term>
+ <term><literal>echo</literal></term>
+ <term><literal>e</literal></term>
+ <listitem>
+ <para>
+ Echo Request (type 8). This message is used to test the
+ connectivity of another device on a network.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>router-advertisement</literal></term>
+ <term><literal>rout-adv</literal></term>
+ <term><literal>ra</literal></term>
+ <listitem>
+ <para>
+ Router Advertisement (type 9). This message is used by
+ routers to let hosts know of their existence and capabilities. See
+ also the <option>--icmp-advert-lifetime</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>router-solicitation</literal></term>
+ <term><literal>rout-sol</literal></term>
+ <term><literal>rs</literal></term>
+ <listitem>
+ <para>
+ Router Solicitation (type 10). This message is used by hosts
+ to request Router Advertisement messages from any listening
+ routers.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>time-exceeded</literal></term>
+ <term><literal>time-exc</literal></term>
+ <term><literal>te</literal></term>
+ <listitem>
+ <para>
+ Time Exceeded (type 11). This message is generated by some
+ intermediate device (normally a router) to indicate that a datagram
+ has been discarded before reaching its destination because the
+ IP TTL expired.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>parameter-problem</literal></term>
+ <term><literal>member-pro</literal></term>
+ <term><literal>pp</literal></term>
+ <listitem>
+ <para>
+ Parameter Problem (type 12). This message is used when a device
+ finds a problem with a parameter in an IP header and it cannot
+ continue processing it. See also the
+ <option>--icmp-param-pointer</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>timestamp</literal></term>
+ <term><literal>time</literal></term>
+ <term><literal>tm</literal></term>
+ <listitem>
+ <para>
+ Timestamp Request (type 13). This message is used to request
+ a device to send a timestamp value for propagation time
+ calculation and clock synchronization. See also the
+ <option>--icmp-orig-time</option>,
+ <option>--icmp-recv-time</option>, and
+ <option>--icmp-trans-time</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>timestamp-reply</literal></term>
+ <term><literal>time-rep</literal></term>
+ <term><literal>tr</literal></term>
+ <listitem>
+ <para>
+ Timestamp Reply (type 14). This message is sent in response
+ to a Timestamp Request message.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>information</literal></term>
+ <term><literal>info</literal></term>
+ <term><literal>i</literal></term>
+ <listitem>
+ <para>
+ Information Request (type 15). This message is now obsolete
+ but it was originally used to request configuration information
+ from another device.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>information-reply</literal></term>
+ <term><literal>info-rep</literal></term>
+ <term><literal>ir</literal></term>
+ <listitem>
+ <para>
+ Information Reply (type 16). This message is now obsolete but
+ it was originally sent in response to an Information Request
+ message to provide configuration information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mask-request</literal></term>
+ <term><literal>mask</literal></term>
+ <term><literal>m</literal></term>
+ <listitem>
+ <para>
+ Address Mask Request (type 17). This message is used to
+ ask a device to send its subnet mask.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mask-reply</literal></term>
+ <term><literal>mask-rep</literal></term>
+ <term><literal>mr</literal></term>
+ <listitem>
+ <para>
+ Address Mask Reply (type 18). This message contains a subnet
+ mask and is sent in response to a Address Mask Request message.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>traceroute</literal></term>
+ <term><literal>trace</literal></term>
+ <term><literal>tc</literal></term>
+ <listitem>
+ <para>
+ Traceroute (type 30). This message is normally sent
+ by an intermediate device when it receives an IP datagram
+ with a traceroute option. ICMP Traceroute messages are still
+ experimental, see
+ RFC 1393<indexterm><primary>RFC 1393</primary></indexterm>
+ for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <indexterm class="endofrange" startref="nping-man-icmp-types-indexterm"/>
+ </refsect2>
+
+ <refsect2 id="nping-man-icmp-codes">
+ <indexterm class="startofrange" id="nping-man-icmp-codes-indexterm"><primary>ICMP codes</primary><secondary>mnemonics of, in Nping</secondary></indexterm>
+ <title>ICMP Codes</title>
+
+ <para>
+ These identifiers may be used as mnemonics for the ICMP code numbers given
+ to the
+ <option>--icmp-code</option><indexterm><primary><option>--icmp-code</option> (Nping option)</primary></indexterm>
+ option. They are listed by the ICMP type they correspond to.
+ </para>
+
+ <refsect3>
+ <title>Destination Unreachable</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>network-unreachable</literal></term>
+ <term><literal>netw-unr</literal></term>
+ <term><literal>net</literal></term>
+ <listitem>
+ <para>
+ Code 0. Datagram could not be delivered to its destination
+ network (probably due to some routing problem).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-unreachable</literal></term>
+ <term><literal>host-unr</literal></term>
+ <term><literal>host</literal></term>
+ <listitem>
+ <para>
+ Code 1. Datagram was delivered to the destination network but it
+ was impossible to reach the specified host (probably due to some
+ routing problem).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>protocol-unreachable</literal></term>
+ <term><literal>prot-unr</literal></term>
+ <term><literal>proto</literal></term>
+ <listitem>
+ <para>
+ Code 2. The protocol specified in the Protocol field of the IP
+ datagram is not supported by the host to which the datagram was
+ delivered.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>port-unreachable</literal></term>
+ <term><literal>port-unr</literal></term>
+ <term><literal>port</literal></term>
+ <listitem>
+ <para>
+ Code 3. The TCP/UDP destination port was invalid.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>needs-fragmentation</literal></term>
+ <term><literal>need-fra</literal></term>
+ <term><literal>frag</literal></term>
+ <listitem>
+ <para>
+ Code 4. Datagram had the DF bit set but it was too large for the
+ MTU of the next physical network so it had to be dropped.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>source-route-failed</literal></term>
+ <term><literal>sour-rou</literal></term>
+ <term><literal>routefail</literal></term>
+ <listitem>
+ <para>
+ Code 5. IP datagram had a Source Route option but a router
+ couldn't pass it to the next hop.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>network-unknown</literal></term>
+ <term><literal>netw-unk</literal></term>
+ <term><literal>net?</literal></term>
+ <listitem>
+ <para>
+ Code 6. Destination network is unknown. This code is never used.
+ Instead, Network Unreachable is used.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-unknown</literal></term>
+ <term><literal>host-unk</literal></term>
+ <term><literal>host?</literal></term>
+ <listitem>
+ <para>
+ Code 7. Specified host is unknown. Usually generated by a router
+ local to the destination host to inform of a bad address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-isolated</literal></term>
+ <term><literal>host-iso</literal></term>
+ <term><literal>isolated</literal></term>
+ <listitem>
+ <para>
+ Code 8. Source Host Isolated. Not used.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>network-prohibited</literal></term>
+ <term><literal>netw-pro</literal></term>
+ <term><literal>!net</literal></term>
+ <listitem>
+ <para>
+ Code 9. Communication with destination network is
+ administratively prohibited (source device is not allowed to send
+ packets to the destination network).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-prohibited</literal></term>
+ <term><literal>host-pro</literal></term>
+ <term><literal>!host</literal></term>
+ <listitem>
+ <para>
+ Code 10. Communication with destination host is administratively
+ prohibited. (The source device is allowed to send packets to the
+ destination network but not to the destination device.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>network-tos</literal></term>
+ <term><literal>unreachable-network-tos</literal></term>
+ <term><literal>netw-tos</literal></term>
+ <term><literal>tosnet</literal></term>
+ <listitem>
+ <para>
+ Code 11. Destination network unreachable because it cannot
+ provide the type of service specified in the IP TOS field.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-tos</literal></term>
+ <term><literal>unreachable-host-tos</literal></term>
+ <term><literal>toshost</literal></term>
+ <listitem>
+ <para>
+ Code 12. Destination host unreachable because it cannot provide
+ the type of service specified in the IP TOS field.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>communication-prohibited</literal></term>
+ <term><literal>comm-pro</literal></term>
+ <term><literal>!comm</literal></term>
+ <listitem>
+ <para>
+ Code 13. Datagram could not be forwarded due to filtering that
+ blocks the message based on its contents.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>host-precedence-violation</literal></term>
+ <term><literal>precedence-violation</literal></term>
+ <term><literal>prec-vio</literal></term>
+ <term><literal>violation</literal></term>
+ <listitem>
+ <para>
+ Code 14. Precedence value in the IP TOS field is not permitted.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>precedence-cutoff</literal></term>
+ <term><literal>prec-cut</literal></term>
+ <term><literal>cutoff</literal></term>
+ <listitem>
+ <para>
+ Code 15. Precedence value in the IP TOS field is lower than the
+ minimum allowed for the network.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+
+ <refsect3>
+ <title>Redirect</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>redirect-network</literal></term>
+ <term><literal>redi-net</literal></term>
+ <term><literal>net</literal></term>
+ <listitem>
+ <para>
+ Code 0. Redirect all future datagrams with the same destination
+ network as the original datagram, to the router specified in the
+ Address field. The use of this code is prohibited by
+ RFC 1812.<indexterm><primary>RFC 1812</primary></indexterm>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>redirect-host</literal></term>
+ <term><literal>redi-host</literal></term>
+ <term><literal>host</literal></term>
+ <listitem>
+ <para>
+ Code 1. Redirect all future datagrams with the same destination
+ host as the original datagram, to the router specified in the
+ Address field.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>redirect-network-tos</literal></term>
+ <term><literal>redi-ntos</literal></term>
+ <term><literal>redir-ntos</literal></term>
+ <listitem>
+ <para>
+ Code 2. Redirect all future datagrams with the same destination
+ network and IP TOS value as the original datagram, to the router
+ specified in the Address field. The use of this code is
+ prohibited by RFC 1812.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>redirect-host-tos</literal></term>
+ <term><literal>redi-htos</literal></term>
+ <term><literal>redir-htos</literal></term>
+ <listitem>
+ <para>
+ Code 3. Redirect all future datagrams with the same destination
+ host and IP TOS value as the original datagram, to the router
+ specified in the Address field.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+
+ <refsect3>
+ <title>Router Advertisement</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>normal-advertisement</literal></term>
+ <term><literal>norm-adv</literal></term>
+ <term><literal>normal</literal></term>
+ <term><literal>zero</literal></term>
+ <term><literal>default</literal></term>
+ <term><literal>def</literal></term>
+ <listitem>
+ <para>
+ Code 0. Normal router advertisement. In Mobile IP: Mobility agent
+ can act as a router for IP datagrams not related to mobile nodes.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>not-route-common-traffic</literal></term>
+ <term><literal>not-rou</literal></term>
+ <term><literal>mobile-ip</literal></term>
+ <term><literal>!route</literal></term>
+ <term><literal>!commontraffic</literal></term>
+ <listitem>
+ <para>
+ Code 16. Used for Mobile IP. The mobility agent does not route
+ common traffic. All foreign agents must forward to a default
+ router any datagrams received from a registered mobile node
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+
+ <refsect3>
+ <title>Time Exceeded</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>ttl-exceeded-in-transit</literal></term>
+ <term><literal>ttl-exc</literal></term>
+ <term><literal>ttl-transit</literal></term>
+ <listitem>
+ <para>
+ Code 0. IP Time To Live expired during transit.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>fragment-reassembly-time-exceeded</literal></term>
+ <term><literal>frag-exc</literal></term>
+ <term><literal>frag-time</literal></term>
+ <listitem>
+ <para>
+ Code 1. Fragment reassembly time has been exceeded.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+
+ <refsect3>
+ <title>Parameter Problem</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>pointer-indicates-error</literal></term>
+ <term><literal>poin-ind</literal></term>
+ <term><literal>pointer</literal></term>
+ <listitem>
+ <para>
+ Code 0. The pointer field indicates the location of the problem.
+ See the <option>--icmp-param-pointer</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>missing-required-option</literal></term>
+ <term><literal>miss-option</literal></term>
+ <term><literal>option-missing</literal></term>
+ <listitem>
+ <para>
+ Code 1. IP datagram was expected to have an option that is not
+ present.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>bad-length</literal></term>
+ <term><literal>bad-len</literal></term>
+ <term><literal>badlen</literal></term>
+ <listitem>
+ <para>
+ Code 2. The length of the IP datagram is incorrect.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+
+<!--
+ <refsect3>
+ <title>ICMP Security Failures Messages (Experimental)</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>bad-spi</literal></term>
+ <term><literal>badspi</literal></term>
+ <term><literal>!spi</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>authentication-failed</literal></term>
+ <term><literal>auth-fai</literal></term>
+ <term><literal>auth-failed</literal></term>
+ <term><literal>authfail</literal></term>
+ <term><literal>!auth</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>decompression-failed</literal></term>
+ <term><literal>deco-fai</literal></term>
+ <term><literal>decom-failed</literal></term>
+ <term><literal>!decompress</literal></term>
+ <term><literal>!decompression</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>decryption-failed</literal></term>
+ <term><literal>decr-fai</literal></term>
+ <term><literal>decrypt-failed</literal></term>
+ <term><literal>!decrypt</literal></term>
+ <term><literal>!decryption</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>need-authentication</literal></term>
+ <term><literal>need-aut</literal></term>
+ <term><literal>need-auth</literal></term>
+ <term><literal>auth-needed</literal></term>
+ <term><literal>!auth</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>need-authorization</literal></term>
+ <term><literal>need-author</literal></term>
+ <term><literal>authorization-needed</literal></term>
+ <term><literal>author-needed</literal></term>
+ <term><literal>!author</literal></term>
+ <term><literal>!authorization</literal></term>
+ <listitem>
+ <para>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect3>
+-->
+
+ <indexterm class="endofrange" startref="nping-man-icmp-types-indexterm"/>
+ </refsect2>
+ </refsect1>
+
+<!-- ARP MODE ************************************************************* -->
+ <refsect1 id="nping-man-arp-mode">
+ <title>ARP Mode</title>
+
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--arp-type <replaceable>type</replaceable></option> (ICMP Type)
+ <indexterm significance="preferred"><primary><option>--arp-type</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies which type of ARP messages should be
+ generated. <replaceable>type</replaceable> can be supplied in
+ two different ways. You can use the
+ <ulink url="http://www.iana.org/assignments/arp-parameters/">official
+ numbers assigned by IANA</ulink>
+ (e.g. <option>--arp-type 1</option> for ARP Request), or you can use
+ one of the mnemonics from <xref linkend="nping-man-arp-types"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--arp-sender-mac <replaceable>mac</replaceable></option> (Sender MAC address)
+ <indexterm significance="preferred"><primary><option>--arp-sender-mac</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Sender Hardware Address field of the ARP header.
+ Although ARP supports many types of link layer addresses, currently
+ Nping only supports MAC addresses.
+ <replaceable>mac</replaceable> must be specified using the
+ traditional MAC notation (e.g. <literal>00:0a:8a:32:f4:ae</literal>). You can also use
+ hyphens as separators (e.g. <literal>00-0a-8a-32-f4-ae</literal>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--arp-sender-ip <replaceable>addr</replaceable></option> (Sender IP address)
+ <indexterm significance="preferred"><primary><option>--arp-sender-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Sender IP field of the ARP header.
+ <replaceable>addr</replaceable> can be given as an IPv4 address or a
+ hostname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--arp-target-mac <replaceable>mac</replaceable></option> (target MAC address)
+ <indexterm significance="preferred"><primary><option>--arp-target-mac</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Target Hardware Address field of the ARP header.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--arp-target-ip <replaceable>addr</replaceable></option> (target ip address)
+ <indexterm significance="preferred"><primary><option>--arp-target-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Target IP field of the ARP header.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <refsect2 id="nping-man-arp-types">
+ <indexterm class="startofrange" id="nping-man-arp-types-indexterm"><primary>ARP types</primary><secondary>mnemonics of, in Nping</secondary></indexterm>
+ <title>ARP Types</title>
+
+ <para>
+ These identifiers may be used as mnemonics for the ARP type numbers given
+ to the
+ <option>--arp-type</option><indexterm><primary><option>--arp-type</option> (Nping option)</primary></indexterm>
+ option.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>arp-request</literal></term>
+ <term><literal>arp</literal></term>
+ <term><literal>a</literal></term>
+ <listitem>
+ <para>
+ ARP Request (type 1). ARP requests are used to translate network
+ layer addresses (normally IP addresses) to link layer addresses
+ (usually MAC addresses). Basically, and ARP request is a
+ broadcasted message that asks the host in the same network
+ segment that has a given IP address to provide its MAC address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>arp-reply</literal></term>
+ <term><literal>arp-rep</literal></term>
+ <term><literal>ar</literal></term>
+ <listitem>
+ <para>
+ ARP Reply (type 2). An ARP reply is a message that a host sends in
+ response to an ARP request to provide its link layer address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>rarp-request</literal></term>
+ <term><literal>rarp</literal></term>
+ <term><literal>r</literal></term>
+ <listitem>
+ <para>
+ RARP Requests (type 3). RARP requests are used to translate a
+ link layer address (normally a MAC address) to a network layer
+ address (usually an IP address). Basically a RARP request is a
+ broadcasted message sent by a host that wants to know his own IP
+ address because it doesn't have any. It was the first protocol
+ designed to solve the bootstrapping problem. However, RARP is now
+ obsolete and DHCP is used instead. For more information about
+ RARP see
+ RFC 903.<indexterm><primary>RFC 903</primary></indexterm>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>rarp-reply</literal></term>
+ <term><literal>rarp-rep</literal></term>
+ <term><literal>rr</literal></term>
+ <listitem>
+ <para>
+ RARP Reply (type 4). A RARP reply is a message sent in response
+ to a RARP request to provide an IP address to the host that sent
+ the RARP request in the first place.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>drarp-request</literal></term>
+ <term><literal>drarp</literal></term>
+ <term><literal>d</literal></term>
+ <listitem>
+ <para>
+ Dynamic RARP Request (type 5). Dynamic RARP is an extension to
+ RARP used to obtain or assign a network layer address from a
+ fixed link layer address. DRARP was used mainly in Sun
+ Microsystems platforms in the late 90's but now it's no longer
+ used. See
+ RFC 1931<indexterm><primary>RFC 1931</primary></indexterm>
+ for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>drarp-reply</literal></term>
+ <term><literal>drarp-rep</literal></term>
+ <term><literal>dr</literal></term>
+ <listitem>
+ <para>
+ Dynamic RARP Reply (type 6). A DRARP reply is a message sent in
+ response to a RARP request to provide network layer address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>drarp-error</literal></term>
+ <term><literal>drarp-err</literal></term>
+ <term><literal>de</literal></term>
+ <listitem>
+ <para>
+ DRARP Error (type 7). DRARP Error messages are usually sent in
+ response to DRARP requests to inform of some error. In DRARP
+ Error messages, the Target Protocol Address field is used to
+ carry an error code (usually in the first byte). The error code
+ is intended to tell why no target protocol address is being
+ returned. For more information see RFC 1931.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>inarp-request</literal></term>
+ <term><literal>inarp</literal></term>
+ <term><literal>i</literal></term>
+ <listitem>
+ <para>
+ Inverse ARP Request (type 8). InARP requests are used to
+ translate a link layer address to a network layer address. It is
+ similar to RARP request but in this case, the sender of the InARP
+ request wants to know the network layer address of another node,
+ not its own address. InARP is mainly used in Frame Relay and ATM
+ networks. For more information see
+ RFC 2390.<indexterm><primary>RFC 2390</primary></indexterm>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>inarp-reply</literal></term>
+ <term><literal>inarp-rep</literal></term>
+ <term><literal>ir</literal></term>
+ <listitem>
+ <para>
+ Inverse ARP Reply (type 9). InARP reply messages are sent in
+ response to InARP requests to provide the network layer address
+ associated with the host that has a given link layer address.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>arp-nak</literal></term>
+ <term><literal>an</literal></term>
+ <listitem>
+ <para>
+ ARP NAK (type 10). ARP NAK messages are an extension to the
+ ATMARP protocol and they are used to improve the robustness of
+ the ATMARP server mechanism. With ARP NAK, a client can determine
+ the difference between a catastrophic server failure and an
+ ATMARP table lookup failure. See
+ RFC 1577<indexterm><primary>RFC 1577</primary></indexterm>
+ for more information.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <indexterm class="endofrange" startref="nping-man-arp-types-indexterm"/>
+ </refsect2>
+
+ </refsect1>
+
+
+
+<!-- IPv4 OPTIONS ********************************************************** -->
+ <refsect1 id="nping-man-ip-options">
+ <title>IPv4 Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>-S <replaceable>addr</replaceable></option>,
+ <option>--source-ip <replaceable>addr</replaceable></option> (Source IP Address)
+ <indexterm significance="preferred"><primary><option>--source-ip</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-S</option> (Nping option)</primary><see><option>--source-ip</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the source IP address. This option lets you specify a custom IP
+ address to be used as source IP address in sent packets. This
+ allows spoofing the sender of the packets.
+ <replaceable>addr</replaceable> can be an IPv4 address or a hostname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--dest-ip <replaceable>addr</replaceable></option> (Destination IP Address)
+ <indexterm significance="preferred"><primary><option>--dest-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Adds a target to Nping's target list.
+ This option is provided for consistency but its use is deprecated
+ in favor of plain target specifications. See
+ <xref linkend="nping-man-target-specification"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--tos <replaceable>tos</replaceable></option> (Type of Service)
+ <indexterm significance="preferred"><primary><option>--tos</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the IP TOS field. The TOS field is used to carry information
+ to provide quality of service features. It is normally used to
+ support a technique called Differentiated Services. See
+ RFC 2474<indexterm><primary>RFC 2474</primary></indexterm>
+ for
+ more information. <replaceable>tos</replaceable> must be a number
+ in the range [0&ndash;255].
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--id <replaceable>id</replaceable></option> (Identification)
+ <indexterm significance="preferred"><primary><option>--id</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the IPv4 Identification field. The Identification field is a
+ 16-bit value that is common to all fragments belonging to a particular
+ message. The value is used by the receiver to reassemble the
+ original message from the fragments received. <replaceable>id</replaceable>
+ must be a number in the range [0&ndash;65535].
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--df</option> (Don't Fragment)
+ <indexterm significance="preferred"><primary><option>--df</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the Don't Fragment bit in sent packets. When an
+ IP datagram has its DF flag set, intermediate devices are not
+ allowed to fragment it so if it needs to travel across a network
+ with a MTU smaller that datagram length the datagram will have
+ to be dropped. Normally an ICMP Destination Unreachable message
+ is generated and sent back to the sender.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--mf</option> (More Fragments)
+ <indexterm significance="preferred"><primary><option>--mf</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the More Fragments bit in sent packets. The MF
+ flag is set to indicate the receiver that the current datagram is
+ a fragment of some larger datagram. When set to zero it indicates
+ that the current datagram is either the last fragment in the set
+ or that it is the only fragment.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--evil</option> (Reserved / Evil)
+ <indexterm significance="preferred"><primary><option>--evil</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the Reserved / Evil bit in sent packets. The Evil flag
+ helps firewalls and other network security systems to distinguish
+ between datagrams that have malicious intent and those that are
+ merely unusual. When set, it indicates that the datagram has evil
+ intent, instructing insecure systems to succumb. Setting it to zero
+ indicates no evil intent. The option is implied if environmental
+ variable SCRIPT_KIDDIE is set to a non-zero value.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ttl <replaceable>hops</replaceable></option> (Time To Live)
+ <indexterm significance="preferred"><primary><option>--ttl</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the IPv4 Time-To-Live (TTL) field in sent packets to the given
+ value. The TTL field specifies how long the datagram is allowed
+ to exist on the network. It was originally intended to represent
+ a number of seconds but it actually represents the number of
+ hops a packet can traverse before being dropped. The TTL tries to
+ avoid a situation in which undeliverable datagrams keep being
+ forwarded from one router to another endlessly.
+ <replaceable>hops</replaceable> must be a number in the range [0&ndash;255].
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--badsum-ip</option> (Invalid IP checksum)
+ <indexterm significance="preferred"><primary><option>--badsum-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Asks Nping to use an invalid IP checksum for packets sent to
+ target hosts. Note that some systems (like most Linux kernels),
+ may fix the checksum before placing the packet on the wire, so
+ even if Nping shows the incorrect checksum in its output, the
+ packets may be transparently corrected by the kernel.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--ip-options <replaceable>R|S [route]|L [route]|T|U ...</replaceable></option>,
+ <option>--ip-options <replaceable>hex string</replaceable></option> (IP Options)
+ <indexterm significance="preferred"><primary><option>--ip-options</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ The IP protocol offers several options which may be placed in
+ packet headers. Unlike the ubiquitous TCP options, IP options are
+ rarely seen due to practicality and security concerns. In fact,
+ many Internet routers block the most dangerous options such as
+ source routing. Yet options can still be useful in some cases for
+ determining and manipulating the network route to target machines.
+ For example, you may be able to use the record route option to
+ determine a path to a target even when more traditional
+ traceroute-style approaches fail. Or if your packets are being
+ dropped by a certain firewall, you may be able to specify a
+ different route with the strict or loose source routing options.
+ </para>
+
+ <para>
+ The most powerful way to specify IP options is to simply pass in hexadecimal data
+ as the argument to <option>--ip-options</option>. Precede each hex byte value
+ with <literal>\x</literal>. You may repeat certain characters by
+ following them with an asterisk and then the number of times you
+ wish them to repeat. For example,
+ <literal>\x01\x07\x04\x00*4</literal> is the same as
+ <literal>\x01\x07\x04\x00\x00\x00\x00</literal>.
+ </para>
+
+ <para>
+ Note that if you specify a number of bytes that is not a multiple
+ of four, an incorrect IP header length will be set in the IP
+ packet. The reason for this is that the IP header length field
+ can only express multiples of four. In those cases, the length is
+ computed by dividing the header length by 4 and rounding down.
+ This will
+ affect the way the header that follows the IP header is
+ interpreted, showing bogus information in Nping or in the output
+ of any sniffer. Although this kind of situation might be useful
+ for some stack stress tests, users would normally want to
+ specify explicit padding, so the correct header length is set.
+ </para>
+
+ <para>
+ Nping also offers a shortcut mechanism for specifying options.
+ Simply pass the letter <literal>R</literal>, <literal>T</literal>, or <literal>U</literal> to request record-route,
+ record-timestamp, or both options together, respectively. Loose
+ or strict source routing may be specified with an L or S followed
+ by a space and then a space-separated list of IP addresses.
+ </para>
+
+ <para>
+ For more information and examples of using IP options with Nping,
+ see the mailing list post at
+ <ulink url="https://seclists.org/nmap-dev/2006/q3/0052.html"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--mtu <replaceable>size</replaceable></option> (Maximum Transmission Unit)
+ <indexterm significance="preferred"><primary><option>--mtu</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets a fictional MTU in Nping so IP datagrams larger than
+ <replaceable>size</replaceable> are fragmented before transmission.
+ <replaceable>size</replaceable> must be specified in bytes and
+ corresponds to the number of octets that can be carried on a
+ single link-layer frame.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+
+<!-- IPv6 OPTIONS ********************************************************** -->
+ <refsect1 id="nping-man-ip6-options">
+ <title>IPv6 Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>-6</option>,
+ <option>--ipv6</option> (Use IPv6)
+ <indexterm significance="preferred"><primary><option>--ipv6</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-6</option> (Nping option)</primary><see><option>--ipv6</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Tells Nping to use IP version 6 instead of the default IPv4.
+ It is generally a good idea to specify this option as early as
+ possible in the command line so Nping can parse it soon and know in
+ advance that the rest of the parameters refer to IPv6. The command
+ syntax is the same as usual except that you also add the <option>-6</option> option.
+ Of course, you must use IPv6 syntax if you specify an address
+ rather than a hostname. An address might look like
+ <option>3ffe:7501:4819:2000:210:f3ff:fe03:14d0</option>, so hostnames are
+ recommended.
+ </para>
+ <para>
+ While IPv6 hasn't exactly taken the world by storm, it gets
+ significant use in some (usually Asian) countries and most modern
+ operating systems support it. To use Nping with IPv6, both the
+ source and target of your packets must be configured for IPv6. If your
+ ISP (like most of them) does not allocate IPv6 addresses to you,
+ free tunnel brokers are widely available and work fine with Nping.
+ You can use the free IPv6 tunnel broker service at
+ <ulink url="http://www.tunnelbroker.net"/>.
+ </para>
+ <para>
+ Please note that IPv6 support is still highly experimental and
+ many modes and options may not work with it.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+
+
+ <varlistentry>
+ <term>
+ <option>-S <replaceable>addr</replaceable></option>,
+ <option>--source-ip <replaceable>addr</replaceable></option> (Source IP Address)
+ <indexterm significance="preferred"><primary><option>--source-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the source IP address. This option lets you specify a custom IP
+ address to be used as source IP address in sent packets. This
+ allows spoofing the sender of the packets.
+ <replaceable>addr</replaceable> can be an IPv6 address or a hostname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--dest-ip <replaceable>addr</replaceable></option> (Destination IP Address)
+ <indexterm significance="preferred"><primary><option>--dest-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Adds a target to Nping's target list.
+ This option is provided for consistency but its use is deprecated
+ in favor of plain target specifications. See
+ <xref linkend="nping-man-target-specification"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--flow <replaceable>label</replaceable></option> (Flow Label)
+ <indexterm significance="preferred"><primary><option>--flow</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the IPv6 Flow Label. The Flow Label field is 20 bits long and is
+ intended to provide certain quality-of-service properties for
+ real-time datagram delivery. However, it has not been widely
+ adopted, and not all routers or endpoints support it. Check
+ RFC 2460<indexterm><primary>RFC 2560</primary></indexterm>
+ for more information. <replaceable>label</replaceable> must be an
+ integer in the range [0&ndash;1048575].
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--traffic-class <replaceable>class</replaceable></option> (Traffic Class)
+ <indexterm significance="preferred"><primary><option>--traffic-class</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Sets the IPv6 Traffic Class. This field is similar to the TOS field in
+ IPv4, and is intended to provide the Differentiated Services
+ method, enabling scalable service discrimination in the Internet
+ without the need for per-flow state and signaling at every hop. Check
+ RFC 2474<indexterm><primary>RFC 2474</primary></indexterm>
+ for more information. <replaceable>class</replaceable> must
+ be an integer in the range [0&ndash;255].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--hop-limit <replaceable>hops</replaceable></option> (Hop Limit)
+ <indexterm significance="preferred"><primary><option>--hop-limit</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ <indexterm><primary>hop limit (IPv6)</primary><seealso>TTL</seealso></indexterm>
+ Sets the IPv6 Hop Limit field in sent packets to the given
+ value. The Hop Limit field specifies how long the datagram is allowed
+ to exist on the network. It represents the number of hops a packet
+ can traverse before being dropped. As with the TTL in IPv4, IPv6 Hop Limit
+ tries to avoid a situation in which undeliverable datagrams keep being
+ forwarded from one router to another endlessly.
+ <replaceable>hops</replaceable> must be a number in the range [0&ndash;255].
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+
+
+<!-- ETHERNET OPTIONS ***************************************************** -->
+ <refsect1 id="nping-man-ethernet-options">
+ <title>Ethernet Options</title>
+
+ <para>
+ In most cases Nping sends packets at the raw IP level. This means that Nping
+ creates its own IP packets and transmits them through a raw socket. However,
+ in some cases it may be necessary to send packets at the raw Ethernet level.
+ This happens, for example, when Nping is run under Windows (as Microsoft
+ has disabled raw socket support since Windows XP SP2), or when Nping is
+ asked to send ARP packets.
+ Since in some cases it is necessary to construct ethernet frames, Nping
+ offers some options to manipulate the different fields.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--dest-mac <replaceable>mac</replaceable></option> (Ethernet Destination MAC Address)
+ <indexterm significance="preferred"><primary><option>--dest-mac</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the destination MAC address that should be set in
+ outgoing Ethernet frames. This is useful in case Nping can't
+ determine the next hop's MAC address or when you want to route
+ probes through a router other than the configured default
+ gateway. The MAC address should have the usual format of
+ six colon-separated bytes, e.g. <literal>00:50:56:d4:01:98</literal>.
+ Alternatively, hyphens may be used instead of colons.
+ Use the word <literal>random</literal> or <literal>rand</literal> to
+ generate a random address, and <literal>broadcast</literal> or
+ <literal>bcast</literal> to use ff:ff:ff:ff:ff:ff.
+ If you set up a bogus destination MAC address your probes may not
+ reach the intended targets.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--source-mac <replaceable>mac</replaceable></option> (Ethernet Source MAC Address)
+ <indexterm significance="preferred"><primary><option>--source-mac</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the source MAC address that should be set in
+ outgoing Ethernet frames. This is useful in case Nping can't
+ determine your network interface MAC address or when you want to
+ inject traffic into the network while hiding your network card's real
+ address. The syntax is the same as for <literal>--dest-mac</literal>.
+ If you set up a bogus source MAC address
+ you may not receive probe replies.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--ether-type <replaceable>type</replaceable></option> (Ethertype)
+ <indexterm significance="preferred"><primary><option>--ether-type</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option sets the Ethertype field of the ethernet frame.
+ The Ethertype is used to indicate which protocol is encapsulated
+ in the payload. <replaceable>type</replaceable> can be supplied in
+ two different ways. You can use the
+ <ulink url="http://standards.ieee.org/regauth/ethertype/eth.txt">official
+ numbers listed by the IEEE</ulink>
+ (e.g. <option>--ether-type 0x0800</option> for IP version 4),
+ or one of the mnemonics from
+ <xref linkend="nping-man-ether-types" xrefstyle="template:the section called &#x201c;%t&#x201d;"/>.
+ <!-- Hide the page number, but also include the section title. xrefstyle="select: label nopage" doesn't work here. -->
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <refsect2 id="nping-man-ether-types">
+ <indexterm class="startofrange" id="nping-man-arp-ether-indexterm"><primary>Ethernet types</primary><secondary>mnemonics of, in Nping</secondary></indexterm>
+ <title>Ethernet Types</title>
+
+ <para>
+ These identifiers may be used as mnemonics for the Ethertype numbers given
+ to the
+ <option>--arp-type</option><indexterm><primary><option>--arp-type</option> (Nping option)</primary></indexterm>
+ option.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><literal>ipv4</literal></term>
+ <term><literal>ip</literal></term>
+ <term><literal>4</literal></term>
+ <listitem>
+ <para>
+ Internet Protocol version 4 (type 0x0800).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ipv6</literal></term>
+ <term><literal>6</literal></term>
+ <listitem>
+ <para>
+ Internet Protocol version 6 (type 0x86DD).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>arp</literal></term>
+ <listitem>
+ <para>
+ Address Resolution Protocol (type 0x0806).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>rarp</literal></term>
+ <listitem>
+ <para>
+ Reverse Address Resolution Protocol (type 0x8035).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>frame-relay</literal></term>
+ <term><literal>frelay</literal></term>
+ <term><literal>fr</literal></term>
+ <listitem>
+ <para>
+ Frame Relay (type 0x0808).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ppp</literal></term>
+ <listitem>
+ <para>
+ Point-to-Point Protocol (type 0x880B).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>gsmp</literal></term>
+ <listitem>
+ <para>
+ General Switch Management Protocol (type 0x880C).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mpls</literal></term>
+ <listitem>
+ <para>
+ Multiprotocol Label Switching (type 0x8847).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mps-ual</literal></term>
+ <term><literal>mps</literal></term>
+ <listitem>
+ <para>
+ Multiprotocol Label Switching with Upstream-assigned Label (type 0x8848).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mcap</literal></term>
+ <listitem>
+ <para>
+ Multicast Channel Allocation Protocol (type 0x8861).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>pppoe-discovery</literal></term>
+ <term><literal>pppoe-d</literal></term>
+ <listitem>
+ <para>
+ PPP over Ethernet Discovery Stage (type 0x8863).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>pppoe-session</literal></term>
+ <term><literal>pppoe-s</literal></term>
+ <listitem>
+ <para>
+ PPP over Ethernet Session Stage (type 0x8864).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ctag</literal></term>
+ <listitem>
+ <para>
+ Customer VLAN Tag Type (type 0x8100).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>epon</literal></term>
+ <listitem>
+ <para>
+ Ethernet Passive Optical Network (type 0x8808).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>pbnac</literal></term>
+ <listitem>
+ <para>
+ Port-based network access control (type 0x888E).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>stag</literal></term>
+ <listitem>
+ <para>
+ Service VLAN tag identifier (type 0x88A8).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ethexp1</literal></term>
+ <listitem>
+ <para>
+ Local Experimental Ethertype 1 (type 0x88B5).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ethexp2</literal></term>
+ <listitem>
+ <para>
+ Local Experimental Ethertype 2 (type 0x88B6).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>ethoui</literal></term>
+ <listitem>
+ <para>
+ OUI Extended Ethertype (type 0x88B7).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>preauth</literal></term>
+ <listitem>
+ <para>
+ Pre-Authentication (type 0x88C7).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>lldp</literal></term>
+ <listitem>
+ <para>
+ Link Layer Discovery Protocol (type 0x88CC).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mac-security</literal></term>
+ <term><literal>mac-sec</literal></term>
+ <term><literal>macsec</literal></term>
+ <listitem>
+ <para>
+ Media Access Control Security (type 0x88E5).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mvrp</literal></term>
+ <listitem>
+ <para>
+ Multiple VLAN Registration Protocol (type 0x88F5).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>mmrp</literal></term>
+ <listitem>
+ <para>
+ Multiple Multicast Registration Protocol (type 0x88F6).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>frrr</literal></term>
+ <listitem>
+ <para>
+ Fast Roaming Remote Request (type 0x890D).
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <indexterm class="endofrange" startref="nping-man-ether-types-indexterm"/>
+ </refsect2>
+ </refsect1>
+
+
+
+
+<!-- PAYLOAD OPTIONS ******************************************************* -->
+ <refsect1 id="nping-man-payload-options">
+ <title>Payload Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--data <replaceable>hex string</replaceable></option> (Append custom binary data to sent packets)
+ <indexterm significance="preferred"><primary><option>--data</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you include binary data as payload in sent packets.
+ <replaceable>hex string</replaceable> may be specified in any of
+ the following formats: <literal>0xAABBCCDDEEFF<replaceable>...</replaceable></literal>,
+ <literal>AABBCCDDEEFF<replaceable>...</replaceable></literal> or
+ <literal>\xAA\xBB\xCC\xDD\xEE\xFF<replaceable>...</replaceable></literal>.
+ Examples of use are <option>--data 0xdeadbeef</option> and
+ <option>--data \xCA\xFE\x09</option>. Note that if you specify a
+ number like <literal>0x00ff</literal>
+ no byte-order conversion is performed. Make sure you specify
+ the information in the byte order expected by the receiver.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--data-string <replaceable>string</replaceable></option> (Append custom string to sent packets)
+ <indexterm significance="preferred"><primary><option>--data-string</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you include a regular string as payload in
+ sent packets. <replaceable>string</replaceable> can
+ contain any string. However, note that some characters
+ may depend on your system's locale and the receiver may not
+ see the same information. Also, make sure you enclose the string
+ in double quotes and escape any special characters from the shell.
+ Example: <option>--data-string "Jimmy Jazz..."</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--data-length <replaceable>len</replaceable></option> (Append random data to sent packets)
+ <indexterm significance="preferred"><primary><option>--data-length</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you include <replaceable>len</replaceable>
+ random bytes of data as payload in sent packets.
+ <replaceable>len</replaceable> must be an integer in the range
+ [0&ndash;65400]. However, values higher than 1400 are not recommended
+ because it may not be possible to transmit packets due to
+ network MTU limitations.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+
+
+<!-- ECHO MODE ****************************************************** -->
+ <refsect1 id="nping-man-echo-mode">
+ <title>Echo Mode</title>
+
+ <para>
+ The "Echo Mode" is a novel technique implemented by Nping which lets users
+ see how network packets change in transit, from the host where they
+ originated to the target machine. Basically, the Echo mode turns Nping into
+ two different pieces: the Echo server and the Echo client. The Echo server
+ is a network service that has the ability to capture packets from the
+ network and send a copy ("echo them") to the originating client through a
+ side TCP channel. The Echo client is the part that generates such network
+ packets, transmits them to the server, and receives their echoed version
+ through a side TCP channel that it has previously established with the Echo
+ server.
+ </para>
+
+ <para>
+ This scheme lets the client see the differences between the packets that it
+ sends and what is actually received by the server. By having the server
+ send back copies of the received packets through the side channel, things
+ like NAT devices become immediately apparent to the client because it
+ notices the changes in the source IP address (and maybe even source
+ port). Other devices like those that perform traffic shaping, changing
+ TCP window sizes or adding TCP options transparently between hosts, turn up
+ too.
+ </para>
+
+ <para>
+ The Echo mode is also useful for troubleshooting routing and firewall issues.
+ Among other things, it can be used to determine if the traffic generated
+ by the Nping client is being dropped in transit and never gets to its
+ destination or if the responses are the ones that don't get back to it.
+ </para>
+
+ <para>
+ Internally, client and server communicate over an encrypted and
+ authenticated channel, using the Nping Echo Protocol (NEP), whose technical
+ specification can be found in
+ <ulink url="https://nmap.org/svn/nping/docs/EchoProtoRFC.txt"/>
+ </para>
+
+ <para>
+ The following paragraphs describe the different options available in Nping's
+ Echo mode.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--ec <replaceable>passphrase</replaceable></option>,
+ <option>--echo-client <replaceable>passphrase</replaceable></option> (Run Echo client)
+ <indexterm significance="preferred"><primary><option>--echo-client</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--ec</option> (Nping option)</primary><see><option>--echo-client</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option tells Nping to run as an Echo client.
+ <replaceable>passphrase</replaceable> is a sequence of ASCII
+ characters that is used used to generate the cryptographic
+ keys needed for encryption and authentication in a given session.
+ The passphrase should be a secret that is also known by the server,
+ and it may contain any number of printable ASCII characters.
+ Passphrases that contain whitespace or special characters must be
+ enclosed in double quotes.
+ </para>
+
+ <para>
+ When running Nping as an Echo client, most options from the regular
+ raw probe modes apply. The client may be configured to send specific
+ probes using flags like <option>--tcp</option>,
+ <option>--icmp</option> or <option>--udp</option>. Protocol header
+ fields may be manipulated normally using the appropriate options
+ (e.g. <option>--ttl</option>, <option>--seq</option>,
+ <option>--icmp-type</option>, etc.). The only exceptions are
+ ARP-related flags, which are not supported in Echo mode, as protocols
+ like ARP are closely related to the data link layer and its probes
+ can't pass through different network segments.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--es <replaceable>passphrase</replaceable></option>,
+ <option>--echo-server <replaceable>passphrase</replaceable></option> (Run Echo server)
+ <indexterm significance="preferred"><primary><option>--echo-server</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--es</option> (Nping option)</primary><see><option>--echo-server</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option tells Nping to run as an Echo server.
+ <replaceable>passphrase</replaceable> is a sequence of ASCII
+ characters that is used used to generate the cryptographic
+ keys needed for encryption and authentication in a given session.
+ The passphrase should be a secret that is also known by the clients,
+ and it may contain any number of printable ASCII characters.
+ Passphrases that contain whitespace or special characters must be
+ enclosed in double quotes. Note that although it is not recommended,
+ it is possible to use empty passphrases, supplying
+ <option>--echo-server ""</option>. However, if what you
+ want is to set up an open Echo server, it is better to use option
+ <option>--no-crypto</option>. See below for details.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+
+ <varlistentry>
+ <term>
+ <option>--ep <replaceable>port</replaceable></option>,
+ <option>--echo-port <replaceable>port</replaceable></option> (Set Echo TCP port number)
+ <indexterm significance="preferred"><primary><option>--echo-port</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--ep</option> (Nping option)</primary><see><option>--echo-port</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks Nping to use the specified TCP port number for the
+ Echo side channel connection. If this option is used with
+ <option>--echo-server</option>, it specifies the port on which the
+ server listens for connections. If it is used with
+ <option>--echo-client</option>, it specifies the port to connect to
+ on the remote host. By default, port number 9929 is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--nc</option>,
+ <option>--no-crypto</option> (Disable encryption and authentication)
+ <indexterm significance="preferred"><primary><option>--no-crypto</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--nc</option> (Nping option)</primary><see><option>--no-crypto</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks Nping not to use any cryptographic operations during
+ an Echo session. In practical terms, this means that the Echo side
+ channel session data will be transmitted in the clear, and no
+ authentication will be performed by the server or client
+ during the session establishment phase. When <option>--no-crypto</option>
+ is used, the passphrase supplied with <option>--echo-server</option>
+ or <option>--echo-client</option> is ignored.
+ </para>
+
+ <para>
+ This option must be specified if Nping was compiled without
+ openSSL support. Note that, for technical reasons, a passphrase still
+ needs to be supplied after the --echo-client or --echo-server flags,
+ even though it will be ignored.
+ </para>
+
+ <para>
+ The --no-crypto flag might be useful when setting up a public Echo
+ server, because it allows users to connect to the Echo server without
+ the need for any passphrase or shared secret. However, it is strongly
+ recommended to not use --no-crypto unless absolutely necessary. Public
+ Echo servers should be configured to use the passphrase "public" or
+ the empty passphrase (--echo-server "") as the use of cryptography
+ does not only provide confidentiality and authentication but also
+ message integrity.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--once</option> (Serve one client and quit)
+ <indexterm significance="preferred"><primary><option>--once</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks the Echo server to quit after serving one client.
+ This is useful when only a single Echo session wants to be established
+ as it eliminates the need to access the remote host to shutdown the
+ server.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--safe-payloads</option> (Zero application data before echoing a packet)
+ <indexterm significance="preferred"><primary><option>--safe-payloads</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option asks the Echo server to erase any application layer data
+ found in client packets before echoing them. When the option is enabled,
+ the Echo server parses the packets received from Echo clients and tries
+ to determine if they contain data beyond the transport layer. If such
+ data is found, it is overwritten with zeroes before transmitting the
+ packets to the appropriate Echo client.
+ </para>
+
+ <para>
+ Echo servers can handle multiple simultaneous clients running
+ multiple echo sessions in parallel. In order to determine which packet
+ needs to be echoed to which client and through which session, the Echo
+ server uses an heuristic algorithm. Although we have taken every
+ security measure that we could think of to prevent that a client
+ receives an echoed packet that it did not generate, there is always
+ a risk that our algorithm makes a mistake and delivers a packet to
+ the wrong client. The --safe-payloads option is useful for public
+ echo servers or critical deployments where that kind of mistake
+ cannot be afforded.
+ </para>
+
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ The following examples illustrate how Nping's Echo mode can be used
+ to discover intermediate devices.
+ </para>
+
+ <example id="nping-man-ex-echo1"><title>Discovering NAT devices</title>
+ <indexterm><primary><option>--echo-client</option> (Nping option)</primary><secondary>example of</secondary></indexterm>
+ <screen format="linespecific">
+ # <userinput>nping --echo-client "public" echo.nmap.org --udp </userinput>
+
+ Starting Nping ( https://nmap.org/nping )
+ SENT (1.0970s) UDP 10.1.20.128:53 &gt; 178.79.165.17:40125 ttl=64 id=32523 iplen=28
+ CAPT (1.1270s) UDP 80.38.10.21:45657 &gt; 178.79.165.17:40125 ttl=54 id=32523 iplen=28
+ RCVD (1.1570s) ICMP 178.79.165.17 &gt; 10.1.20.128 Port unreachable (type=3/code=3) ttl=49 id=16619 iplen=56
+ [...]
+ SENT (5.1020s) UDP 10.1.20.128:53 &gt; 178.79.165.17:40125 ttl=64 id=32523 iplen=28
+ CAPT (5.1335s) UDP 80.38.10.21:45657 &gt; 178.79.165.17:40125 ttl=54 id=32523 iplen=28
+ RCVD (5.1600s) ICMP 178.79.165.17 &gt; 10.1.20.128 Port unreachable (type=3/code=3) ttl=49 id=16623 iplen=56
+
+ Max rtt: 60.628ms | Min rtt: 58.378ms | Avg rtt: 59.389ms
+ Raw packets sent: 5 (140B) | Rcvd: 5 (280B) | Lost: 0 (0.00%)| Echoed: 5 (140B)
+ Tx time: 4.00459s | Tx bytes/s: 34.96 | Tx pkts/s: 1.25
+ Rx time: 5.00629s | Rx bytes/s: 55.93 | Rx pkts/s: 1.00
+ Nping done: 1 IP address pinged in 6.18 seconds
+ </screen>
+ </example>
+
+ <para>
+ The output clearly shows the presence of a NAT device in the client's local
+ network. Note how the captured packet (CAPT) differs from the SENT packet: the
+ source address for the original packets is in the reserved 10.0.0.0/8 range,
+ while the address seen by the server is 80.38.10.21, the Internet side address
+ of the NAT device. The source port was also modified by the device. The line
+ starting with RCVD corresponds to the responses generated by the TCP/IP stack
+ of the machine where the Echo server is run.
+ </para>
+
+ <example id="nping-man-ex-echo2"><title>Discovering a transparent proxy</title>
+ <screen format="linespecific">
+ # <userinput>nping --echo-client "public" echo.nmap.org --tcp -p80</userinput>
+
+ Starting Nping ( https://nmap.org/nping )
+ SENT (1.2160s) TCP 10.0.1.77:41659 &gt; 178.79.165.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ RCVD (1.2180s) TCP 178.79.165.17:80 &gt; 10.0.1.77:41659 SA ttl=128 id=13177 iplen=44 seq=3647106954 win=16384 &lt;mss 1460&gt;
+ SENT (2.2150s) TCP 10.0.1.77:41659 &gt; 178.79.165.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (3.2180s) TCP 10.0.1.77:41659 &gt; 178.79.165.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (4.2190s) TCP 10.0.1.77:41659 &gt; 178.79.165.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (5.2200s) TCP 10.0.1.77:41659 &gt; 178.79.165.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+
+ Max rtt: 2.062ms | Min rtt: 2.062ms | Avg rtt: 2.062ms
+ Raw packets sent: 5 (200B) | Rcvd: 1 (46B) | Lost: 4 (80.00%)| Echoed: 0 (0B)
+ Tx time: 4.00504s | Tx bytes/s: 49.94 | Tx pkts/s: 1.25
+ Rx time: 5.00618s | Rx bytes/s: 9.19 | Rx pkts/s: 0.20
+ Nping done: 1 IP address pinged in 6.39 seconds
+ </screen>
+ </example>
+
+ <para>
+ In this example, the output is a bit more tricky. The absence of error
+ messages shows that the Echo client has successfully established an Echo
+ session with the server. However, no CAPT packets can be seen in the output.
+ This means that none of the transmitted packets reached the server.
+ Interestingly, a TCP SYN-ACK packet was received in response to the first
+ TCP-SYN packet (and also, it is known that the target host does not have
+ port 80 open). This behavior reveals the presence of a transparent web proxy
+ cache server (which in this case is an old MS ISA server).
+ </para>
+
+</refsect1>
+
+
+<!-- TIMING AND PERFORMANCE OPTIONS **************************************** -->
+ <refsect1 id="nping-man-timing-performance-options">
+ <title>Timing and Performance Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>--delay <replaceable>time</replaceable></option> (Delay between probes)
+ <indexterm significance="preferred"><primary><option>--delay</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you control for how long will Nping wait before
+ sending the next probe. Like in many other ping tools, the default
+ delay is one second.
+ <replaceable>time</replaceable> must be a positive
+ integer or floating point number. By default it is specified in
+ seconds, however you can give an explicit unit by appending
+ <literal>ms</literal> for milliseconds, <literal>s</literal> for seconds,
+ <literal>m</literal> for minutes, or <literal>h</literal> for hours
+ (e.g. <literal>2.5s</literal>, <literal>45m</literal>, <literal>2h</literal>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--rate <replaceable>rate</replaceable></option> (Send probes at a given rate)
+ <indexterm significance="preferred"><primary><option>--rate</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option specifies the number of probes that Nping should send
+ per second. This option and <option>--delay</option> are inverses;
+ <option>--rate 20</option> is the same as
+ <option>--delay 0.05</option>. If both options are used, only the
+ last one in the parameter list counts.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+
+
+
+
+
+<!-- MISCELLANEOUS OPTIONS ************************************************ -->
+ <refsect1 id="nping-man-miscellaneous-options">
+ <title>Miscellaneous Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>-h</option>,
+ <option>--help</option> (Display help)
+ <indexterm significance="preferred"><primary><option>--help</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--h</option> (Nping option)</primary><see><option>--help</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Displays help information and exits.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>-V</option>,
+ <option>--version</option> (Display version)
+ <indexterm significance="preferred"><primary><option>--version</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-V</option> (Nping option)</primary><see><option>--version</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Displays the program's version number and quits.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-c <replaceable>rounds</replaceable></option>,
+ <option>--count <replaceable>rounds</replaceable></option> (Stop after a given number of rounds)
+ <indexterm significance="preferred"><primary><option>--count</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-c</option> (Nping option)</primary><see><option>--count</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you specify the number of times that Nping should
+ loop over target hosts (and in some cases target ports). Nping calls
+ these <quote>rounds</quote>. In a basic execution with only one target (and only
+ one target port in TCP/UDP modes), the number of rounds matches the
+ number of probes sent to the target host. However, in more complex
+ executions where Nping is run against multiple targets and multiple
+ ports, the number of rounds is the number of times that Nping sends
+ a complete set of probes that covers all target IPs and all
+ target ports. For example, if Nping is asked to send TCP SYN packets
+ to hosts 192.168.1.0-255 and ports 80 and 433, then 256&thinsp;&times;&thinsp;2&nbsp;=&nbsp;512 packets
+ are sent in one round. So if you specify <option>-c 100</option>, Nping will
+ loop over the different target hosts and ports 100 times, sending
+ a total of 256&thinsp;&times;&thinsp;2&thinsp;&times;&thinsp;100&nbsp;=&nbsp;51200 packets. By default Nping runs for
+ 5 rounds. If a value of 0 is specified, Nping will run continuously.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-e <replaceable>name</replaceable></option>,
+ <option>--interface <replaceable>name</replaceable></option> (Set the network interface to be used)
+ <indexterm significance="preferred"><primary><option>--interface</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-e</option> (Nping option)</primary><see><option>--interface</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option tells Nping what interface should be used to send and
+ receive packets. Nping should be able to detect this automatically,
+ but it will tell you if it cannot. <replaceable>name</replaceable>
+ must be the name of an existing network interface with an assigned
+ IP address.
+
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--privileged</option> (Assume that the user is fully privileged)
+ <indexterm significance="preferred"><primary><option>--privileged</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Tells Nping to simply assume that it is privileged enough to perform
+ raw socket sends, packet sniffing, and similar operations that
+ usually require special privileges. By default Nping quits if such
+ operations are requested by a user that has no root or administrator
+ privileges. This option may be useful on Linux, BSD or similar
+ systems that can be configured to allow unprivileged users to perform
+ raw-packet transmissions. The
+ <envar>NPING_PRIVILEGED</envar><indexterm><primary><envar>NPING_PRIVILEGED</envar> environment variable</primary></indexterm>
+ environment variable
+ may be set as an alternative to using <option>--privileged</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--unprivileged</option> (Assume that the user lacks raw socket privileges)
+ <indexterm significance="preferred"><primary><option>--unprivileged</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option is the opposite of <option>--privileged</option>. It tells Nping to treat
+ the user as lacking network raw socket and sniffing privileges.
+ This is useful for testing, debugging, or when the raw network
+ functionality of your operating system is somehow broken. The
+ <envar>NPING_UNPRIVILEGED</envar><indexterm><primary><envar>NPING_UNPRIVILEGED</envar> environment variable</primary></indexterm>
+ environment variable may be set as an
+ alternative to using <option>--unprivileged</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--send-eth</option> (Use raw ethernet sending)
+ <indexterm significance="preferred"><primary><option>--send-eth</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Asks Nping to send packets at the raw ethernet (data link) layer
+ rather than the higher IP (network) layer. By default, Nping chooses
+ the one which is generally best for the platform it is running on.
+ Raw sockets (IP layer) are generally most efficient for Unix
+ machines, while ethernet frames are required for Windows operation
+ since Microsoft disabled raw socket support. Nping still uses raw IP
+ packets despite this option when there is no other choice (such as
+ non-ethernet connections).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>--send-ip</option> (Send at raw IP level)
+ <indexterm significance="preferred"><primary><option>--send-ip</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Asks Nping to send packets via raw IP sockets rather than sending
+ lower level ethernet frames. It is the complement to the
+ <option>--send-eth</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>--bpf-filter <replaceable>filter spec</replaceable></option>
+ <option>--filter <replaceable>filter spec</replaceable></option> (Set custom BPF filter)
+ <indexterm significance="preferred"><primary><option>--bpf-filter</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>--filter</option> (Nping option)</primary><see>--bpf-filter</see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option lets you use a custom BPF filter. By default Nping
+ chooses a filter that is intended to capture most common responses
+ to the particular probes that are sent. For example, when sending
+ TCP packets, the filter is set to capture packets whose destination
+ port matches the probe's source port or ICMP error messages that may
+ be generated by the target or any intermediate device as a result of
+ the probe. If for some reason you expect strange packets in response
+ to sent probes or you just want to sniff a particular kind of
+ traffic, you can specify a custom filter using the BPF syntax used
+ by tools like
+ tcpdump.<indexterm><primary>tcpdump</primary></indexterm>
+ See the documentation at <ulink url="http://www.tcpdump.org/"/> for
+ more information.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>-H</option>,
+ <option>--hide-sent</option> (Do not display sent packets)
+ <indexterm significance="preferred"><primary><option>--hide-sent</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-H</option> (Nping option)</primary><see>--hide-sent</see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option tells Nping not to print information about sent packets.
+ This can be useful when using very short inter-probe delays (i.e.,
+ when flooding), because printing information to the standard
+ output has a computational cost and disabling it can probably
+ speed things up a bit. Also, it may be useful when using Nping to
+ detect active hosts or open ports (e.g. sending probes to all TCP
+ ports in a /24 subnet). In that case, users may not want to see
+ thousands of sent probes but just the replies generated by active
+ hosts.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <option>-N</option>,
+ <option>--no-capture</option> (Do not attempt to capture replies)
+ <indexterm significance="preferred"><primary><option>--no-capture</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-N</option> (Nping option)</primary><see><option>--no-capture</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ This option tells Nping to skip packet capture. This means that
+ packets in response to sent probes will not be processed or
+ displayed. This can be useful when doing flooding and network stack
+ stress tests. Note that when this option is specified, most of
+ the statistics shown at the end of the execution will be useless.
+ This option does not work with TCP Connect mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+
+
+
+
+
+<!-- OUTPUT OPTIONS **************************************** -->
+ <refsect1 id="nping-man-output-options">
+ <title>Output Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <option>-v<optional><replaceable>level</replaceable></optional></option>,
+ <option>--verbose <optional><replaceable>level</replaceable></optional></option> (Increase or set verbosity level)
+ <indexterm significance="preferred"><primary><option>--verbose</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-v</option> (Nping option)</primary><see><option>--verbose</option></see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Increases the verbosity level, causing Nping to print more
+ information during its execution. There are 9 levels of verbosity
+ (-4 to 4). Every instance of <option>-v</option> increments the verbosity level by one
+ (from its default value, level 0). Every instance of option <option>-q</option>
+ decrements the verbosity level by one. Alternatively you can specify
+ the level directly, as in <option>-v3</option> or
+ <option>-v-1</option>. These are the available levels:
+ </para>
+
+ <indexterm><primary>verbosity levels of Nping</primary></indexterm>
+ <variablelist>
+ <varlistentry>
+ <term>Level -4</term>
+ <listitem>
+ <para>
+ No output at all. In some circumstances you may not want
+ Nping to produce any output (like when one of your work mates is
+ watching over your shoulder). In that case level -4 can be useful
+ because although you won't see any response packets, probes will
+ still be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level -3</term>
+ <listitem>
+ <para>
+ Like level -4 but displays fatal error messages so you can
+ actually see if Nping is running or it failed due to some error.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level -2</term>
+ <listitem>
+ <para>
+ Like level -3 but also displays warnings and recoverable errors.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level -1</term>
+ <listitem>
+ <para>
+ Displays traditional run-time information (version, start time,
+ statistics, etc.) but does not display sent or received packets.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 0</term>
+ <listitem>
+ <para>
+ This is the default verbosity level. It behaves like level -1 but
+ also displays sent and received packets and some other important information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 1</term>
+ <listitem>
+ <para>
+ Like level 0 but it displays detailed information about
+ timing, flags, protocol details, etc.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 2</term>
+ <listitem>
+ <para>
+ Like level 1 but displays very detailed information
+ about sent and received packets and other interesting information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 3</term>
+ <listitem>
+ <para>
+ Like level 2 but also displays the raw hexadecimal dump of sent
+ and received packets.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 4 and higher</term>
+ <listitem>
+ <para>
+ Same as level 3.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <option>-q<optional><replaceable>level</replaceable></optional></option>,
+ <option>--reduce-verbosity <optional><replaceable>level</replaceable></optional></option> (Decrease verbosity level)
+ <indexterm significance="preferred"><primary><option>--reduce-verbosity</option> (Nping option)</primary></indexterm>
+ <indexterm significance="preferred"><primary><option>-q</option> (Nping option)</primary><see>--reduce-verbosity</see></indexterm>
+ </term>
+ <listitem>
+ <para>
+ Decreases the verbosity level, causing Nping to print less
+ information during its execution.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+
+
+ <varlistentry>
+ <term>
+ <option>-d<optional><replaceable>level</replaceable></optional></option> (Increase or set debugging level)
+ <indexterm significance="preferred"><primary><option>-d</option> (Nping option)</primary></indexterm>
+ </term>
+ <listitem>
+
+ <para>
+ When even verbose mode doesn't provide sufficient data for you,
+ debugging is available to flood you with much more! As with the
+ <option>-v</option>, debugging is enabled with a command-line
+ flag <option>-d</option> and the debug level can be increased by
+ specifying it multiple times. There are 7 debugging levels (0 to 6).
+ Every instance of <option>-d</option> increments debugging level by
+ one. Provide an argument to <option>-d</option> to set the level
+ directly; for example <option>-d4</option>.
+ </para>
+
+ <para>
+ Debugging output is useful when you suspect a bug in Nping, or if
+ you are simply confused as to what Nping is doing and why. As this
+ feature is mostly intended for developers, debug lines aren't
+ always self-explanatory. You may get something like
+<indexterm><primary>Nsock</primary><secondary>debug output of</secondary></indexterm>
+<screen>
+NSOCK (1.0000s) Callback: TIMER SUCCESS for EID 12; tcpconnect_event_handler<continuation/>(): Received callback of type TIMER with status SUCCESS
+</screen>
+ If you don't understand a line, your only
+ recourses are to ignore it, look it up in the source code, or
+ request help from the development list (<citetitle>nmap-dev</citetitle>). Some lines are
+ self-explanatory, but the messages become more obscure as the debug
+ level is increased. These are the available levels:
+ </para>
+
+ <indexterm><primary>debug levels of Nping</primary></indexterm>
+ <variablelist>
+ <varlistentry>
+ <term>Level 0</term>
+ <listitem>
+ <para>
+ Level 0. No debug information at all. This is the default level.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 1</term>
+ <listitem>
+ <para>
+ In this level, only very important or high-level debug information
+ will be printed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 2</term>
+ <listitem>
+ <para>
+ Like level 1 but also displays important or medium-level debug
+ information
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 3</term>
+ <listitem>
+ <para>
+ Like level 2 but also displays regular and low-level debug information.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 4</term>
+ <listitem>
+ <para>
+ Like level 3 but also displays messages only a real Nping freak would
+ want to see.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 5</term>
+ <listitem>
+ <para>
+ Like level 4 but it enables basic debug information related to
+ external libraries like Nsock.<indexterm><primary>Nsock</primary></indexterm>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Level 6</term>
+ <listitem>
+ <para>
+ Like level 5 but it enables full, very detailed, debug information
+ related to external libraries like Nsock.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1 id="nping-man-bugs">
+ <title>Bugs</title>
+ <indexterm><primary>bugs, reporting</primary></indexterm>
+
+ <para>Like its authors, Nping isn't perfect. But you can help make
+ it better by sending bug reports or even writing patches. If Nping
+ doesn't behave the way you expect, first upgrade to the latest
+ version available from <ulink
+ url="https://nmap.org"/>. If the problem persists,
+ do some research to determine whether it has already been
+ discovered and addressed. Try searching for the problem or error message on
+ Google since that aggregates so many forums. If nothing comes of this, create an Issue on our tracker
+ (<ulink url="http://issues.nmap.org"/>) and/or mail a bug report to
+ <email>dev@nmap.org</email>. If you subscribe to the nmap-dev
+ list before posting, your message will bypass moderation and get
+ through more quickly. Subscribe at <ulink
+ url="https://nmap.org/mailman/listinfo/dev"/>. Please include everything
+ you have learned about the problem, as well as what version of
+ Nping you are using and what operating system version it is
+ running on. Other suggestions for improving Nping may be sent to
+ the Nmap dev mailing list as well.</para>
+
+ <para>If you are able to write a patch improving Nping or fixing a
+ bug, that is even better! Instructions for submitting patches or
+ git pull requests are available from <ulink
+ url="https://github.com/nmap/nmap/blob/master/CONTRIBUTING.md"/></para>
+
+ <para>Particularly sensitive issues such as a security reports may
+ be sent directly to Fyodor directly at
+ <email>fyodor@nmap.org</email>. All other reports and comments
+ should use the dev list or issue tracker instead because more
+ people read, follow, and respond to those.</para>
+
+ </refsect1>
+
+ <refsect1 id="nping-man-author">
+ <title>Authors</title>
+
+ <para>Luis MartinGarcia <email>luis.mgarc@gmail.com</email> (<ulink url="http://www.luismg.com" />)</para>
+
+ <para>Fyodor <email>fyodor@nmap.org</email> (<ulink url="https://insecure.org" />)</para>
+
+ </refsect1>
+
+
+</refentry>
diff --git a/nping/docs/nping-usage.txt b/nping/docs/nping-usage.txt
new file mode 100644
index 0000000..3e0cfca
--- /dev/null
+++ b/nping/docs/nping-usage.txt
@@ -0,0 +1,120 @@
+Nping 0.7.92SVN ( https://nmap.org/nping )
+Usage: nping [Probe mode] [Options] {target specification}
+
+TARGET SPECIFICATION:
+ Targets may be specified as hostnames, IP addresses, networks, etc.
+ Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.*.1-24
+PROBE MODES:
+ --tcp-connect : Unprivileged TCP connect probe mode.
+ --tcp : TCP probe mode.
+ --udp : UDP probe mode.
+ --icmp : ICMP probe mode.
+ --arp : ARP/RARP probe mode.
+ --tr, --traceroute : Traceroute mode (can only be used with
+ TCP/UDP/ICMP modes).
+TCP CONNECT MODE:
+ -p, --dest-port <port spec> : Set destination port(s).
+ -g, --source-port <portnumber> : Try to use a custom source port.
+TCP PROBE MODE:
+ -g, --source-port <portnumber> : Set source port.
+ -p, --dest-port <port spec> : Set destination port(s).
+ --seq <seqnumber> : Set sequence number.
+ --flags <flag list> : Set TCP flags (ACK,PSH,RST,SYN,FIN...)
+ --ack <acknumber> : Set ACK number.
+ --win <size> : Set window size.
+ --badsum : Use a random invalid checksum.
+UDP PROBE MODE:
+ -g, --source-port <portnumber> : Set source port.
+ -p, --dest-port <port spec> : Set destination port(s).
+ --badsum : Use a random invalid checksum.
+ICMP PROBE MODE:
+ --icmp-type <type> : ICMP type.
+ --icmp-code <code> : ICMP code.
+ --icmp-id <id> : Set identifier.
+ --icmp-seq <n> : Set sequence number.
+ --icmp-redirect-addr <addr> : Set redirect address.
+ --icmp-param-pointer <pnt> : Set parameter problem pointer.
+ --icmp-advert-lifetime <time> : Set router advertisement lifetime.
+ --icmp-advert-entry <IP,pref> : Add router advertisement entry.
+ --icmp-orig-time <timestamp> : Set originate timestamp.
+ --icmp-recv-time <timestamp> : Set receive timestamp.
+ --icmp-trans-time <timestamp> : Set transmit timestamp.
+ARP/RARP PROBE MODE:
+ --arp-type <type> : Type: ARP, ARP-reply, RARP, RARP-reply.
+ --arp-sender-mac <mac> : Set sender MAC address.
+ --arp-sender-ip <addr> : Set sender IP address.
+ --arp-target-mac <mac> : Set target MAC address.
+ --arp-target-ip <addr> : Set target IP address.
+IPv4 OPTIONS:
+ -S, --source-ip : Set source IP address.
+ --dest-ip <addr> : Set destination IP address (used as an
+ alternative to {target specification} ).
+ --tos <tos> : Set type of service field (8bits).
+ --id <id> : Set identification field (16 bits).
+ --df : Set Don't Fragment flag.
+ --mf : Set More Fragments flag.
+ --evil : Set Reserved / Evil flag.
+ --ttl <hops> : Set time to live [0-255].
+ --badsum-ip : Use a random invalid checksum.
+ --ip-options <S|R [route]|L [route]|T|U ...> : Set IP options
+ --ip-options <hex string> : Set IP options
+ --mtu <size> : Set MTU. Packets get fragmented if MTU is
+ small enough.
+IPv6 OPTIONS:
+ -6, --IPv6 : Use IP version 6.
+ --dest-ip : Set destination IP address (used as an
+ alternative to {target specification}).
+ --hop-limit : Set hop limit (same as IPv4 TTL).
+ --traffic-class <class> : : Set traffic class.
+ --flow <label> : Set flow label.
+ETHERNET OPTIONS:
+ --dest-mac <mac> : Set destination mac address. (Disables
+ ARP resolution)
+ --source-mac <mac> : Set source MAC address.
+ --ether-type <type> : Set EtherType value.
+PAYLOAD OPTIONS:
+ --data <hex string> : Include a custom payload.
+ --data-string <text> : Include a custom ASCII text.
+ --data-length <len> : Include len random bytes as payload.
+ECHO CLIENT/SERVER:
+ --echo-client <passphrase> : Run Nping in client mode.
+ --echo-server <passphrase> : Run Nping in server mode.
+ --echo-port <port> : Use custom <port> to listen or connect.
+ --no-crypto : Disable encryption and authentication.
+ --once : Stop the server after one connection.
+ --safe-payloads : Erase application data in echoed packets.
+TIMING AND PERFORMANCE:
+ Options which take <time> are in seconds, or append 'ms' (milliseconds),
+ 's' (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m, 0.25h).
+ --delay <time> : Adjust delay between probes.
+ --rate <rate> : Send num packets per second.
+MISC:
+ -h, --help : Display help information.
+ -V, --version : Display current version number.
+ -c, --count <n> : Stop after <n> rounds.
+ -e, --interface <name> : Use supplied network interface.
+ -H, --hide-sent : Do not display sent packets.
+ -N, --no-capture : Do not try to capture replies.
+ --privileged : Assume user is fully privileged.
+ --unprivileged : Assume user lacks raw socket privileges.
+ --send-eth : Send packets at the raw Ethernet layer.
+ --send-ip : Send packets using raw IP sockets.
+ --bpf-filter <filter spec> : Specify custom BPF filter.
+OUTPUT:
+ -v : Increment verbosity level by one.
+ -v[level] : Set verbosity level. E.g: -v4
+ -d : Increment debugging level by one.
+ -d[level] : Set debugging level. E.g: -d3
+ -q : Decrease verbosity level by one.
+ -q[N] : Decrease verbosity level N times
+ --quiet : Set verbosity and debug level to minimum.
+ --debug : Set verbosity and debug to the max level.
+EXAMPLES:
+ nping scanme.nmap.org
+ nping --tcp -p 80 --flags rst --ttl 2 192.168.1.1
+ nping --icmp --icmp-type time --delay 500ms 192.168.254.254
+ nping --echo-server "public" -e wlan0 -vvv
+ nping --echo-client "public" echo.nmap.org --tcp -p1-1024 --flags ack
+
+SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES
+
diff --git a/nping/docs/nping-usage.xml b/nping/docs/nping-usage.xml
new file mode 100644
index 0000000..6713aff
--- /dev/null
+++ b/nping/docs/nping-usage.xml
@@ -0,0 +1,2 @@
+<?dbfo-need height="1in"?>
+<screen><xi:include href="nping-usage.txt" parse="text" xmlns:xi="http://www.w3.org/2001/XInclude" /></screen>
diff --git a/nping/docs/nping.1 b/nping/docs/nping.1
new file mode 100644
index 0000000..2c92f41
--- /dev/null
+++ b/nping/docs/nping.1
@@ -0,0 +1,1797 @@
+'\" t
+.\" Title: nping
+.\" Author: [see the "Authors" section]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\" Date: 05/17/2023
+.\" Manual: Nping Reference Guide
+.\" Source: Nping
+.\" Language: English
+.\"
+.TH "NPING" "1" "05/17/2023" "Nping" "Nping Reference Guide"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nping \- Network packet generation tool / ping utility
+.SH "SYNOPSIS"
+.HP \w'\fBnping\fR\ 'u
+\fBnping\fR [\fIOptions\fR] {\fItargets\fR}
+.SH "DESCRIPTION"
+.PP
+Nping is an open\-source tool for network packet generation, response analysis and response time measurement\&. Nping allows users to generate network packets of a wide range of protocols, letting them tune virtually any field of the protocol headers\&. While Nping can be used as a simple ping utility to detect active hosts, it can also be used as a raw packet generator for network stack stress tests, ARP poisoning, Denial of Service attacks, route tracing, and other purposes\&.
+.PP
+Additionally, Nping offers a special mode of operation called the "Echo Mode", that lets users see how the generated probes change in transit, revealing the differences between the transmitted packets and the packets received at the other end\&. See section "Echo Mode" for details\&.
+.PP
+The output from Nping is a list of the packets that are being sent and received\&. The level of detail depends on the options used\&.
+.PP
+A typical Nping execution is shown in
+Example\ \&1\&. The only Nping arguments used in this example are
+\fB\-c\fR, to specify the number of times to target each host,
+\fB\-\-tcp\fR
+to specify TCP Probe Mode,
+\fB\-p 80,433\fR
+to specify the target ports; and then the two target hostnames\&.
+.PP
+\fBExample\ \&1.\ \&A representative Nping execution\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# \fBnping \-c 1 \-\-tcp \-p 80,433 scanme\&.nmap\&.org google\&.com\fR
+
+Starting Nping ( https://nmap\&.org/nping )
+SENT (0\&.0120s) TCP 96\&.16\&.226\&.135:50091 > 64\&.13\&.134\&.52:80 S ttl=64 id=52072 iplen=40 seq=1077657388 win=1480
+RCVD (0\&.1810s) TCP 64\&.13\&.134\&.52:80 > 96\&.16\&.226\&.135:50091 SA ttl=53 id=0 iplen=44 seq=4158134847 win=5840 <mss 1460>
+SENT (1\&.0140s) TCP 96\&.16\&.226\&.135:50091 > 74\&.125\&.45\&.100:80 S ttl=64 id=13932 iplen=40 seq=1077657388 win=1480
+RCVD (1\&.1370s) TCP 74\&.125\&.45\&.100:80 > 96\&.16\&.226\&.135:50091 SA ttl=52 id=52913 iplen=44 seq=2650443864 win=5720 <mss 1430>
+SENT (2\&.0140s) TCP 96\&.16\&.226\&.135:50091 > 64\&.13\&.134\&.52:433 S ttl=64 id=8373 iplen=40 seq=1077657388 win=1480
+SENT (3\&.0140s) TCP 96\&.16\&.226\&.135:50091 > 74\&.125\&.45\&.100:433 S ttl=64 id=23624 iplen=40 seq=1077657388 win=1480
+
+Statistics for host scanme\&.nmap\&.org (64\&.13\&.134\&.52):
+ | Probes Sent: 2 | Rcvd: 1 | Lost: 1 (50\&.00%)
+ |_ Max rtt: 169\&.720ms | Min rtt: 169\&.720ms | Avg rtt: 169\&.720ms
+Statistics for host google\&.com (74\&.125\&.45\&.100):
+ | Probes Sent: 2 | Rcvd: 1 | Lost: 1 (50\&.00%)
+ |_ Max rtt: 122\&.686ms | Min rtt: 122\&.686ms | Avg rtt: 122\&.686ms
+Raw packets sent: 4 (160B) | Rcvd: 2 (92B) | Lost: 2 (50\&.00%)
+Tx time: 3\&.00296s | Tx bytes/s: 53\&.28 | Tx pkts/s: 1\&.33
+Rx time: 3\&.00296s | Rx bytes/s: 30\&.64 | Rx pkts/s: 0\&.67
+Nping done: 2 IP addresses pinged in 4\&.01 seconds
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The newest version of Nping can be obtained with Nmap at
+\m[blue]\fB\%https://nmap.org\fR\m[]\&. The newest version of this man page is available at
+\m[blue]\fB\%https://nmap.org/book/nping-man.html\fR\m[]\&.
+
+\-\->
+ .SH "OPTIONS SUMMARY"
+.PP
+This options summary is printed when Nping is run with no arguments\&. It helps people remember the most common options, but is no substitute for the in\-depth documentation in the rest of this manual\&. Some obscure options aren\*(Aqt even included here\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+Nping 0\&.7\&.92SVN ( https://nmap\&.org/nping )
+Usage: nping [Probe mode] [Options] {target specification}
+
+TARGET SPECIFICATION:
+ Targets may be specified as hostnames, IP addresses, networks, etc\&.
+ Ex: scanme\&.nmap\&.org, microsoft\&.com/24, 192\&.168\&.0\&.1; 10\&.0\&.*\&.1\-24
+PROBE MODES:
+ \-\-tcp\-connect : Unprivileged TCP connect probe mode\&.
+ \-\-tcp : TCP probe mode\&.
+ \-\-udp : UDP probe mode\&.
+ \-\-icmp : ICMP probe mode\&.
+ \-\-arp : ARP/RARP probe mode\&.
+ \-\-tr, \-\-traceroute : Traceroute mode (can only be used with
+ TCP/UDP/ICMP modes)\&.
+TCP CONNECT MODE:
+ \-p, \-\-dest\-port <port spec> : Set destination port(s)\&.
+ \-g, \-\-source\-port <portnumber> : Try to use a custom source port\&.
+TCP PROBE MODE:
+ \-g, \-\-source\-port <portnumber> : Set source port\&.
+ \-p, \-\-dest\-port <port spec> : Set destination port(s)\&.
+ \-\-seq <seqnumber> : Set sequence number\&.
+ \-\-flags <flag list> : Set TCP flags (ACK,PSH,RST,SYN,FIN\&.\&.\&.)
+ \-\-ack <acknumber> : Set ACK number\&.
+ \-\-win <size> : Set window size\&.
+ \-\-badsum : Use a random invalid checksum\&.
+UDP PROBE MODE:
+ \-g, \-\-source\-port <portnumber> : Set source port\&.
+ \-p, \-\-dest\-port <port spec> : Set destination port(s)\&.
+ \-\-badsum : Use a random invalid checksum\&.
+ICMP PROBE MODE:
+ \-\-icmp\-type <type> : ICMP type\&.
+ \-\-icmp\-code <code> : ICMP code\&.
+ \-\-icmp\-id <id> : Set identifier\&.
+ \-\-icmp\-seq <n> : Set sequence number\&.
+ \-\-icmp\-redirect\-addr <addr> : Set redirect address\&.
+ \-\-icmp\-param\-pointer <pnt> : Set parameter problem pointer\&.
+ \-\-icmp\-advert\-lifetime <time> : Set router advertisement lifetime\&.
+ \-\-icmp\-advert\-entry <IP,pref> : Add router advertisement entry\&.
+ \-\-icmp\-orig\-time <timestamp> : Set originate timestamp\&.
+ \-\-icmp\-recv\-time <timestamp> : Set receive timestamp\&.
+ \-\-icmp\-trans\-time <timestamp> : Set transmit timestamp\&.
+ARP/RARP PROBE MODE:
+ \-\-arp\-type <type> : Type: ARP, ARP\-reply, RARP, RARP\-reply\&.
+ \-\-arp\-sender\-mac <mac> : Set sender MAC address\&.
+ \-\-arp\-sender\-ip <addr> : Set sender IP address\&.
+ \-\-arp\-target\-mac <mac> : Set target MAC address\&.
+ \-\-arp\-target\-ip <addr> : Set target IP address\&.
+IPv4 OPTIONS:
+ \-S, \-\-source\-ip : Set source IP address\&.
+ \-\-dest\-ip <addr> : Set destination IP address (used as an
+ alternative to {target specification} )\&.
+ \-\-tos <tos> : Set type of service field (8bits)\&.
+ \-\-id <id> : Set identification field (16 bits)\&.
+ \-\-df : Set Don\*(Aqt Fragment flag\&.
+ \-\-mf : Set More Fragments flag\&.
+ \-\-evil : Set Reserved / Evil flag\&.
+ \-\-ttl <hops> : Set time to live [0\-255]\&.
+ \-\-badsum\-ip : Use a random invalid checksum\&.
+ \-\-ip\-options <S|R [route]|L [route]|T|U \&.\&.\&.> : Set IP options
+ \-\-ip\-options <hex string> : Set IP options
+ \-\-mtu <size> : Set MTU\&. Packets get fragmented if MTU is
+ small enough\&.
+IPv6 OPTIONS:
+ \-6, \-\-IPv6 : Use IP version 6\&.
+ \-\-dest\-ip : Set destination IP address (used as an
+ alternative to {target specification})\&.
+ \-\-hop\-limit : Set hop limit (same as IPv4 TTL)\&.
+ \-\-traffic\-class <class> : : Set traffic class\&.
+ \-\-flow <label> : Set flow label\&.
+ETHERNET OPTIONS:
+ \-\-dest\-mac <mac> : Set destination mac address\&. (Disables
+ ARP resolution)
+ \-\-source\-mac <mac> : Set source MAC address\&.
+ \-\-ether\-type <type> : Set EtherType value\&.
+PAYLOAD OPTIONS:
+ \-\-data <hex string> : Include a custom payload\&.
+ \-\-data\-string <text> : Include a custom ASCII text\&.
+ \-\-data\-length <len> : Include len random bytes as payload\&.
+ECHO CLIENT/SERVER:
+ \-\-echo\-client <passphrase> : Run Nping in client mode\&.
+ \-\-echo\-server <passphrase> : Run Nping in server mode\&.
+ \-\-echo\-port <port> : Use custom <port> to listen or connect\&.
+ \-\-no\-crypto : Disable encryption and authentication\&.
+ \-\-once : Stop the server after one connection\&.
+ \-\-safe\-payloads : Erase application data in echoed packets\&.
+TIMING AND PERFORMANCE:
+ Options which take <time> are in seconds, or append \*(Aqms\*(Aq (milliseconds),
+ \*(Aqs\*(Aq (seconds), \*(Aqm\*(Aq (minutes), or \*(Aqh\*(Aq (hours) to the value (e\&.g\&. 30m, 0\&.25h)\&.
+ \-\-delay <time> : Adjust delay between probes\&.
+ \-\-rate <rate> : Send num packets per second\&.
+MISC:
+ \-h, \-\-help : Display help information\&.
+ \-V, \-\-version : Display current version number\&.
+ \-c, \-\-count <n> : Stop after <n> rounds\&.
+ \-e, \-\-interface <name> : Use supplied network interface\&.
+ \-H, \-\-hide\-sent : Do not display sent packets\&.
+ \-N, \-\-no\-capture : Do not try to capture replies\&.
+ \-\-privileged : Assume user is fully privileged\&.
+ \-\-unprivileged : Assume user lacks raw socket privileges\&.
+ \-\-send\-eth : Send packets at the raw Ethernet layer\&.
+ \-\-send\-ip : Send packets using raw IP sockets\&.
+ \-\-bpf\-filter <filter spec> : Specify custom BPF filter\&.
+OUTPUT:
+ \-v : Increment verbosity level by one\&.
+ \-v[level] : Set verbosity level\&. E\&.g: \-v4
+ \-d : Increment debugging level by one\&.
+ \-d[level] : Set debugging level\&. E\&.g: \-d3
+ \-q : Decrease verbosity level by one\&.
+ \-q[N] : Decrease verbosity level N times
+ \-\-quiet : Set verbosity and debug level to minimum\&.
+ \-\-debug : Set verbosity and debug to the max level\&.
+EXAMPLES:
+ nping scanme\&.nmap\&.org
+ nping \-\-tcp \-p 80 \-\-flags rst \-\-ttl 2 192\&.168\&.1\&.1
+ nping \-\-icmp \-\-icmp\-type time \-\-delay 500ms 192\&.168\&.254\&.254
+ nping \-\-echo\-server "public" \-e wlan0 \-vvv
+ nping \-\-echo\-client "public" echo\&.nmap\&.org \-\-tcp \-p1\-1024 \-\-flags ack
+
+SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES
+
+.fi
+.if n \{\
+.RE
+.\}
+.SH "TARGET SPECIFICATION"
+.PP
+Everything on the Nping command line that isn\*(Aqt an option or an option argument is treated as a target host specification\&. Nping uses the same syntax for target specifications that Nmap does\&. The simplest case is a single target given by IP address or hostname\&.
+.PP
+Nping supports CIDR\-style
+addressing\&. You can append
+/\fInumbits\fR
+to an IPv4 address or hostname and Nping will send probes to every IP address for which the first
+\fInumbits\fR
+are the same as for the reference IP or hostname given\&. For example,
+192\&.168\&.10\&.0/24
+would send probes to the 256 hosts between 192\&.168\&.10\&.0 (binary:
+11000000 10101000 00001010 00000000) and 192\&.168\&.10\&.255 (binary:
+11000000 10101000 00001010 11111111), inclusive\&.
+192\&.168\&.10\&.40/24
+would ping exactly the same targets\&. Given that the host scanme\&.nmap\&.org
+is at the IP address 64\&.13\&.134\&.52, the specification
+scanme\&.nmap\&.org/16
+would send probes to the 65,536 IP addresses between 64\&.13\&.0\&.0 and 64\&.13\&.255\&.255\&. The smallest allowed value is
+/0, which targets the whole Internet\&. The largest value is
+/32, which targets just the named host or IP address because all address bits are fixed\&.
+.PP
+CIDR notation is short but not always flexible enough\&. For example, you might want to send probes to 192\&.168\&.0\&.0/16 but skip any IPs ending with \&.0 or \&.255 because they may be used as subnet network and broadcast addresses\&. Nping supports this through octet range addressing\&. Rather than specify a normal IP address, you can specify a comma\-separated list of numbers or ranges for each octet\&. For example,
+192\&.168\&.0\-255\&.1\-254
+will skip all addresses in the range that end in \&.0 or \&.255, and
+192\&.168\&.3\-5,7\&.1
+will target the four addresses 192\&.168\&.3\&.1, 192\&.168\&.4\&.1, 192\&.168\&.5\&.1, and 192\&.168\&.7\&.1\&. Either side of a range may be omitted; the default values are 0 on the left and 255 on the right\&. Using
+\-
+by itself is the same as
+0\-255, but remember to use
+0\-
+in the first octet so the target specification doesn\*(Aqt look like a command\-line option\&. Ranges need not be limited to the final octets: the specifier
+0\-\&.\-\&.13\&.37
+will send probes to all IP addresses on the Internet ending in \&.13\&.37\&. This sort of broad sampling can be useful for Internet surveys and research\&.
+.PP
+IPv6 addresses can only be specified by their fully qualified IPv6 address or hostname\&. CIDR and octet ranges aren\*(Aqt supported for IPv6 because they are rarely useful\&.
+.PP
+Nping accepts multiple host specifications on the command line, and they don\*(Aqt need to be the same type\&. The command
+\fBnping scanme\&.nmap\&.org 192\&.168\&.0\&.0/8 10\&.0\&.0,1,3\-7\&.\-\fR
+does what you would expect\&.
+.SH "OPTION SPECIFICATION"
+.PP
+Nping is designed to be very flexible and fit a wide variety of needs\&. As with most command\-line tools, its behavior can be adjusted using command\-line options\&. These general principles apply to option arguments, unless stated otherwise\&.
+.PP
+Options that take integer numbers can accept values specified in decimal, octal or hexadecimal base\&. When a number starts with
+0x, it will be treated as hexadecimal; when it simply starts with
+0, it will be treated as octal\&. Otherwise, Nping will assume the number has been specified in base 10\&. Virtually all numbers that can be supplied from the command line are unsigned so, as a general rule, the minimum value is zero\&. Users may also specify the word
+random
+or
+rand
+to make Nping generate a random value within the expected range\&.
+.PP
+IP addresses may be given as IPv4 addresses (e\&.g\&.
+192\&.168\&.1\&.1), IPv6 addresses (e\&.g\&.
+2001:db8:85a3::8e4c:760:7146), or hostnames, which will be resolved using the default DNS server configured in the host system\&.
+.PP
+Options that take MAC addresses accept the usual colon\-separated 6 hex byte format (e\&.g\&.
+00:50:56:d4:01:98)\&. Hyphens may also be used instead of colons (e\&.g\&.
+00\-50\-56\-c0\-00\-08)\&. The special word
+random
+or
+rand
+sets a random address and the word
+broadcast
+or
+bcast
+sets ff:ff:ff:ff:ff:ff\&.
+.SH "GENERAL OPERATION"
+.PP
+Unlike other ping and packet generation tools, Nping supports multiple target host and port specifications\&. While this provides great flexibility, it is not obvious how Nping handles situations where there is more than one host and/or more than one port to send probes to\&. This section explains how Nping behaves in these cases\&.
+.PP
+When multiple target hosts are specified, Nping rotates among them in round\-robin fashion\&. This gives slow hosts more time to send their responses before another probe is sent to them\&. Ports are also scheduled using round robin\&. So, unless only one port is specified, Nping never sends two probes to the same target host and port consecutively\&.
+.PP
+The loop around targets is the
+\(lqinner loop\(rq
+and the loop around ports is the
+\(lqouter loop\(rq\&. All targets will be sent a probe for a given port before moving on to the next port\&. Between probes, Nping waits a configurable amount of time called the
+\(lqinter\-probe delay\(rq, which is controlled by the
+\fB\-\-delay\fR
+option\&. These examples show how it works\&.
+.PP
+.PP One target, three ports, and two rounds\&.
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# \fBnping \-\-tcp \-c 2 1\&.1\&.1\&.1 \-p 100\-102\fR
+
+Starting Nping ( https://nmap\&.org/nping )
+SENT (0\&.0210s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:100
+SENT (1\&.0230s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:101
+SENT (2\&.0250s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:102
+SENT (3\&.0280s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:100
+SENT (4\&.0300s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:101
+SENT (5\&.0320s) TCP 192\&.168\&.1\&.77 > 1\&.1\&.1\&.1:102
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+.PP Three targets, one port, and two rounds\&.
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# \fBnping \-\-tcp \-c 2 1\&.1\&.1\&.1 2\&.2\&.2\&.2 3\&.3\&.3\&.3 \-p 8080\fR
+
+Starting Nping ( https://nmap\&.org/nping )
+SENT (0\&.0230s) TCP 192\&.168\&.0\&.21 > 1\&.1\&.1\&.1:8080
+SENT (1\&.0240s) TCP 192\&.168\&.0\&.21 > 2\&.2\&.2\&.2:8080
+SENT (2\&.0260s) TCP 192\&.168\&.0\&.21 > 3\&.3\&.3\&.3:8080
+SENT (3\&.0270s) TCP 192\&.168\&.0\&.21 > 1\&.1\&.1\&.1:8080
+SENT (4\&.0290s) TCP 192\&.168\&.0\&.21 > 2\&.2\&.2\&.2:8080
+SENT (5\&.0310s) TCP 192\&.168\&.0\&.21 > 3\&.3\&.3\&.3:8080
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.PP
+.PP Three hosts, three ports, one round, inter\-probe delay of 500\ \&ms\&.
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# \fBnping \-\-tcp \-c 1 \-\-delay 500ms 1\&.1\&.1\&.1 2\&.2\&.2\&.2 3\&.3\&.3\&.3 \-p 137\-139\fR
+
+Starting Nping ( https://nmap\&.org/nping )
+SENT (0\&.0230s) TCP 192\&.168\&.0\&.21 > 1\&.1\&.1\&.1:137
+SENT (0\&.5250s) TCP 192\&.168\&.0\&.21 > 2\&.2\&.2\&.2:137
+SENT (1\&.0250s) TCP 192\&.168\&.0\&.21 > 3\&.3\&.3\&.3:137
+SENT (1\&.5280s) TCP 192\&.168\&.0\&.21 > 1\&.1\&.1\&.1:138
+SENT (2\&.0280s) TCP 192\&.168\&.0\&.21 > 2\&.2\&.2\&.2:138
+SENT (2\&.5310s) TCP 192\&.168\&.0\&.21 > 3\&.3\&.3\&.3:138
+SENT (3\&.0300s) TCP 192\&.168\&.0\&.21 > 1\&.1\&.1\&.1:139
+SENT (3\&.5330s) TCP 192\&.168\&.0\&.21 > 2\&.2\&.2\&.2:139
+SENT (4\&.0330s) TCP 192\&.168\&.0\&.21 > 3\&.3\&.3\&.3:139
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.SH "PROBE MODES"
+.PP
+Nping supports a wide variety of protocols\&. Although in some cases Nping can automatically determine the mode from the options used, it is generally a good idea to specify it explicitly\&.
+.PP
+\fB\-\-tcp\-connect\fR (TCP Connect mode)
+.RS 4
+TCP connect mode is the default mode when a user does not have raw packet privileges\&. Instead of writing raw packets as most other modes do, Nping asks the underlying operating system to establish a connection with the target machine and port by issuing the
+connect
+system call\&. This is the same high\-level system call that web browsers, P2P clients, and most other network\-enabled applications use to establish a connection\&. It is part of a programming interface known as the Berkeley Sockets API\&. Rather than read raw packet responses off the wire, Nping uses this API to obtain status information on each connection attempt\&. For this reason, you will not be able to see the contents of the packets that are sent or received but only status information about the TCP connection establishment taking place\&.
+.RE
+.PP
+\fB\-\-tcp\fR (TCP mode)
+.RS 4
+TCP is the mode that lets users create and send any kind of TCP packet\&. TCP packets are sent embedded in IP packets that can also be tuned\&. This mode can be used for many different purposes\&. For example you could try to discover open ports by sending TCP SYN messages without completing the three\-way handshake\&. This technique is often referred to as half\-open scanning, because you don\*(Aqt open a full TCP connection\&. You send a SYN packet, as if you are going to open a real connection and then wait for a response\&. A SYN/ACK indicates the port is open, while a RST indicates it\*(Aqs closed\&. If no response is received one could assume that some intermediate network device is filtering the responses\&. Another use could be to see how a remote TCP/IP stack behaves when it receives a non\-RFC\-compliant packet, like one with both SYN and RST flags set\&. One could also do some evil by creating custom RST packets using an spoofed IP address with the intent of closing an active TCP connection\&.
+.RE
+.PP
+\fB\-\-udp\fR (UDP mode)
+.RS 4
+UDP mode can have two different behaviours\&. Under normal circumstances, it lets users create custom IP/UDP packets\&. However, if Nping is run by a user without raw packet privileges and no changes to the default protocol headers are requested, then Nping enters the unprivileged UDP mode which basically sends UDP packets to the specified target hosts and ports using the
+sendto
+system call\&. Note that in this unprivileged mode it is not possible to see low\-level header information of the packets on the wire but only status information about the amount of bytes that are being transmitted and received\&. UDP mode can be used to interact with any UDP\-based server\&. Examples are DNS servers, streaming servers, online gaming servers, and port knocking/single\-packet
+authorization daemons\&.
+.RE
+.PP
+\fB\-\-icmp\fR (ICMP mode)
+.RS 4
+ICMP mode is the default mode when the user runs Nping with raw packet privileges\&. Any kind of ICMP message can be created\&. The default ICMP type is Echo, i\&.e\&., ping\&. ICMP mode can be used for many different purposes, from a simple request for a timestamp or a netmask to the transmission of fake destination unreachable messages, custom redirects, and router advertisements\&.
+.RE
+.PP
+\fB\-\-arp\fR (ARP/RARP mode)
+.RS 4
+ARP lets you create and send a few different ARP\-related packets\&. These include ARP, RARP, DRARP, and InARP requests and replies\&. This mode can ban be used to perform low\-level host discovery, and conduct ARP\-cache poisoning attacks\&.
+.RE
+.PP
+\fB\-\-traceroute\fR (Traceroute mode)
+.RS 4
+Traceroute is not a mode by itself but a complement to TCP, UDP, and ICMP modes\&. When this option is specified Nping will set the IP TTL value of the first probe to 1\&. When the next router receives the packet it will drop it due to the expiration of the TTL and it will generate an ICMP destination unreachable message\&. The next probe will have a TTL of 2 so now the first router will forward the packet while the second router will be the one that drops the packet and generates the ICMP message\&. The third probe will have a TTL value of 3 and so on\&. By examining the source addresses of all those ICMP Destination Unreachable messages it is possible to determine the path that the probes take until they reach their final destination\&.
+.RE
+.SH "TCP CONNECT MODE"
+.PP
+\fB\-p \fR\fB\fIport_spec\fR\fR, \fB\-\-dest\-port \fR\fB\fIport_spec\fR\fR (Target ports)
+.RS 4
+This option specifies which ports you want to try to connect to\&. It can be a single port, a comma\-separated list of ports (e\&.g\&.
+80,443,8080), a range (e\&.g\&.
+1\-1023), and any combination of those (e\&.g\&.
+21\-25,80,443,1024\-2048)\&. The beginning and/or end values of a range may be omitted, causing Nping to use 1 and 65535, respectively\&. So you can specify
+\-p\-
+to target ports from 1 through 65535\&. Using port zero is allowed if you specify it explicitly\&.
+.RE
+.PP
+\fB\-g \fR\fB\fIportnumber\fR\fR, \fB\-\-source\-port \fR\fB\fIportnumber\fR\fR (Spoof source port)
+.RS 4
+This option asks Nping to use the specified port as source port for the TCP connections\&. Note that this might not work on all systems or may require root privileges\&. Specified value must be an integer in the range [0\(en65535]\&.
+.RE
+.SH "TCP MODE"
+.PP
+\fB\-p \fR\fB\fIport_spec\fR\fR, \fB\-\-dest\-port \fR\fB\fIport_spec\fR\fR (Target ports)
+.RS 4
+This option specifies which destination ports you want to send probes to\&. It can be a single port, a comma\-separated list of ports (e\&.g\&.
+80,443,8080), a range (e\&.g\&.
+1\-1023), and any combination of those (e\&.g\&.
+21\-25,80,443,1024\-2048)\&. The beginning and/or end values of a range may be omitted, causing Nping to use 1 and 65535, respectively\&. So you can specify
+\-p\-
+to target ports from 1 through 65535\&. Using port zero is allowed if you specify it explicitly\&.
+.RE
+.PP
+\fB\-g \fR\fB\fIportnumber\fR\fR, \fB\-\-source\-port \fR\fB\fIportnumber\fR\fR (Spoof source port)
+.RS 4
+This option asks Nping to use the specified port as source port for the TCP connections\&. Note that this might not work on all systems or may require root privileges\&. Specified value must be an integer in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-seq \fR\fB\fIseqnumber\fR\fR (Sequence Number)
+.RS 4
+Specifies the TCP sequence number\&. In SYN packets this is the initial sequence number (ISN)\&. In a normal transmission this corresponds to the sequence number of the first byte of data in the segment\&.
+\fIseqnumber\fR
+must be a number in the range [0\(en4294967295]\&.
+.RE
+.PP
+\fB\-\-flags \fR\fB\fIflags\fR\fR (TCP Flags)
+.RS 4
+This option specifies which flags should be set in the TCP packet\&.
+\fIflags\fR
+may be specified in three different ways:
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 1.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 1." 4.2
+.\}
+As a comma\-separated list of flags, e\&.g\&.
+\fB\-\-flags syn,ack,rst\fR
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 2.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 2." 4.2
+.\}
+As a list of one\-character flag initials, e\&.g\&.
+\fB\-\-flags SAR\fR
+tells Nping to set flags SYN, ACK, and RST\&.
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 3.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 3." 4.2
+.\}
+As an 8\-bit hexadecimal number, where the supplied number is the exact value that will be placed in the flags field of the TCP header\&. The number should start with the prefix
+0x
+and should be in the range [0x00\(en0xFF], e\&.g\&.
+\-\-flags 0x20
+sets the URG flag as 0x20 corresponds to binary 00100000 and the URG flag is represented by the third bit\&.
+.RE
+.sp
+There are 8 possible flags to set:
+CWR,
+ECN,
+URG,
+ACK,
+PSH,
+RST,
+SYN, and
+FIN\&. The special value
+ALL
+means to set all flags\&.
+NONE
+means to set no flags\&. It is important that if you don\*(Aqt want any flag to be set, you request it explicitly because in some cases the SYN flag may be set by default\&. Here is a brief description of the meaning of each flag:
+.PP
+CWR (Congestion Window Reduced)
+.RS 4
+Set by an ECN\-Capable sender when it reduces its congestion window (due to a retransmit timeout, a fast retransmit or in response to an ECN notification\&.
+.RE
+.PP
+ECN (Explicit Congestion Notification)
+.RS 4
+During the three\-way handshake it indicates that sender is capable of performing explicit congestion notification\&. Normally it means that a packet with the IP Congestion Experienced flag set was received during normal transmission\&. See RFC 3168
+for more information\&.
+.RE
+.PP
+URG (Urgent)
+.RS 4
+Segment is urgent and the urgent pointer field carries valid information\&.
+.RE
+.PP
+ACK (Acknowledgement)
+.RS 4
+The segment carries an acknowledgement and the value of the acknowledgement number field is valid and contains the next sequence number that is expected from the receiver\&.
+.RE
+.PP
+PSH (Push)
+.RS 4
+The data in this segment should be immediately pushed to the application layer on arrival\&.
+.RE
+.PP
+RST (Reset)
+.RS 4
+There was some problem and the sender wants to abort the connection\&.
+.RE
+.PP
+SYN (Synchronize)
+.RS 4
+The segment is a request to synchronize sequence numbers and establish a connection\&. The sequence number field contains the sender\*(Aqs initial sequence number\&.
+.RE
+.PP
+FIN (Finish)
+.RS 4
+The sender wants to close the connection\&.
+.RE
+.RE
+.PP
+\fB\-\-win \fR\fB\fIsize\fR\fR (Window Size)
+.RS 4
+Specifies the TCP window size, this is, the number of octets the sender of the segment is willing to accept from the receiver at one time\&. This is usually the size of the reception buffer that the OS allocates for a given connection\&.
+\fIsize\fR
+must be a number in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-badsum\fR (Invalid Checksum)
+.RS 4
+Asks Nping to use an invalid TCP checksum for the packets sent to target hosts\&. Since virtually all host IP stacks properly drop these packets, any responses received are likely coming from a firewall or an IDS that didn\*(Aqt bother to verify the checksum\&. For more details on this technique, see
+\m[blue]\fB\%https://nmap.org/p60-12.html\fR\m[]\&.
+.RE
+.SH "UDP MODE"
+.PP
+\fB\-p \fR\fB\fIport_spec\fR\fR, \fB\-\-dest\-port \fR\fB\fIport_spec\fR\fR (Target ports)
+.RS 4
+This option specifies which ports you want UDP datagrams to be sent to\&. It can be a single port, a comma\-separated list of ports (e\&.g\&.
+80,443,8080), a range (e\&.g\&.
+1\-1023), and any combination of those (e\&.g\&.
+21\-25,80,443,1024\-2048)\&. The beginning and/or end values of a range may be omitted, causing Nping to use 1 and 65535, respectively\&. So you can specify
+\-p\-
+to target ports from 1 through 65535\&. Using port zero is allowed if you specify it explicitly\&.
+.RE
+.PP
+\fB\-g \fR\fB\fIportnumber\fR\fR, \fB\-\-source\-port \fR\fB\fIportnumber\fR\fR (Spoof source port)
+.RS 4
+This option asks Nping to use the specified port as source port for the transmitted datagrams\&. Note that this might not work on all systems or may require root privileges\&. Specified value must be an integer in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-badsum\fR (Invalid Checksum)
+.RS 4
+Asks Nping to use an invalid UDP checksum for the packets sent to target hosts\&. Since virtually all host IP stacks properly drop these packets, any responses received are likely coming from a firewall or an IDS that didn\*(Aqt bother to verify the checksum\&. For more details on this technique, see
+\m[blue]\fB\%https://nmap.org/p60-12.html\fR\m[]\&.
+.RE
+.SH "ICMP MODE"
+.PP
+\fB\-\-icmp\-type \fR\fB\fItype\fR\fR (ICMP type)
+.RS 4
+This option specifies which type of ICMP messages should be generated\&.
+\fItype\fR
+can be supplied in two different ways\&. You can use the
+\m[blue]\fBofficial type numbers assigned by IANA\fR\m[]\&\s-2\u[1]\d\s+2
+(e\&.g\&.
+\fB\-\-icmp\-type 8\fR
+for ICMP Echo Request), or you can use any of the mnemonics listed in
+the section called \(lqICMP Types\(rq\&.
+.RE
+.PP
+\fB\-\-icmp\-code \fR\fB\fIcode\fR\fR (ICMP code)
+.RS 4
+This option specifies which ICMP code should be included in the generated ICMP messages\&.
+\fIcode\fR
+can be supplied in two different ways\&. You can use the
+\m[blue]\fBofficial code numbers assigned by IANA\fR\m[]\&\s-2\u[1]\d\s+2
+(e\&.g\&.
+\fB\-\-icmp\-code 1\fR
+for Fragment Reassembly Time Exceeded), or you can use any of the mnemonics listed in
+the section called \(lqICMP Codes\(rq\&.
+.RE
+.PP
+\fB\-\-icmp\-id \fR\fB\fIid\fR\fR (ICMP identifier)
+.RS 4
+This option specifies the value of the identifier used in some of the ICMP messages\&. In general it is used to match request and reply messages\&.
+\fIid\fR
+must be a number in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-icmp\-seq \fR\fB\fIseq\fR\fR (ICMP sequence)
+.RS 4
+This option specifies the value of the sequence number field used in some ICMP messages\&. In general it is used to match request and reply messages\&.
+\fIid\fR
+must be a number in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-icmp\-redirect\-addr \fR\fB\fIaddr\fR\fR (ICMP Redirect address)
+.RS 4
+This option sets the address field in ICMP Redirect messages\&. In other words, it sets the IP address of the router that should be used when sending IP datagrams to the original destination\&.
+\fIaddr\fR
+can be either an IPv4 address or a hostname\&.
+.RE
+.PP
+\fB\-\-icmp\-param\-pointer \fR\fB\fIpointer\fR\fR (ICMP Parameter Problem pointer)
+.RS 4
+This option specifies the pointer that indicates the location of the problem in ICMP Parameter Problem messages\&.
+\fIpointer\fR
+should be a number in the range [0\(en255]\&. Normally this option is only used when ICMP code is set to 0 ("Pointer indicates the error")\&.
+.RE
+.PP
+\fB\-\-icmp\-advert\-lifetime \fR\fB\fIttl\fR\fR (ICMP Router Advertisement Lifetime)
+.RS 4
+This option specifies the router advertisement lifetime, this is, the number of seconds the information carried in an ICMP Router Advertisement can be considered valid for\&.
+\fIttl\fR
+must be a positive integer in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-icmp\-advert\-entry \fR\fB\fIaddr\fR\fR\fB,\fR\fB\fIpref\fR\fR (ICMP Router Advertisement Entry)
+.RS 4
+This option adds a Router Advertisement entry to an ICMP Router Advertisement message\&. The parameter must be two values separated by a comma\&.
+\fIaddr\fR
+is the router\*(Aqs IP and can be specified either as an IP address in dot\-decimal notation or as a hostname\&.
+\fIpref\fR
+is the preference level for the specified IP\&. It must be a number in the range [0\(en4294967295]\&. An example is
+\fB\-\-icmp\-advert\-entry 192\&.168\&.128\&.1,3\fR\&.
+.RE
+.PP
+\fB\-\-icmp\-orig\-time \fR\fB\fItimestamp\fR\fR (ICMP Originate Timestamp)
+.RS 4
+This option sets the Originate Timestamp in ICMP Timestamp messages\&. The Originate Timestamp is expressed as the number of milliseconds since midnight UTC and it corresponds to the time the sender last touched the Timestamp message before its transmission\&.
+\fItimestamp\fR
+can be specified as a regular time (e\&.g\&.
+10s,
+3h,
+1000ms), or the special string
+now\&. You can add or subtract values from
+now, for example
+\fB\-\-icmp\-orig\-time now\-2s\fR,
+\fB\-\-icmp\-orig\-time now+1h\fR,
+\fB\-\-icmp\-orig\-time now+200ms\fR\&.
+.RE
+.PP
+\fB\-\-icmp\-recv\-time \fR\fB\fItimestamp\fR\fR (ICMP Receive Timestamp)
+.RS 4
+This option sets the Receive Timestamp in ICMP Timestamp messages\&. The Receive Timestamp is expressed as the number of milliseconds since midnight UTC and it corresponds to the time the echoer first touched the Timestamp message on receipt\&.
+\fItimestamp\fR
+is as with
+\fB\-\-icmp\-orig\-time\fR\&.
+.RE
+.PP
+\fB\-\-icmp\-trans\-time \fR\fB\fItimestamp\fR\fR (ICMP Transmit Timestamp)
+.RS 4
+This option sets the Transmit Timestamp in ICMP Timestamp messages\&. The Transmit Timestamp is expressed as the number of milliseconds since midnight UTC and it corresponds to the time the echoer last touched the Timestamp message before its transmission\&.
+\fItimestamp\fR
+is as with
+\fB\-\-icmp\-orig\-time\fR\&.
+.RE
+.SS "ICMP Types"
+.PP
+These identifiers may be used as mnemonics for the ICMP type numbers given to the
+\fB\-\-icmp\-type\fR
+option\&. In general there are three forms of each identifier: the full name (e\&.g\&.
+destination\-unreachable), the short name (e\&.g\&.
+dest\-unr), or the initials (e\&.g\&.
+du)\&. In ICMP types that request something, the word "request" is omitted\&.
+.PP
+echo\-reply, echo\-rep, er
+.RS 4
+Echo Reply (type 0)\&. This message is sent in response to an Echo Request message\&.
+.RE
+.PP
+destination\-unreachable, dest\-unr, du
+.RS 4
+Destination Unreachable (type 3)\&. This message indicates that a datagram could not be delivered to its destination\&.
+.RE
+.PP
+source\-quench, sour\-que, sq
+.RS 4
+Source Quench (type 4)\&. This message is used by a congested IP device to tell other device that is sending packets too fast and that it should slow down\&.
+.RE
+.PP
+redirect, redi, r
+.RS 4
+Redirect (type 5)\&. This message is normally used by routers to inform a host that there is a better route to use for sending datagrams\&. See also the
+\fB\-\-icmp\-redirect\-addr\fR
+option\&.
+.RE
+.PP
+echo\-request, echo, e
+.RS 4
+Echo Request (type 8)\&. This message is used to test the connectivity of another device on a network\&.
+.RE
+.PP
+router\-advertisement, rout\-adv, ra
+.RS 4
+Router Advertisement (type 9)\&. This message is used by routers to let hosts know of their existence and capabilities\&. See also the
+\fB\-\-icmp\-advert\-lifetime\fR
+option\&.
+.RE
+.PP
+router\-solicitation, rout\-sol, rs
+.RS 4
+Router Solicitation (type 10)\&. This message is used by hosts to request Router Advertisement messages from any listening routers\&.
+.RE
+.PP
+time\-exceeded, time\-exc, te
+.RS 4
+Time Exceeded (type 11)\&. This message is generated by some intermediate device (normally a router) to indicate that a datagram has been discarded before reaching its destination because the IP TTL expired\&.
+.RE
+.PP
+parameter\-problem, member\-pro, pp
+.RS 4
+Parameter Problem (type 12)\&. This message is used when a device finds a problem with a parameter in an IP header and it cannot continue processing it\&. See also the
+\fB\-\-icmp\-param\-pointer\fR
+option\&.
+.RE
+.PP
+timestamp, time, tm
+.RS 4
+Timestamp Request (type 13)\&. This message is used to request a device to send a timestamp value for propagation time calculation and clock synchronization\&. See also the
+\fB\-\-icmp\-orig\-time\fR,
+\fB\-\-icmp\-recv\-time\fR, and
+\fB\-\-icmp\-trans\-time\fR\&.
+.RE
+.PP
+timestamp\-reply, time\-rep, tr
+.RS 4
+Timestamp Reply (type 14)\&. This message is sent in response to a Timestamp Request message\&.
+.RE
+.PP
+information, info, i
+.RS 4
+Information Request (type 15)\&. This message is now obsolete but it was originally used to request configuration information from another device\&.
+.RE
+.PP
+information\-reply, info\-rep, ir
+.RS 4
+Information Reply (type 16)\&. This message is now obsolete but it was originally sent in response to an Information Request message to provide configuration information\&.
+.RE
+.PP
+mask\-request, mask, m
+.RS 4
+Address Mask Request (type 17)\&. This message is used to ask a device to send its subnet mask\&.
+.RE
+.PP
+mask\-reply, mask\-rep, mr
+.RS 4
+Address Mask Reply (type 18)\&. This message contains a subnet mask and is sent in response to a Address Mask Request message\&.
+.RE
+.PP
+traceroute, trace, tc
+.RS 4
+Traceroute (type 30)\&. This message is normally sent by an intermediate device when it receives an IP datagram with a traceroute option\&. ICMP Traceroute messages are still experimental, see RFC 1393
+for more information\&.
+.RE
+.SS "ICMP Codes"
+.PP
+These identifiers may be used as mnemonics for the ICMP code numbers given to the
+\fB\-\-icmp\-code\fR
+option\&. They are listed by the ICMP type they correspond to\&.
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBDestination Unreachable\fR
+.RS 4
+.PP
+network\-unreachable, netw\-unr, net
+.RS 4
+Code 0\&. Datagram could not be delivered to its destination network (probably due to some routing problem)\&.
+.RE
+.PP
+host\-unreachable, host\-unr, host
+.RS 4
+Code 1\&. Datagram was delivered to the destination network but it was impossible to reach the specified host (probably due to some routing problem)\&.
+.RE
+.PP
+protocol\-unreachable, prot\-unr, proto
+.RS 4
+Code 2\&. The protocol specified in the Protocol field of the IP datagram is not supported by the host to which the datagram was delivered\&.
+.RE
+.PP
+port\-unreachable, port\-unr, port
+.RS 4
+Code 3\&. The TCP/UDP destination port was invalid\&.
+.RE
+.PP
+needs\-fragmentation, need\-fra, frag
+.RS 4
+Code 4\&. Datagram had the DF bit set but it was too large for the MTU of the next physical network so it had to be dropped\&.
+.RE
+.PP
+source\-route\-failed, sour\-rou, routefail
+.RS 4
+Code 5\&. IP datagram had a Source Route option but a router couldn\*(Aqt pass it to the next hop\&.
+.RE
+.PP
+network\-unknown, netw\-unk, net?
+.RS 4
+Code 6\&. Destination network is unknown\&. This code is never used\&. Instead, Network Unreachable is used\&.
+.RE
+.PP
+host\-unknown, host\-unk, host?
+.RS 4
+Code 7\&. Specified host is unknown\&. Usually generated by a router local to the destination host to inform of a bad address\&.
+.RE
+.PP
+host\-isolated, host\-iso, isolated
+.RS 4
+Code 8\&. Source Host Isolated\&. Not used\&.
+.RE
+.PP
+network\-prohibited, netw\-pro, !net
+.RS 4
+Code 9\&. Communication with destination network is administratively prohibited (source device is not allowed to send packets to the destination network)\&.
+.RE
+.PP
+host\-prohibited, host\-pro, !host
+.RS 4
+Code 10\&. Communication with destination host is administratively prohibited\&. (The source device is allowed to send packets to the destination network but not to the destination device\&.)
+.RE
+.PP
+network\-tos, unreachable\-network\-tos, netw\-tos, tosnet
+.RS 4
+Code 11\&. Destination network unreachable because it cannot provide the type of service specified in the IP TOS field\&.
+.RE
+.PP
+host\-tos, unreachable\-host\-tos, toshost
+.RS 4
+Code 12\&. Destination host unreachable because it cannot provide the type of service specified in the IP TOS field\&.
+.RE
+.PP
+communication\-prohibited, comm\-pro, !comm
+.RS 4
+Code 13\&. Datagram could not be forwarded due to filtering that blocks the message based on its contents\&.
+.RE
+.PP
+host\-precedence\-violation, precedence\-violation, prec\-vio, violation
+.RS 4
+Code 14\&. Precedence value in the IP TOS field is not permitted\&.
+.RE
+.PP
+precedence\-cutoff, prec\-cut, cutoff
+.RS 4
+Code 15\&. Precedence value in the IP TOS field is lower than the minimum allowed for the network\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBRedirect\fR
+.RS 4
+.PP
+redirect\-network, redi\-net, net
+.RS 4
+Code 0\&. Redirect all future datagrams with the same destination network as the original datagram, to the router specified in the Address field\&. The use of this code is prohibited by RFC 1812\&.
+.RE
+.PP
+redirect\-host, redi\-host, host
+.RS 4
+Code 1\&. Redirect all future datagrams with the same destination host as the original datagram, to the router specified in the Address field\&.
+.RE
+.PP
+redirect\-network\-tos, redi\-ntos, redir\-ntos
+.RS 4
+Code 2\&. Redirect all future datagrams with the same destination network and IP TOS value as the original datagram, to the router specified in the Address field\&. The use of this code is prohibited by RFC 1812\&.
+.RE
+.PP
+redirect\-host\-tos, redi\-htos, redir\-htos
+.RS 4
+Code 3\&. Redirect all future datagrams with the same destination host and IP TOS value as the original datagram, to the router specified in the Address field\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBRouter Advertisement\fR
+.RS 4
+.PP
+normal\-advertisement, norm\-adv, normal, zero, default, def
+.RS 4
+Code 0\&. Normal router advertisement\&. In Mobile IP: Mobility agent can act as a router for IP datagrams not related to mobile nodes\&.
+.RE
+.PP
+not\-route\-common\-traffic, not\-rou, mobile\-ip, !route, !commontraffic
+.RS 4
+Code 16\&. Used for Mobile IP\&. The mobility agent does not route common traffic\&. All foreign agents must forward to a default router any datagrams received from a registered mobile node
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBTime Exceeded\fR
+.RS 4
+.PP
+ttl\-exceeded\-in\-transit, ttl\-exc, ttl\-transit
+.RS 4
+Code 0\&. IP Time To Live expired during transit\&.
+.RE
+.PP
+fragment\-reassembly\-time\-exceeded, frag\-exc, frag\-time
+.RS 4
+Code 1\&. Fragment reassembly time has been exceeded\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBParameter Problem\fR
+.RS 4
+.PP
+pointer\-indicates\-error, poin\-ind, pointer
+.RS 4
+Code 0\&. The pointer field indicates the location of the problem\&. See the
+\fB\-\-icmp\-param\-pointer\fR
+option\&.
+.RE
+.PP
+missing\-required\-option, miss\-option, option\-missing
+.RS 4
+Code 1\&. IP datagram was expected to have an option that is not present\&.
+.RE
+.PP
+bad\-length, bad\-len, badlen
+.RS 4
+Code 2\&. The length of the IP datagram is incorrect\&.
+.RE
+.RE
+.SH "ARP MODE"
+.PP
+\fB\-\-arp\-type \fR\fB\fItype\fR\fR (ICMP Type)
+.RS 4
+This option specifies which type of ARP messages should be generated\&.
+\fItype\fR
+can be supplied in two different ways\&. You can use the
+\m[blue]\fBofficial numbers assigned by IANA\fR\m[]\&\s-2\u[2]\d\s+2
+(e\&.g\&.
+\fB\-\-arp\-type 1\fR
+for ARP Request), or you can use one of the mnemonics from
+the section called \(lqARP Types\(rq\&.
+.RE
+.PP
+\fB\-\-arp\-sender\-mac \fR\fB\fImac\fR\fR (Sender MAC address)
+.RS 4
+This option sets the Sender Hardware Address field of the ARP header\&. Although ARP supports many types of link layer addresses, currently Nping only supports MAC addresses\&.
+\fImac\fR
+must be specified using the traditional MAC notation (e\&.g\&.
+00:0a:8a:32:f4:ae)\&. You can also use hyphens as separators (e\&.g\&.
+00\-0a\-8a\-32\-f4\-ae)\&.
+.RE
+.PP
+\fB\-\-arp\-sender\-ip \fR\fB\fIaddr\fR\fR (Sender IP address)
+.RS 4
+This option sets the Sender IP field of the ARP header\&.
+\fIaddr\fR
+can be given as an IPv4 address or a hostname\&.
+.RE
+.PP
+\fB\-\-arp\-target\-mac \fR\fB\fImac\fR\fR (target MAC address)
+.RS 4
+This option sets the Target Hardware Address field of the ARP header\&.
+.RE
+.PP
+\fB\-\-arp\-target\-ip \fR\fB\fIaddr\fR\fR (target ip address)
+.RS 4
+This option sets the Target IP field of the ARP header\&.
+.RE
+.SS "ARP Types"
+.PP
+These identifiers may be used as mnemonics for the ARP type numbers given to the
+\fB\-\-arp\-type\fR
+option\&.
+.PP
+arp\-request, arp, a
+.RS 4
+ARP Request (type 1)\&. ARP requests are used to translate network layer addresses (normally IP addresses) to link layer addresses (usually MAC addresses)\&. Basically, and ARP request is a broadcasted message that asks the host in the same network segment that has a given IP address to provide its MAC address\&.
+.RE
+.PP
+arp\-reply, arp\-rep, ar
+.RS 4
+ARP Reply (type 2)\&. An ARP reply is a message that a host sends in response to an ARP request to provide its link layer address\&.
+.RE
+.PP
+rarp\-request, rarp, r
+.RS 4
+RARP Requests (type 3)\&. RARP requests are used to translate a link layer address (normally a MAC address) to a network layer address (usually an IP address)\&. Basically a RARP request is a broadcasted message sent by a host that wants to know his own IP address because it doesn\*(Aqt have any\&. It was the first protocol designed to solve the bootstrapping problem\&. However, RARP is now obsolete and DHCP is used instead\&. For more information about RARP see RFC 903\&.
+.RE
+.PP
+rarp\-reply, rarp\-rep, rr
+.RS 4
+RARP Reply (type 4)\&. A RARP reply is a message sent in response to a RARP request to provide an IP address to the host that sent the RARP request in the first place\&.
+.RE
+.PP
+drarp\-request, drarp, d
+.RS 4
+Dynamic RARP Request (type 5)\&. Dynamic RARP is an extension to RARP used to obtain or assign a network layer address from a fixed link layer address\&. DRARP was used mainly in Sun Microsystems platforms in the late 90\*(Aqs but now it\*(Aqs no longer used\&. See RFC 1931
+for more information\&.
+.RE
+.PP
+drarp\-reply, drarp\-rep, dr
+.RS 4
+Dynamic RARP Reply (type 6)\&. A DRARP reply is a message sent in response to a RARP request to provide network layer address\&.
+.RE
+.PP
+drarp\-error, drarp\-err, de
+.RS 4
+DRARP Error (type 7)\&. DRARP Error messages are usually sent in response to DRARP requests to inform of some error\&. In DRARP Error messages, the Target Protocol Address field is used to carry an error code (usually in the first byte)\&. The error code is intended to tell why no target protocol address is being returned\&. For more information see RFC 1931\&.
+.RE
+.PP
+inarp\-request, inarp, i
+.RS 4
+Inverse ARP Request (type 8)\&. InARP requests are used to translate a link layer address to a network layer address\&. It is similar to RARP request but in this case, the sender of the InARP request wants to know the network layer address of another node, not its own address\&. InARP is mainly used in Frame Relay and ATM networks\&. For more information see RFC 2390\&.
+.RE
+.PP
+inarp\-reply, inarp\-rep, ir
+.RS 4
+Inverse ARP Reply (type 9)\&. InARP reply messages are sent in response to InARP requests to provide the network layer address associated with the host that has a given link layer address\&.
+.RE
+.PP
+arp\-nak, an
+.RS 4
+ARP NAK (type 10)\&. ARP NAK messages are an extension to the ATMARP protocol and they are used to improve the robustness of the ATMARP server mechanism\&. With ARP NAK, a client can determine the difference between a catastrophic server failure and an ATMARP table lookup failure\&. See RFC 1577
+for more information\&.
+.RE
+.SH "IPV4 OPTIONS"
+.PP
+\fB\-S \fR\fB\fIaddr\fR\fR, \fB\-\-source\-ip \fR\fB\fIaddr\fR\fR (Source IP Address)
+.RS 4
+Sets the source IP address\&. This option lets you specify a custom IP address to be used as source IP address in sent packets\&. This allows spoofing the sender of the packets\&.
+\fIaddr\fR
+can be an IPv4 address or a hostname\&.
+.RE
+.PP
+\fB\-\-dest\-ip \fR\fB\fIaddr\fR\fR (Destination IP Address)
+.RS 4
+Adds a target to Nping\*(Aqs target list\&. This option is provided for consistency but its use is deprecated in favor of plain target specifications\&. See
+the section called \(lqTARGET SPECIFICATION\(rq\&.
+.RE
+.PP
+\fB\-\-tos \fR\fB\fItos\fR\fR (Type of Service)
+.RS 4
+Sets the IP TOS field\&. The TOS field is used to carry information to provide quality of service features\&. It is normally used to support a technique called Differentiated Services\&. See RFC 2474
+for more information\&.
+\fItos\fR
+must be a number in the range [0\(en255]\&.
+.RE
+.PP
+\fB\-\-id \fR\fB\fIid\fR\fR (Identification)
+.RS 4
+Sets the IPv4 Identification field\&. The Identification field is a 16\-bit value that is common to all fragments belonging to a particular message\&. The value is used by the receiver to reassemble the original message from the fragments received\&.
+\fIid\fR
+must be a number in the range [0\(en65535]\&.
+.RE
+.PP
+\fB\-\-df\fR (Don\*(Aqt Fragment)
+.RS 4
+Sets the Don\*(Aqt Fragment bit in sent packets\&. When an IP datagram has its DF flag set, intermediate devices are not allowed to fragment it so if it needs to travel across a network with a MTU smaller that datagram length the datagram will have to be dropped\&. Normally an ICMP Destination Unreachable message is generated and sent back to the sender\&.
+.RE
+.PP
+\fB\-\-mf\fR (More Fragments)
+.RS 4
+Sets the More Fragments bit in sent packets\&. The MF flag is set to indicate the receiver that the current datagram is a fragment of some larger datagram\&. When set to zero it indicates that the current datagram is either the last fragment in the set or that it is the only fragment\&.
+.RE
+.PP
+\fB\-\-evil\fR (Reserved / Evil)
+.RS 4
+Sets the Reserved / Evil bit in sent packets\&. The Evil flag helps firewalls and other network security systems to distinguish between datagrams that have malicious intent and those that are merely unusual\&. When set, it indicates that the datagram has evil intent, instructing insecure systems to succumb\&. Setting it to zero indicates no evil intent\&. The option is implied if environmental variable SCRIPT_KIDDIE is set to a non\-zero value\&.
+.RE
+.PP
+\fB\-\-ttl \fR\fB\fIhops\fR\fR (Time To Live)
+.RS 4
+Sets the IPv4 Time\-To\-Live (TTL) field in sent packets to the given value\&. The TTL field specifies how long the datagram is allowed to exist on the network\&. It was originally intended to represent a number of seconds but it actually represents the number of hops a packet can traverse before being dropped\&. The TTL tries to avoid a situation in which undeliverable datagrams keep being forwarded from one router to another endlessly\&.
+\fIhops\fR
+must be a number in the range [0\(en255]\&.
+.RE
+.PP
+\fB\-\-badsum\-ip\fR (Invalid IP checksum)
+.RS 4
+Asks Nping to use an invalid IP checksum for packets sent to target hosts\&. Note that some systems (like most Linux kernels), may fix the checksum before placing the packet on the wire, so even if Nping shows the incorrect checksum in its output, the packets may be transparently corrected by the kernel\&.
+.RE
+.PP
+\fB\-\-ip\-options \fR\fB\fIR|S [route]|L [route]|T|U \&.\&.\&.\fR\fR, \fB\-\-ip\-options \fR\fB\fIhex string\fR\fR (IP Options)
+.RS 4
+The IP protocol offers several options which may be placed in packet headers\&. Unlike the ubiquitous TCP options, IP options are rarely seen due to practicality and security concerns\&. In fact, many Internet routers block the most dangerous options such as source routing\&. Yet options can still be useful in some cases for determining and manipulating the network route to target machines\&. For example, you may be able to use the record route option to determine a path to a target even when more traditional traceroute\-style approaches fail\&. Or if your packets are being dropped by a certain firewall, you may be able to specify a different route with the strict or loose source routing options\&.
+.sp
+The most powerful way to specify IP options is to simply pass in hexadecimal data as the argument to
+\fB\-\-ip\-options\fR\&. Precede each hex byte value with
+\ex\&. You may repeat certain characters by following them with an asterisk and then the number of times you wish them to repeat\&. For example,
+\ex01\ex07\ex04\ex00*4
+is the same as
+\ex01\ex07\ex04\ex00\ex00\ex00\ex00\&.
+.sp
+Note that if you specify a number of bytes that is not a multiple of four, an incorrect IP header length will be set in the IP packet\&. The reason for this is that the IP header length field can only express multiples of four\&. In those cases, the length is computed by dividing the header length by 4 and rounding down\&. This will affect the way the header that follows the IP header is interpreted, showing bogus information in Nping or in the output of any sniffer\&. Although this kind of situation might be useful for some stack stress tests, users would normally want to specify explicit padding, so the correct header length is set\&.
+.sp
+Nping also offers a shortcut mechanism for specifying options\&. Simply pass the letter
+R,
+T, or
+U
+to request record\-route, record\-timestamp, or both options together, respectively\&. Loose or strict source routing may be specified with an L or S followed by a space and then a space\-separated list of IP addresses\&.
+.sp
+For more information and examples of using IP options with Nping, see the mailing list post at
+\m[blue]\fB\%https://seclists.org/nmap-dev/2006/q3/0052.html\fR\m[]\&.
+.RE
+.PP
+\fB\-\-mtu \fR\fB\fIsize\fR\fR (Maximum Transmission Unit)
+.RS 4
+This option sets a fictional MTU in Nping so IP datagrams larger than
+\fIsize\fR
+are fragmented before transmission\&.
+\fIsize\fR
+must be specified in bytes and corresponds to the number of octets that can be carried on a single link\-layer frame\&.
+.RE
+.SH "IPV6 OPTIONS"
+.PP
+\fB\-6\fR, \fB\-\-ipv6\fR (Use IPv6)
+.RS 4
+Tells Nping to use IP version 6 instead of the default IPv4\&. It is generally a good idea to specify this option as early as possible in the command line so Nping can parse it soon and know in advance that the rest of the parameters refer to IPv6\&. The command syntax is the same as usual except that you also add the
+\fB\-6\fR
+option\&. Of course, you must use IPv6 syntax if you specify an address rather than a hostname\&. An address might look like
+\fB3ffe:7501:4819:2000:210:f3ff:fe03:14d0\fR, so hostnames are recommended\&.
+.sp
+While IPv6 hasn\*(Aqt exactly taken the world by storm, it gets significant use in some (usually Asian) countries and most modern operating systems support it\&. To use Nping with IPv6, both the source and target of your packets must be configured for IPv6\&. If your ISP (like most of them) does not allocate IPv6 addresses to you, free tunnel brokers are widely available and work fine with Nping\&. You can use the free IPv6 tunnel broker service at
+\m[blue]\fB\%http://www.tunnelbroker.net\fR\m[]\&.
+.sp
+Please note that IPv6 support is still highly experimental and many modes and options may not work with it\&.
+.RE
+.PP
+\fB\-S \fR\fB\fIaddr\fR\fR, \fB\-\-source\-ip \fR\fB\fIaddr\fR\fR (Source IP Address)
+.RS 4
+Sets the source IP address\&. This option lets you specify a custom IP address to be used as source IP address in sent packets\&. This allows spoofing the sender of the packets\&.
+\fIaddr\fR
+can be an IPv6 address or a hostname\&.
+.RE
+.PP
+\fB\-\-dest\-ip \fR\fB\fIaddr\fR\fR (Destination IP Address)
+.RS 4
+Adds a target to Nping\*(Aqs target list\&. This option is provided for consistency but its use is deprecated in favor of plain target specifications\&. See
+the section called \(lqTARGET SPECIFICATION\(rq\&.
+.RE
+.PP
+\fB\-\-flow \fR\fB\fIlabel\fR\fR (Flow Label)
+.RS 4
+Sets the IPv6 Flow Label\&. The Flow Label field is 20 bits long and is intended to provide certain quality\-of\-service properties for real\-time datagram delivery\&. However, it has not been widely adopted, and not all routers or endpoints support it\&. Check RFC 2460
+for more information\&.
+\fIlabel\fR
+must be an integer in the range [0\(en1048575]\&.
+.RE
+.PP
+\fB\-\-traffic\-class \fR\fB\fIclass\fR\fR (Traffic Class)
+.RS 4
+Sets the IPv6 Traffic Class\&. This field is similar to the TOS field in IPv4, and is intended to provide the Differentiated Services method, enabling scalable service discrimination in the Internet without the need for per\-flow state and signaling at every hop\&. Check RFC 2474
+for more information\&.
+\fIclass\fR
+must be an integer in the range [0\(en255]\&.
+.RE
+.PP
+\fB\-\-hop\-limit \fR\fB\fIhops\fR\fR (Hop Limit)
+.RS 4
+
+Sets the IPv6 Hop Limit field in sent packets to the given value\&. The Hop Limit field specifies how long the datagram is allowed to exist on the network\&. It represents the number of hops a packet can traverse before being dropped\&. As with the TTL in IPv4, IPv6 Hop Limit tries to avoid a situation in which undeliverable datagrams keep being forwarded from one router to another endlessly\&.
+\fIhops\fR
+must be a number in the range [0\(en255]\&.
+.RE
+.SH "ETHERNET OPTIONS"
+.PP
+In most cases Nping sends packets at the raw IP level\&. This means that Nping creates its own IP packets and transmits them through a raw socket\&. However, in some cases it may be necessary to send packets at the raw Ethernet level\&. This happens, for example, when Nping is run under Windows (as Microsoft has disabled raw socket support since Windows XP SP2), or when Nping is asked to send ARP packets\&. Since in some cases it is necessary to construct ethernet frames, Nping offers some options to manipulate the different fields\&.
+.PP
+\fB\-\-dest\-mac \fR\fB\fImac\fR\fR (Ethernet Destination MAC Address)
+.RS 4
+This option sets the destination MAC address that should be set in outgoing Ethernet frames\&. This is useful in case Nping can\*(Aqt determine the next hop\*(Aqs MAC address or when you want to route probes through a router other than the configured default gateway\&. The MAC address should have the usual format of six colon\-separated bytes, e\&.g\&.
+00:50:56:d4:01:98\&. Alternatively, hyphens may be used instead of colons\&. Use the word
+random
+or
+rand
+to generate a random address, and
+broadcast
+or
+bcast
+to use ff:ff:ff:ff:ff:ff\&. If you set up a bogus destination MAC address your probes may not reach the intended targets\&.
+.RE
+.PP
+\fB\-\-source\-mac \fR\fB\fImac\fR\fR (Ethernet Source MAC Address)
+.RS 4
+This option sets the source MAC address that should be set in outgoing Ethernet frames\&. This is useful in case Nping can\*(Aqt determine your network interface MAC address or when you want to inject traffic into the network while hiding your network card\*(Aqs real address\&. The syntax is the same as for
+\-\-dest\-mac\&. If you set up a bogus source MAC address you may not receive probe replies\&.
+.RE
+.PP
+\fB\-\-ether\-type \fR\fB\fItype\fR\fR (Ethertype)
+.RS 4
+This option sets the Ethertype field of the ethernet frame\&. The Ethertype is used to indicate which protocol is encapsulated in the payload\&.
+\fItype\fR
+can be supplied in two different ways\&. You can use the
+\m[blue]\fBofficial numbers listed by the IEEE\fR\m[]\&\s-2\u[3]\d\s+2
+(e\&.g\&.
+\fB\-\-ether\-type 0x0800\fR
+for IP version 4), or one of the mnemonics from
+the section called \(lqEthernet Types\(rq\&.
+.RE
+.SS "Ethernet Types"
+.PP
+These identifiers may be used as mnemonics for the Ethertype numbers given to the
+\fB\-\-arp\-type\fR
+option\&.
+.PP
+ipv4, ip, 4
+.RS 4
+Internet Protocol version 4 (type 0x0800)\&.
+.RE
+.PP
+ipv6, 6
+.RS 4
+Internet Protocol version 6 (type 0x86DD)\&.
+.RE
+.PP
+arp
+.RS 4
+Address Resolution Protocol (type 0x0806)\&.
+.RE
+.PP
+rarp
+.RS 4
+Reverse Address Resolution Protocol (type 0x8035)\&.
+.RE
+.PP
+frame\-relay, frelay, fr
+.RS 4
+Frame Relay (type 0x0808)\&.
+.RE
+.PP
+ppp
+.RS 4
+Point\-to\-Point Protocol (type 0x880B)\&.
+.RE
+.PP
+gsmp
+.RS 4
+General Switch Management Protocol (type 0x880C)\&.
+.RE
+.PP
+mpls
+.RS 4
+Multiprotocol Label Switching (type 0x8847)\&.
+.RE
+.PP
+mps\-ual, mps
+.RS 4
+Multiprotocol Label Switching with Upstream\-assigned Label (type 0x8848)\&.
+.RE
+.PP
+mcap
+.RS 4
+Multicast Channel Allocation Protocol (type 0x8861)\&.
+.RE
+.PP
+pppoe\-discovery, pppoe\-d
+.RS 4
+PPP over Ethernet Discovery Stage (type 0x8863)\&.
+.RE
+.PP
+pppoe\-session, pppoe\-s
+.RS 4
+PPP over Ethernet Session Stage (type 0x8864)\&.
+.RE
+.PP
+ctag
+.RS 4
+Customer VLAN Tag Type (type 0x8100)\&.
+.RE
+.PP
+epon
+.RS 4
+Ethernet Passive Optical Network (type 0x8808)\&.
+.RE
+.PP
+pbnac
+.RS 4
+Port\-based network access control (type 0x888E)\&.
+.RE
+.PP
+stag
+.RS 4
+Service VLAN tag identifier (type 0x88A8)\&.
+.RE
+.PP
+ethexp1
+.RS 4
+Local Experimental Ethertype 1 (type 0x88B5)\&.
+.RE
+.PP
+ethexp2
+.RS 4
+Local Experimental Ethertype 2 (type 0x88B6)\&.
+.RE
+.PP
+ethoui
+.RS 4
+OUI Extended Ethertype (type 0x88B7)\&.
+.RE
+.PP
+preauth
+.RS 4
+Pre\-Authentication (type 0x88C7)\&.
+.RE
+.PP
+lldp
+.RS 4
+Link Layer Discovery Protocol (type 0x88CC)\&.
+.RE
+.PP
+mac\-security, mac\-sec, macsec
+.RS 4
+Media Access Control Security (type 0x88E5)\&.
+.RE
+.PP
+mvrp
+.RS 4
+Multiple VLAN Registration Protocol (type 0x88F5)\&.
+.RE
+.PP
+mmrp
+.RS 4
+Multiple Multicast Registration Protocol (type 0x88F6)\&.
+.RE
+.PP
+frrr
+.RS 4
+Fast Roaming Remote Request (type 0x890D)\&.
+.RE
+.SH "PAYLOAD OPTIONS"
+.PP
+\fB\-\-data \fR\fB\fIhex string\fR\fR (Append custom binary data to sent packets)
+.RS 4
+This option lets you include binary data as payload in sent packets\&.
+\fIhex string\fR
+may be specified in any of the following formats:
+0xAABBCCDDEEFF\fI\&.\&.\&.\fR,
+AABBCCDDEEFF\fI\&.\&.\&.\fR
+or
+\exAA\exBB\exCC\exDD\exEE\exFF\fI\&.\&.\&.\fR\&. Examples of use are
+\fB\-\-data 0xdeadbeef\fR
+and
+\fB\-\-data \exCA\exFE\ex09\fR\&. Note that if you specify a number like
+0x00ff
+no byte\-order conversion is performed\&. Make sure you specify the information in the byte order expected by the receiver\&.
+.RE
+.PP
+\fB\-\-data\-string \fR\fB\fIstring\fR\fR (Append custom string to sent packets)
+.RS 4
+This option lets you include a regular string as payload in sent packets\&.
+\fIstring\fR
+can contain any string\&. However, note that some characters may depend on your system\*(Aqs locale and the receiver may not see the same information\&. Also, make sure you enclose the string in double quotes and escape any special characters from the shell\&. Example:
+\fB\-\-data\-string "Jimmy Jazz\&.\&.\&."\fR\&.
+.RE
+.PP
+\fB\-\-data\-length \fR\fB\fIlen\fR\fR (Append random data to sent packets)
+.RS 4
+This option lets you include
+\fIlen\fR
+random bytes of data as payload in sent packets\&.
+\fIlen\fR
+must be an integer in the range [0\(en65400]\&. However, values higher than 1400 are not recommended because it may not be possible to transmit packets due to network MTU limitations\&.
+.RE
+.SH "ECHO MODE"
+.PP
+The "Echo Mode" is a novel technique implemented by Nping which lets users see how network packets change in transit, from the host where they originated to the target machine\&. Basically, the Echo mode turns Nping into two different pieces: the Echo server and the Echo client\&. The Echo server is a network service that has the ability to capture packets from the network and send a copy ("echo them") to the originating client through a side TCP channel\&. The Echo client is the part that generates such network packets, transmits them to the server, and receives their echoed version through a side TCP channel that it has previously established with the Echo server\&.
+.PP
+This scheme lets the client see the differences between the packets that it sends and what is actually received by the server\&. By having the server send back copies of the received packets through the side channel, things like NAT devices become immediately apparent to the client because it notices the changes in the source IP address (and maybe even source port)\&. Other devices like those that perform traffic shaping, changing TCP window sizes or adding TCP options transparently between hosts, turn up too\&.
+.PP
+The Echo mode is also useful for troubleshooting routing and firewall issues\&. Among other things, it can be used to determine if the traffic generated by the Nping client is being dropped in transit and never gets to its destination or if the responses are the ones that don\*(Aqt get back to it\&.
+.PP
+Internally, client and server communicate over an encrypted and authenticated channel, using the Nping Echo Protocol (NEP), whose technical specification can be found in
+\m[blue]\fB\%https://nmap.org/svn/nping/docs/EchoProtoRFC.txt\fR\m[]
+.PP
+The following paragraphs describe the different options available in Nping\*(Aqs Echo mode\&.
+.PP
+\fB\-\-ec \fR\fB\fIpassphrase\fR\fR, \fB\-\-echo\-client \fR\fB\fIpassphrase\fR\fR (Run Echo client)
+.RS 4
+This option tells Nping to run as an Echo client\&.
+\fIpassphrase\fR
+is a sequence of ASCII characters that is used used to generate the cryptographic keys needed for encryption and authentication in a given session\&. The passphrase should be a secret that is also known by the server, and it may contain any number of printable ASCII characters\&. Passphrases that contain whitespace or special characters must be enclosed in double quotes\&.
+.sp
+When running Nping as an Echo client, most options from the regular raw probe modes apply\&. The client may be configured to send specific probes using flags like
+\fB\-\-tcp\fR,
+\fB\-\-icmp\fR
+or
+\fB\-\-udp\fR\&. Protocol header fields may be manipulated normally using the appropriate options (e\&.g\&.
+\fB\-\-ttl\fR,
+\fB\-\-seq\fR,
+\fB\-\-icmp\-type\fR, etc\&.)\&. The only exceptions are ARP\-related flags, which are not supported in Echo mode, as protocols like ARP are closely related to the data link layer and its probes can\*(Aqt pass through different network segments\&.
+.RE
+.PP
+\fB\-\-es \fR\fB\fIpassphrase\fR\fR, \fB\-\-echo\-server \fR\fB\fIpassphrase\fR\fR (Run Echo server)
+.RS 4
+This option tells Nping to run as an Echo server\&.
+\fIpassphrase\fR
+is a sequence of ASCII characters that is used used to generate the cryptographic keys needed for encryption and authentication in a given session\&. The passphrase should be a secret that is also known by the clients, and it may contain any number of printable ASCII characters\&. Passphrases that contain whitespace or special characters must be enclosed in double quotes\&. Note that although it is not recommended, it is possible to use empty passphrases, supplying
+\fB\-\-echo\-server ""\fR\&. However, if what you want is to set up an open Echo server, it is better to use option
+\fB\-\-no\-crypto\fR\&. See below for details\&.
+.RE
+.PP
+\fB\-\-ep \fR\fB\fIport\fR\fR, \fB\-\-echo\-port \fR\fB\fIport\fR\fR (Set Echo TCP port number)
+.RS 4
+This option asks Nping to use the specified TCP port number for the Echo side channel connection\&. If this option is used with
+\fB\-\-echo\-server\fR, it specifies the port on which the server listens for connections\&. If it is used with
+\fB\-\-echo\-client\fR, it specifies the port to connect to on the remote host\&. By default, port number 9929 is used\&.
+.RE
+.PP
+\fB\-\-nc\fR, \fB\-\-no\-crypto\fR (Disable encryption and authentication)
+.RS 4
+This option asks Nping not to use any cryptographic operations during an Echo session\&. In practical terms, this means that the Echo side channel session data will be transmitted in the clear, and no authentication will be performed by the server or client during the session establishment phase\&. When
+\fB\-\-no\-crypto\fR
+is used, the passphrase supplied with
+\fB\-\-echo\-server\fR
+or
+\fB\-\-echo\-client\fR
+is ignored\&.
+.sp
+This option must be specified if Nping was compiled without openSSL support\&. Note that, for technical reasons, a passphrase still needs to be supplied after the \-\-echo\-client or \-\-echo\-server flags, even though it will be ignored\&.
+.sp
+The \-\-no\-crypto flag might be useful when setting up a public Echo server, because it allows users to connect to the Echo server without the need for any passphrase or shared secret\&. However, it is strongly recommended to not use \-\-no\-crypto unless absolutely necessary\&. Public Echo servers should be configured to use the passphrase "public" or the empty passphrase (\-\-echo\-server "") as the use of cryptography does not only provide confidentiality and authentication but also message integrity\&.
+.RE
+.PP
+\fB\-\-once\fR (Serve one client and quit)
+.RS 4
+This option asks the Echo server to quit after serving one client\&. This is useful when only a single Echo session wants to be established as it eliminates the need to access the remote host to shutdown the server\&.
+.RE
+.PP
+\fB\-\-safe\-payloads\fR (Zero application data before echoing a packet)
+.RS 4
+This option asks the Echo server to erase any application layer data found in client packets before echoing them\&. When the option is enabled, the Echo server parses the packets received from Echo clients and tries to determine if they contain data beyond the transport layer\&. If such data is found, it is overwritten with zeroes before transmitting the packets to the appropriate Echo client\&.
+.sp
+Echo servers can handle multiple simultaneous clients running multiple echo sessions in parallel\&. In order to determine which packet needs to be echoed to which client and through which session, the Echo server uses an heuristic algorithm\&. Although we have taken every security measure that we could think of to prevent that a client receives an echoed packet that it did not generate, there is always a risk that our algorithm makes a mistake and delivers a packet to the wrong client\&. The \-\-safe\-payloads option is useful for public echo servers or critical deployments where that kind of mistake cannot be afforded\&.
+.RE
+.PP
+The following examples illustrate how Nping\*(Aqs Echo mode can be used to discover intermediate devices\&.
+.PP
+\fBExample\ \&2.\ \&Discovering NAT devices\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ # \fBnping \-\-echo\-client "public" echo\&.nmap\&.org \-\-udp \fR
+
+ Starting Nping ( https://nmap\&.org/nping )
+ SENT (1\&.0970s) UDP 10\&.1\&.20\&.128:53 > 178\&.79\&.165\&.17:40125 ttl=64 id=32523 iplen=28
+ CAPT (1\&.1270s) UDP 80\&.38\&.10\&.21:45657 > 178\&.79\&.165\&.17:40125 ttl=54 id=32523 iplen=28
+ RCVD (1\&.1570s) ICMP 178\&.79\&.165\&.17 > 10\&.1\&.20\&.128 Port unreachable (type=3/code=3) ttl=49 id=16619 iplen=56
+ [\&.\&.\&.]
+ SENT (5\&.1020s) UDP 10\&.1\&.20\&.128:53 > 178\&.79\&.165\&.17:40125 ttl=64 id=32523 iplen=28
+ CAPT (5\&.1335s) UDP 80\&.38\&.10\&.21:45657 > 178\&.79\&.165\&.17:40125 ttl=54 id=32523 iplen=28
+ RCVD (5\&.1600s) ICMP 178\&.79\&.165\&.17 > 10\&.1\&.20\&.128 Port unreachable (type=3/code=3) ttl=49 id=16623 iplen=56
+
+ Max rtt: 60\&.628ms | Min rtt: 58\&.378ms | Avg rtt: 59\&.389ms
+ Raw packets sent: 5 (140B) | Rcvd: 5 (280B) | Lost: 0 (0\&.00%)| Echoed: 5 (140B)
+ Tx time: 4\&.00459s | Tx bytes/s: 34\&.96 | Tx pkts/s: 1\&.25
+ Rx time: 5\&.00629s | Rx bytes/s: 55\&.93 | Rx pkts/s: 1\&.00
+ Nping done: 1 IP address pinged in 6\&.18 seconds
+
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The output clearly shows the presence of a NAT device in the client\*(Aqs local network\&. Note how the captured packet (CAPT) differs from the SENT packet: the source address for the original packets is in the reserved 10\&.0\&.0\&.0/8 range, while the address seen by the server is 80\&.38\&.10\&.21, the Internet side address of the NAT device\&. The source port was also modified by the device\&. The line starting with RCVD corresponds to the responses generated by the TCP/IP stack of the machine where the Echo server is run\&.
+.PP
+\fBExample\ \&3.\ \&Discovering a transparent proxy\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ # \fBnping \-\-echo\-client "public" echo\&.nmap\&.org \-\-tcp \-p80\fR
+
+ Starting Nping ( https://nmap\&.org/nping )
+ SENT (1\&.2160s) TCP 10\&.0\&.1\&.77:41659 > 178\&.79\&.165\&.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ RCVD (1\&.2180s) TCP 178\&.79\&.165\&.17:80 > 10\&.0\&.1\&.77:41659 SA ttl=128 id=13177 iplen=44 seq=3647106954 win=16384 <mss 1460>
+ SENT (2\&.2150s) TCP 10\&.0\&.1\&.77:41659 > 178\&.79\&.165\&.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (3\&.2180s) TCP 10\&.0\&.1\&.77:41659 > 178\&.79\&.165\&.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (4\&.2190s) TCP 10\&.0\&.1\&.77:41659 > 178\&.79\&.165\&.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+ SENT (5\&.2200s) TCP 10\&.0\&.1\&.77:41659 > 178\&.79\&.165\&.17:80 S ttl=64 id=3317 iplen=40 seq=567704200 win=1480
+
+ Max rtt: 2\&.062ms | Min rtt: 2\&.062ms | Avg rtt: 2\&.062ms
+ Raw packets sent: 5 (200B) | Rcvd: 1 (46B) | Lost: 4 (80\&.00%)| Echoed: 0 (0B)
+ Tx time: 4\&.00504s | Tx bytes/s: 49\&.94 | Tx pkts/s: 1\&.25
+ Rx time: 5\&.00618s | Rx bytes/s: 9\&.19 | Rx pkts/s: 0\&.20
+ Nping done: 1 IP address pinged in 6\&.39 seconds
+
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+In this example, the output is a bit more tricky\&. The absence of error messages shows that the Echo client has successfully established an Echo session with the server\&. However, no CAPT packets can be seen in the output\&. This means that none of the transmitted packets reached the server\&. Interestingly, a TCP SYN\-ACK packet was received in response to the first TCP\-SYN packet (and also, it is known that the target host does not have port 80 open)\&. This behavior reveals the presence of a transparent web proxy cache server (which in this case is an old MS ISA server)\&.
+.SH "TIMING AND PERFORMANCE OPTIONS"
+.PP
+\fB\-\-delay \fR\fB\fItime\fR\fR (Delay between probes)
+.RS 4
+This option lets you control for how long will Nping wait before sending the next probe\&. Like in many other ping tools, the default delay is one second\&.
+\fItime\fR
+must be a positive integer or floating point number\&. By default it is specified in seconds, however you can give an explicit unit by appending
+ms
+for milliseconds,
+s
+for seconds,
+m
+for minutes, or
+h
+for hours (e\&.g\&.
+2\&.5s,
+45m,
+2h)\&.
+.RE
+.PP
+\fB\-\-rate \fR\fB\fIrate\fR\fR (Send probes at a given rate)
+.RS 4
+This option specifies the number of probes that Nping should send per second\&. This option and
+\fB\-\-delay\fR
+are inverses;
+\fB\-\-rate 20\fR
+is the same as
+\fB\-\-delay 0\&.05\fR\&. If both options are used, only the last one in the parameter list counts\&.
+.RE
+.SH "MISCELLANEOUS OPTIONS"
+.PP
+\fB\-h\fR, \fB\-\-help\fR (Display help)
+.RS 4
+Displays help information and exits\&.
+.RE
+.PP
+\fB\-V\fR, \fB\-\-version\fR (Display version)
+.RS 4
+Displays the program\*(Aqs version number and quits\&.
+.RE
+.PP
+\fB\-c \fR\fB\fIrounds\fR\fR, \fB\-\-count \fR\fB\fIrounds\fR\fR (Stop after a given number of rounds)
+.RS 4
+This option lets you specify the number of times that Nping should loop over target hosts (and in some cases target ports)\&. Nping calls these
+\(lqrounds\(rq\&. In a basic execution with only one target (and only one target port in TCP/UDP modes), the number of rounds matches the number of probes sent to the target host\&. However, in more complex executions where Nping is run against multiple targets and multiple ports, the number of rounds is the number of times that Nping sends a complete set of probes that covers all target IPs and all target ports\&. For example, if Nping is asked to send TCP SYN packets to hosts 192\&.168\&.1\&.0\-255 and ports 80 and 433, then 256 \(mu 2\ \&=\ \&512 packets are sent in one round\&. So if you specify
+\fB\-c 100\fR, Nping will loop over the different target hosts and ports 100 times, sending a total of 256 \(mu 2 \(mu 100\ \&=\ \&51200 packets\&. By default Nping runs for 5 rounds\&. If a value of 0 is specified, Nping will run continuously\&.
+.RE
+.PP
+\fB\-e \fR\fB\fIname\fR\fR, \fB\-\-interface \fR\fB\fIname\fR\fR (Set the network interface to be used)
+.RS 4
+This option tells Nping what interface should be used to send and receive packets\&. Nping should be able to detect this automatically, but it will tell you if it cannot\&.
+\fIname\fR
+must be the name of an existing network interface with an assigned IP address\&.
+.RE
+.PP
+\fB\-\-privileged\fR (Assume that the user is fully privileged)
+.RS 4
+Tells Nping to simply assume that it is privileged enough to perform raw socket sends, packet sniffing, and similar operations that usually require special privileges\&. By default Nping quits if such operations are requested by a user that has no root or administrator privileges\&. This option may be useful on Linux, BSD or similar systems that can be configured to allow unprivileged users to perform raw\-packet transmissions\&. The
+\fBNPING_PRIVILEGED\fR
+environment variable may be set as an alternative to using
+\fB\-\-privileged\fR\&.
+.RE
+.PP
+\fB\-\-unprivileged\fR (Assume that the user lacks raw socket privileges)
+.RS 4
+This option is the opposite of
+\fB\-\-privileged\fR\&. It tells Nping to treat the user as lacking network raw socket and sniffing privileges\&. This is useful for testing, debugging, or when the raw network functionality of your operating system is somehow broken\&. The
+\fBNPING_UNPRIVILEGED\fR
+environment variable may be set as an alternative to using
+\fB\-\-unprivileged\fR\&.
+.RE
+.PP
+\fB\-\-send\-eth\fR (Use raw ethernet sending)
+.RS 4
+Asks Nping to send packets at the raw ethernet (data link) layer rather than the higher IP (network) layer\&. By default, Nping chooses the one which is generally best for the platform it is running on\&. Raw sockets (IP layer) are generally most efficient for Unix machines, while ethernet frames are required for Windows operation since Microsoft disabled raw socket support\&. Nping still uses raw IP packets despite this option when there is no other choice (such as non\-ethernet connections)\&.
+.RE
+.PP
+\fB\-\-send\-ip\fR (Send at raw IP level)
+.RS 4
+Asks Nping to send packets via raw IP sockets rather than sending lower level ethernet frames\&. It is the complement to the
+\fB\-\-send\-eth\fR
+option\&.
+.RE
+.PP
+\fB\-\-bpf\-filter \fR\fB\fIfilter spec\fR\fR \fB\-\-filter \fR\fB\fIfilter spec\fR\fR (Set custom BPF filter)
+.RS 4
+This option lets you use a custom BPF filter\&. By default Nping chooses a filter that is intended to capture most common responses to the particular probes that are sent\&. For example, when sending TCP packets, the filter is set to capture packets whose destination port matches the probe\*(Aqs source port or ICMP error messages that may be generated by the target or any intermediate device as a result of the probe\&. If for some reason you expect strange packets in response to sent probes or you just want to sniff a particular kind of traffic, you can specify a custom filter using the BPF syntax used by tools like tcpdump\&.
+See the documentation at
+\m[blue]\fB\%http://www.tcpdump.org/\fR\m[]
+for more information\&.
+.RE
+.PP
+\fB\-H\fR, \fB\-\-hide\-sent\fR (Do not display sent packets)
+.RS 4
+This option tells Nping not to print information about sent packets\&. This can be useful when using very short inter\-probe delays (i\&.e\&., when flooding), because printing information to the standard output has a computational cost and disabling it can probably speed things up a bit\&. Also, it may be useful when using Nping to detect active hosts or open ports (e\&.g\&. sending probes to all TCP ports in a /24 subnet)\&. In that case, users may not want to see thousands of sent probes but just the replies generated by active hosts\&.
+.RE
+.PP
+\fB\-N\fR, \fB\-\-no\-capture\fR (Do not attempt to capture replies)
+.RS 4
+This option tells Nping to skip packet capture\&. This means that packets in response to sent probes will not be processed or displayed\&. This can be useful when doing flooding and network stack stress tests\&. Note that when this option is specified, most of the statistics shown at the end of the execution will be useless\&. This option does not work with TCP Connect mode\&.
+.RE
+.SH "OUTPUT OPTIONS"
+.PP
+\fB\-v\fR\fB[\fIlevel\fR]\fR, \fB\-\-verbose \fR\fB[\fIlevel\fR]\fR (Increase or set verbosity level)
+.RS 4
+Increases the verbosity level, causing Nping to print more information during its execution\&. There are 9 levels of verbosity (\-4 to 4)\&. Every instance of
+\fB\-v\fR
+increments the verbosity level by one (from its default value, level 0)\&. Every instance of option
+\fB\-q\fR
+decrements the verbosity level by one\&. Alternatively you can specify the level directly, as in
+\fB\-v3\fR
+or
+\fB\-v\-1\fR\&. These are the available levels:
+.PP
+Level \-4
+.RS 4
+No output at all\&. In some circumstances you may not want Nping to produce any output (like when one of your work mates is watching over your shoulder)\&. In that case level \-4 can be useful because although you won\*(Aqt see any response packets, probes will still be sent\&.
+.RE
+.PP
+Level \-3
+.RS 4
+Like level \-4 but displays fatal error messages so you can actually see if Nping is running or it failed due to some error\&.
+.RE
+.PP
+Level \-2
+.RS 4
+Like level \-3 but also displays warnings and recoverable errors\&.
+.RE
+.PP
+Level \-1
+.RS 4
+Displays traditional run\-time information (version, start time, statistics, etc\&.) but does not display sent or received packets\&.
+.RE
+.PP
+Level 0
+.RS 4
+This is the default verbosity level\&. It behaves like level \-1 but also displays sent and received packets and some other important information\&.
+.RE
+.PP
+Level 1
+.RS 4
+Like level 0 but it displays detailed information about timing, flags, protocol details, etc\&.
+.RE
+.PP
+Level 2
+.RS 4
+Like level 1 but displays very detailed information about sent and received packets and other interesting information\&.
+.RE
+.PP
+Level 3
+.RS 4
+Like level 2 but also displays the raw hexadecimal dump of sent and received packets\&.
+.RE
+.PP
+Level 4 and higher
+.RS 4
+Same as level 3\&.
+.RE
+.RE
+.PP
+\fB\-q\fR\fB[\fIlevel\fR]\fR, \fB\-\-reduce\-verbosity \fR\fB[\fIlevel\fR]\fR (Decrease verbosity level)
+.RS 4
+Decreases the verbosity level, causing Nping to print less information during its execution\&.
+.RE
+.PP
+\fB\-d\fR\fB[\fIlevel\fR]\fR (Increase or set debugging level)
+.RS 4
+When even verbose mode doesn\*(Aqt provide sufficient data for you, debugging is available to flood you with much more! As with the
+\fB\-v\fR, debugging is enabled with a command\-line flag
+\fB\-d\fR
+and the debug level can be increased by specifying it multiple times\&. There are 7 debugging levels (0 to 6)\&. Every instance of
+\fB\-d\fR
+increments debugging level by one\&. Provide an argument to
+\fB\-d\fR
+to set the level directly; for example
+\fB\-d4\fR\&.
+.sp
+Debugging output is useful when you suspect a bug in Nping, or if you are simply confused as to what Nping is doing and why\&. As this feature is mostly intended for developers, debug lines aren\*(Aqt always self\-explanatory\&. You may get something like
+
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+NSOCK (1\&.0000s) Callback: TIMER SUCCESS for EID 12; tcpconnect_event_handler(): Received callback of type TIMER with status SUCCESS
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+If you don\*(Aqt understand a line, your only recourses are to ignore it, look it up in the source code, or request help from the development list (nmap\-dev)\&. Some lines are self\-explanatory, but the messages become more obscure as the debug level is increased\&. These are the available levels:
+.PP
+Level 0
+.RS 4
+Level 0\&. No debug information at all\&. This is the default level\&.
+.RE
+.PP
+Level 1
+.RS 4
+In this level, only very important or high\-level debug information will be printed\&.
+.RE
+.PP
+Level 2
+.RS 4
+Like level 1 but also displays important or medium\-level debug information
+.RE
+.PP
+Level 3
+.RS 4
+Like level 2 but also displays regular and low\-level debug information\&.
+.RE
+.PP
+Level 4
+.RS 4
+Like level 3 but also displays messages only a real Nping freak would want to see\&.
+.RE
+.PP
+Level 5
+.RS 4
+Like level 4 but it enables basic debug information related to external libraries like Nsock\&.
+.RE
+.PP
+Level 6
+.RS 4
+Like level 5 but it enables full, very detailed, debug information related to external libraries like Nsock\&.
+.RE
+.RE
+.SH "BUGS"
+.PP
+Like its authors, Nping isn\*(Aqt perfect\&. But you can help make it better by sending bug reports or even writing patches\&. If Nping doesn\*(Aqt behave the way you expect, first upgrade to the latest version available from
+\m[blue]\fB\%https://nmap.org\fR\m[]\&. If the problem persists, do some research to determine whether it has already been discovered and addressed\&. Try searching for the problem or error message on Google since that aggregates so many forums\&. If nothing comes of this, create an Issue on our tracker (\m[blue]\fB\%http://issues.nmap.org\fR\m[]) and/or mail a bug report to
+<dev@nmap\&.org>\&. If you subscribe to the nmap\-dev list before posting, your message will bypass moderation and get through more quickly\&. Subscribe at
+\m[blue]\fB\%https://nmap.org/mailman/listinfo/dev\fR\m[]\&. Please include everything you have learned about the problem, as well as what version of Nping you are using and what operating system version it is running on\&. Other suggestions for improving Nping may be sent to the Nmap dev mailing list as well\&.
+.PP
+If you are able to write a patch improving Nping or fixing a bug, that is even better! Instructions for submitting patches or git pull requests are available from
+\m[blue]\fB\%https://github.com/nmap/nmap/blob/master/CONTRIBUTING.md\fR\m[]
+.PP
+Particularly sensitive issues such as a security reports may be sent directly to Fyodor directly at
+<fyodor@nmap\&.org>\&. All other reports and comments should use the dev list or issue tracker instead because more people read, follow, and respond to those\&.
+.SH "AUTHORS"
+.PP
+Luis MartinGarcia
+<luis\&.mgarc@gmail\&.com>
+(\m[blue]\fB\%http://www.luismg.com\fR\m[])
+.PP
+Fyodor
+<fyodor@nmap\&.org>
+(\m[blue]\fB\%https://insecure.org\fR\m[])
+.SH "NOTES"
+.IP " 1." 4
+official type numbers assigned by IANA
+.RS 4
+\%http://www.iana.org/assignments/icmp-parameters
+.RE
+.IP " 2." 4
+official numbers assigned by IANA
+.RS 4
+\%http://www.iana.org/assignments/arp-parameters/
+.RE
+.IP " 3." 4
+official numbers listed by the IEEE
+.RS 4
+\%http://standards.ieee.org/regauth/ethertype/eth.txt
+.RE
diff --git a/nping/docs/npingmanhtml.xml b/nping/docs/npingmanhtml.xml
new file mode 100644
index 0000000..bf801fe
--- /dev/null
+++ b/nping/docs/npingmanhtml.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
+[
+<!ENTITY refguide SYSTEM "nping-man.xml">
+<!ENTITY nping-usage SYSTEM "nping-usage.xml">
+]>
+<article id="npingman">
+<artheader>
+<title>Nping Reference Guide (Man Page)</title>
+</artheader>
+&refguide;
+</article>
diff --git a/nping/doxyfile b/nping/doxyfile
new file mode 100644
index 0000000..7acb1bb
--- /dev/null
+++ b/nping/doxyfile
@@ -0,0 +1,239 @@
+# Doxyfile 1.5.5
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = Nping
+PROJECT_NUMBER = 0.1
+OUTPUT_DIRECTORY = dox
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = YES
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 4
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = YES
+EXTRACT_ANON_NSPACES = YES
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = YES
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT =
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = YES
+STRIP_CODE_COMMENTS = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = YES
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+CALLER_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/nping/global_structures.h b/nping/global_structures.h
new file mode 100644
index 0000000..aeae3af
--- /dev/null
+++ b/nping/global_structures.h
@@ -0,0 +1,33 @@
+#ifndef GLOBAL_STRUCTURES_H
+#define GLOBAL_STRUCTURES_H
+
+#include "nsock.h"
+#include "nbase.h"
+
+
+typedef struct service_lookup {
+ char *name;
+ u8 proto;
+ u16 portno;
+} service_lookup;
+
+
+
+typedef struct m_data {
+ nsock_pool nsp;
+ nsock_iod nsi;
+ int state;
+ int protocol;
+ unsigned short port;
+ struct in_addr ip;
+ int attempts;
+ int max_attempts; /* how many attempts in one connection */
+ char *username;
+ char *password;
+ char *buf;
+ int bufsize;
+} m_data;
+
+
+
+#endif
diff --git a/nping/nping-dev/Diagram1.dia b/nping/nping-dev/Diagram1.dia
new file mode 100644
index 0000000..0ecb76c
--- /dev/null
+++ b/nping/nping-dev/Diagram1.dia
Binary files differ
diff --git a/nping/nping-dev/EchoProtoRFC_v0.txt b/nping/nping-dev/EchoProtoRFC_v0.txt
new file mode 100644
index 0000000..65f1a88
--- /dev/null
+++ b/nping/nping-dev/EchoProtoRFC_v0.txt
@@ -0,0 +1,741 @@
++-----------------------------------------------------------------------------+
+
+
+
+
+
+
+ NPING ECHO PROTOCOL
+
+
+
+
+ PROTOCOL SPECIFICATION
+
+ Request for Comments
+
+ July 2009
+
+
+
+
+
+ Luis MartinGarcia
+ (luis.mgarc@gmail.com)
+
+
+
+
+
+
++-----------------------------------------------------------------------------+
+
+
+
+
+ PREFACE
+
+This document introduces Nping Echo Protocol, the protocol that has been
+designed to support a new feature that allows Nping users to see what the
+packets they send look like when they reach their destination.
+
+
+
+ TABLE OF CONTENTS
+
+1. INTRODUCTION ..................................................... x
+
+
+2. NPING ECHO PROTOCOL SPECIFICATION................................. x
+
+ 2.1 General Packet Format.............. ........................... x
+ 2.2 Field Description ............................................. x
+ 2.3 Operation Codes ............................................... x
+ 2.4 Operation HELLO................................................ x
+ 2.5 Operation HELLO RESPONSE ...................................... x
+ 2.6 Operation SPECS ............................................... x
+ 2.7 Operation READY ............................................... x
+ 2.8 Operation ECHOPKT ............................................. x
+ 2.9 Operation QUIT ................................................ x
+ 2.10 Flow Diagram .................................................. x
+ 2.11 Security .......................................................x
+
+3. GLOSSARY .......................................................... x
+
+4. REFERENCES ........................................................ x
+
+
+
+
+
+
+
+
+
+
+
+
+
+1. INTRODUCTION
+
+ Troubleshooting routing and firewall issues is a common task nowadays.
+ The scenario is generally that some network traffic should be flowing
+ but isn't. The causes of problem can range from routing issues to
+ network firewall to host-based firewalls to all sorts of other strange
+ things. It is usually the "middle box" problem that is the hardest to
+ find.
+
+ Suppose there is some host with a TCP service listening that you can't
+ connect to for an unknown reason. If a Nmap -sS scan doesn't show the
+ port as open there are a multitude of possible problems. Maybe the SYN
+ packet never made it because of some firewall in the middle. Maybe the
+ SYN did make it but the SYN+ACK got dropped on it's way back to you.
+ Maybe the TTL expired in transit but the ICMP message got blocked by
+ another firewall before making it back to you. Maybe the SYN made it
+ but some intermediate host forged a reset packet to snipe the connection
+ before the SYN+ACK made it back to you.
+
+ When things like the above are going on it is often the case that even
+ hping can't track down the problem alone. One generally have to turn to
+ Wireshark/tcpdump on one station and hping on the other but sometimes
+ it may be quite difficult to coordinate, specially when the person at
+ the remote host does not even know what an IP address is.
+
+ To solve this problem, Nping will have a mode called "Echo mode" (We are
+ still looking for a better name, suggestions are welcome), that will
+ give it the power of hping + tcpdump.
+
+ Both machines have to be running Nping, one of them in server mode and
+ the other in client mode. The way it works is: the Nping
+ client performs an initial handshake with the server over some
+ standard port (creating a side-channel). Then it notifies the server
+ what packets are about to be sent. The server sets up a liberal BPF
+ filter that captures those packets, and starts listening. When the server
+ receives a packet it encapsulates it (including the link layer frame)
+ into our own protocol packet and sends it back to the nping client.
+ This would be essentially like running tcpdump on the remote machine
+ and having it report back the packets you sent to it with Nping.
+
+ By having the side-channel to talk to the server, things like NAT would
+ become immediately apparent because you'd see your source IP (and
+ sometimes port) change. Things like "packet shapers" that change TCP
+ window sizes transparently between hosts would
+ turn up. It would be easy to tell if the traffic is being dropped in
+ transit and never gets to the box. It would also be easy to tell if
+ the traffic does make it to the box but the reply never makes it back
+ to you.
+
+ In general, it would be like sending a postal package to someone and
+ having them email you a photo of the package when they get it. If you
+ think your packages are being abused by the parcel service then having
+ someone on the other end to send information back is a great way to
+ uncover what is going on.
+
+
+
+2. NPING ECHO PROTOCOL SPECIFICATION
+
+
+ 2.1 General Packet Format
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code | Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . .
+ . DATA .
+ . .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . Checksum .
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ There are 6 different kinds of packets:
+
+ HELLO: (C->S)
+ Informs the server of the highest version we support.
+
+ HELLO RESPONSE: (S->C)
+ Informs the client of the highest version we support.
+
+ SPECS: (C->S):
+ Tells the server what kind of packets we are planning to send.
+
+ READY: (S->C):
+ Tells the client that the server is ready to start receiving
+ packets.
+
+ ECHOPKT: (S->C):
+ Contains the packet that the server receives from the client.
+
+ QUIT: (C->S or S->C):
+ Asks to stop the echo process.
+
+
+
+
+
+
+ 2.2 Field Description
+
+ Version: 8 bits
+ Current version of the protocol. This document covers version 0x01.
+
+
+ Operation Code: 8 bits
+ Indicates the type of packet. It must be one of the operation
+ codes defined in section 2.2.
+
+
+ Total Length: 16 bits
+ Length of the entire packet, measured in 32bit words. Value must
+ be in NETWORK byte order.
+
+
+ Sequence Number: 32 bits
+ Initially each peer generates a random sequence number and then
+ increments it by one in each packet that it sends. It must be
+ in NETWORK byte order. This field is intented to provide some,
+ very basic, protection against replay attacks.
+
+
+ Reserved: 64 bits
+ Reserved for future use. Reserved fields have been added for two
+ reason. To allow future extension of the protocol and to make
+ the header a multiple of 128 bits needed to satisfy AES encryption
+ requirements in block size.
+
+
+ Data: variable length
+ Operation specific data.
+
+
+ Checksum: 256 bits
+ SHA-256 sum of the entire packet. Checksum computation includes
+ the checksum field which must be previously set to zero.
+ This field is intended to provide client authentication. Echo
+ messages are transmitted encrypted (unless Nping is compiled
+ without OpenSSL). When a server receives a packet, it decrypts it
+ using a symmetric key known by both ends. Then it verifies the
+ checksum. If the checksum is correct it assumes the client is
+ an authorized user because only a person who knows the encryption
+ key and is capable of generating packets that when decrypted
+ produce valid sums.
+
+
+
+
+
+
+ 2.3 Operation Codes
+
+ Operation HELLO: 0x01
+ Operation HELLO RESPONSE: 0x02
+ Operation SPECS: 0x03
+ Operation READY: 0x04
+ Operation ECHOPKT: 0x05
+ Operation QUIT: 0x06
+
+
+
+
+
+ 2.4 Operation HELLO
+
+ The HELLO packet is sent by the client and it asks the server
+ to establish a new session. The packet also informs the server
+ of the latest version of the protocol that the client supports.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x01 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved | Reserved | IP version |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 5 +-- --+
+ | |
+ 6 +-- Partner IP address --+
+ | |
+ 7 +-- --+
+ | |
+ 8 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 9 +-- --+
+ | |
+ 10 +-- Reserved --+
+ | |
+ 11 +-- --+
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ IP Version: 8 bits
+ IP version of the following IP address.
+
+
+ Partner IP address: 128 bits
+ This is the server's IP address as seen by the client. This is
+ not very useful but is provided for consistency with the HELLO
+ response packet.
+ This field has 128 bits to allow use of both IPv4 and IPv6
+ addresses. When IPv4 is used, only the first four bytes are used.
+ The rest may be set to zero or filled with random data.
+
+ Reserved: 128 bits
+ Reserved for future use.
+
+
+
+
+ 2.5 Operation HELLO RESPONSE
+
+ The HELLO RESPONSE packet is sent by the server to indicate the client
+ that he is actually a Nping Echo server and to inform about the
+ latest version it supports.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x02 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved | Reserved | IP version |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 5 +-- --+
+ | |
+ 6 +-- Partner IP address --+
+ | |
+ 7 +-- --+
+ | |
+ 8 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ 9 +-- --+
+ | |
+ 10 +-- Reserved --+
+ | |
+ 11 +-- --+
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ 20 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ IP Version: 8 bits
+ IP version of the following IP address.
+
+
+ Partner IP address: 128 bits
+ This is the client's IP address as seen by the server. This
+ lets the client to inmediatly detect the presence of some
+ intermediate device that changes his source IP (e.g a NAT box).
+ This can also be useful in case the client wants to specify
+ its own BPF filter (overriding server's default behaviour)
+ (see section 2.5 for more information).
+ This field has 128 bits to allow use of both IPv4 and IPv6
+ addresses. When IPv4 is used, only the first four bytes are used.
+ The rest may be set to zero or filled with random data.
+
+ Reserved: 128 bits
+ Reserved for future use.
+
+
+ 2.6 Operation SPECS
+
+ The SPECS packet is sent by the client to tell the server what kind
+ of packets it should expect. Additionally, the client may also include
+ a custom BPF filter for the server.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x03 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Protocol | Reserved | Packet Count |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . | |
+ . . .
+ . . BPF filter specification .
+ n . .
+ | |
+ n+1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ n+9 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ Protocol: 8 bits.
+ Specifies which kind of packets will be sent to the server. It
+ must contain one of the following values:
+
+ 0x01 (Protocol TCP)
+ Tells the server to listen to TCP packets coming from
+ the client's IP address.
+
+ 0x02 (Protocol UDP)
+ Tells the server to listen to UDP packets coming from
+ the client's IP address.
+
+ 0x03 (Protocol ICMP)
+ Tells the server to listen to ICMP packets coming from
+ the client's IP address.
+
+ 0x04 (Protocol ARP)
+ Tells the server to listen to ARP packets coming from
+ the client's MAC address (or in most cases, server's
+ gateway MAC address).
+
+ 0xAA (Custom BPF filter included)
+ Tells the server to use a custom BPF filter specified in
+ an additional field.
+
+ 0xFF (Any protocol)
+ Tells the server to listen to any packets coming from
+ the client's IP address.
+
+ Reserved: 8 bits
+ Reserved for future use.
+
+
+ Packet count: 16 bits.
+ Specifies how many packets will be sent. It must be in NETWORK
+ byte order.
+
+
+ BPF filter specification: variable length
+
+ When field "Protocol" contains value 0xAA, an additional
+ field is included in the packet: the BPF filter specification.
+
+ This field contains a BPF filter specification in tcpdump
+ format. This is useful when the client wants to override the
+ server's default BPF filters and capture a different type of
+ traffic.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | BPF Filter Spec Length | .
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ .
+ . .
+ . BFP Filter Spec .
+ . +-+-+-+-+-+-+-+-+
+ | | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The length is measured in bytes and should be in NETWORK byte
+ order. If the length is not a multiple of 16, it must be padded
+ with NULL bytes.
+
+
+ When client specifies an empty filter, meaning capture all
+ packets, the field will look like:
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Length=0 | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ As a security measure, the server may not allow use of
+ custom BPF filters. In that case, a QUIT packet must be
+ sent to the client.
+
+
+
+
+ 2.7 Operation READY
+
+ The READY packet is sent by the server to indicate the client that
+ his SPECS packet was accepted and that everything is ready to start
+ receiving and echoing packets.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x04 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+
+
+ 2.8 Operation ECHOPKT
+
+ The ECHOPKT packet is sent by the server and it contains an echoed
+ packet.
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x05 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DLT Type | Packet Length |
+ 5 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ . . .
+ . . Packet .
+ . . .
+ n . +-+-+-+-+-+-+-+-+
+ | | Padding |
+ n+1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ n+9 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+
+ DLT Type: 16 bits.
+ Specifies the type of link layer device used in the server side.
+ Since the server includes link layer frames in echoed packets,
+ the client needs to know the DLT in order to process link layer
+ header information.
+ Values used in this field must match DLT types defined in libpcap
+ and must be transmitted in NETWORK byte order.
+
+ Packet Length: 16 bits.
+ Specifies the length of the echoed packet measured in bytes.
+ It must be in NETWORK byte order.
+
+ Packet: variable length.
+ This corresponds to the packet being echoed. Server should
+ store the packet exactly as it was received. No byte order
+ conversions or any other alteration should be performed.
+ If the length is not a multiple of 16, it must be padded with
+ NULL bytes.
+
+
+
+ 2.9 Operation QUIT
+
+ The QUIT packet is sent by client or server to tell its peer to
+ terminate the current session.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Version | OP Code 0x06 | Total Length |
+ 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ 4 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ . . .
+ . . SHA256 Checksum .
+ . . .
+ | |
+ 12 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ This packet should be sent:
+ By the client: to tell the server to stop echoing packets and
+ terminate the current session.
+
+ By the server: to tell the client that no custom BPF filter
+ is allowed so the session will be terminated.
+
+
+ 2.10 Flow diagram
+
+
+ The following diagram represents a typical session:
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | HELLO | :: Hi. I'm an Nping Client.
+ |------------------>>| I support version 1.
+ | |
+ | |
+ | HELLO RESPONSE |
+ |<<------------------| :: Nice 2 meet u. Im a server..
+ | | I also support version 1
+ | |
+ | SPECS |
+ |------------------>>| :: I'll be sending 5 ICMP
+ | | Destination Unreachable probes.
+ | |
+ | |
+ | READY |
+ |<<-- ---------------| :: OK, I'm ready for those probes.
+ | |
+ | |
+ | |
+ | |
+ | ECHOPKT |
+ |<<------------------| :: Here's what I received.
+ | |
+ | ECHOPKT |
+ |<<------------------| :: Here's what I received.
+ | |
+ | ECHOPKT |
+ |<<------------------| :: Here's what I received.
+ | . |
+ | . |
+ | . |
+ | ECHOPKT |
+ |<<------------------| :: Here's what I received.
+ | |
+ | |
+ | |
+ | QUIT |
+ |------------------>>| :: It's been a pleasure.
+
+
+
+
+ The following diagram represents a session where the client requests
+ the use of a custom BPF filter but the server is configured not to
+ allow it.
+
+ +------+ +------+
+ |CLIENT| |SERVER|
+ +------+ +------+
+ | |
+ | HELLO | :: Hi. I'm an Nping Client.
+ |------------------>>| I support version 1.
+ | |
+ | |
+ | HELLO RESPONSE |
+ |<<------------------| :: Nice 2 meet u. Im a server..
+ | | I also support version 1
+ | |
+ | SPECS |
+ |------------------>>| :: Use this BPF filter (tcp and udp)
+ | |
+ | |
+ | |
+ | QUIT |
+ |<<-- ---------------| :: Sorry, no custom BPF allowed.
+
+
+ 2.11 Security
+
+ The Nping Echo functionality involves direct access to network traffic
+ on the server side and that can easily involve information leakage
+ problems if no security measures are taken.
+
+ Unless Nping is compiled without OpenSSL support, all Nping Echo
+ Protocol (NEP) packets are transmitted encrypted. Rijndael/AES standard
+ is used. It has a block size of 128 bits, that's why all NEP packets
+ must have a length that is multiple of 16 bytes.
+
+ Every NEP packet includes a SHA-256 checksum. SHA-256 has been chosen
+ over MD5 or SHA1, just to be safe in the future. MD5 is already broken
+ and some studies show important advances in SHA1 attacks.
+
+ As described above, client authentication is performed using the
+ checksum field. The server assumes only a client in possesion of the
+ correct encryption key is capable of producing packets that, when
+ decrypted, contain valid SHA-256 checksum. However, replay attacks
+ may be possible in this scheme. A small 32bit Sequence field is
+ included in every packet. In theory, the server could have a list
+ of sequence numbers that have already been used and deny connection
+ to clients that use replayed packets. However, a 32 bit space may not
+ be sufficiently large to provide security, and exhaustion of sequence
+ numbers may result in a denial of service for authorized clients.
+
+ If we set the "Reserved" field (56 bits) in the initial HELLO packet
+ to some random value, and we instruct the server to keep a list of
+ both, sequence numbers and checksums, then it is possible that the
+ tuple (seq, checksum) provides enough security while significantly
+ reducing the possibility of client denial of service. We can even use
+ (seq, rand, checksum) where "rand" is the random data included in
+ the reserved space.
+
+ The problem with replay attacks is not tremendously important because,
+ at the end of the day, an attacker that does not have the encryption
+ key and therefore cannot see the contents of the ECHOPKT packets.
+ However, if the attacker replays old packets to establish a new
+ connection, the server will send him some data whenever he captures
+ a packet, and the fact the it has actually captured a packet can give
+ the attacker enough information to tell if the server is behind a
+ firewall, etc.
+
+ Security aspects are not yet defined properly. Any comments and
+ suggestions are welcome.
+
+
+
+3. GLOSSARY
+
+4. REFERENCES
+
+ [1]
+
+ [2]
+
+ [3]
+
+ [4]
+
+
+
+
+
+
+
diff --git a/nping/nping-dev/NpingCommandLine.txt b/nping/nping-dev/NpingCommandLine.txt
new file mode 100644
index 0000000..df4175d
--- /dev/null
+++ b/nping/nping-dev/NpingCommandLine.txt
@@ -0,0 +1,151 @@
+++++++++++++++++++++++++++++++++++
+| NPING COMMAND LINE INTERFACE |
+++++++++++++++++++++++++++++++++++
+
+This document presents Nping's command line interface. All option flags are
+now definitive. Howerever, comments and suggestions are still welcome.
+
+
+
+Nping 0.01a ( https://nmap.org/nping )
+Usage: nping [Probe mode] [Options] {target specification}
+
+TARGET SPECIFICATION:
+ Targets may be specified as hostnames, IP addresses, networks, etc.
+ Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254
+ -iL <inputfilename>: Read targets from list of hosts or networks
+PROBE MODES:
+ --tcp-connect : Unprivileged TCP connect probe mode.
+ --tcp : TCP probe mode.
+ --upd : UPD probe mode.
+ --icmp : ICMP probe mode.
+ --arp : ARP Request probe mode.
+ --rarp : RARP Request probe mode.
+ --arp-response : ARP Response probe mode.
+ --rarp-response : RARP Response probe mode.
+ -tr, --traceroute : Traceroute mode (can be used together with TCP/UDP/ICMP
+ pings, but not with ARP ping)
+TCP PROBE MODE:
+ -g, --source-port <portnumber> : Set source port.
+ -p, --dest-port <portnumber> : Set destination port.
+ --seq <seqnumber> : Set sequence number.
+ --flags <flags> : Set TCP flags.
+ --ack <acknumber> : Set ACK number.
+ --win <size> : Set window size.
+ --badsum : Use a random invalid checksum.
+ --mss <size> : Set maximum segment size.
+ --ws <n> : Set window scale.
+ --ts <echo,reply> : Set timestamp (echo and reply fields).
+UDP PROBE MODE:
+ -g, --source-port <portnumber> : Set source port.
+ -p, --dest-port <portnumber> : Set destination port.
+ --badsum : Use a random invalid checksum.
+ICMP PROBE MODE:
+ -I3, --dest-unr : Send "destination unreacheable" messages.
+ -I8, --echo-req : Send "echo request" messages.
+ -I13, --ts-req : Send "timestamp request" messages.
+ -I15, --info-req : Send "Information request" messages.
+ -I17, --netmask-req : Send "Netmask request" messages.
+ --icmp-code <code> : ICMP code.
+ --icmp-id <id> : Sets field "Identifier" in echo messages (16bits).
+ --icmp-seq <n> : Sets field "Sequence number" in echo messages (16 bits).
+ARP/RARP PROBE MODE:
+ --arp-sender-mac <mac> : Set sender MAC address.
+ --arp-sender-ip <ip> : Set sender IP address.
+ --arp-target-mac <mac> : Set target MAC address.
+ --arp-target-ip <ip> : Set target IP address.
+ETHERNET OPTIONS:
+ --dest-mac : Set destination mac address. This disables ARP resolution.
+ --source-mac : Set source MAC address.
+IP OPTIONS:
+ -S, --source-ip : Set source IP address.
+ --dest-ip : Set destination IP address (used as an alternative to
+ {target specification} ).
+ --tos <val> : Set type of service field (8bits).
+ --id <val> : Set identification field (16 bits).
+ --df : Set Don't Fragment flag.
+ --mf : Set More Fragments flag.
+ --ttl <val> : Set time to live [0-256].
+ --badsum-ip : Use a random invalid checksum.
+ --ip-options S|R [route]|L [route]|T|U ... : Set IP options
+ --ip-options hex string : Set IP options
+ --mtu <len> : Set MTU. Packets get fragmented if MTU is small enough.
+ -f : Fragment packets.
+PAYLOAD OPTIONS:
+ --data <hex string> : Include TCP/UPD/ICMP payload (if it makes sense).
+ --data-file <filename> : Get payload from specified file.
+ --data-length <len> : Include len random bytes as payload.
+ECHO CLIENT/SERVER:
+ -K, --ekey <hex> : Key to be used for encryption/decryption.
+ -P, --passphrase : Passphrase to derive an encryption key from.
+ CLIENT-ONLY OPTIONS:
+ --client : Run Nping in client mode.
+ --interpret : Interpret received echoes.
+ SERVER-ONLY OPTIONS:
+ --server : Run Nping in server mode.
+ --echo-link : Return back: link+net+transport+payload
+ --echo-net : Return back: net+transport+payload
+ --echo-trans : Return back: transport+payload
+ --echo-data : Just return payload.
+TIMING AND PERFORMANCE:
+ Options which take <time> are in milliseconds, unless you append 's'
+ (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).
+ --delay <time> : Adjust delay between probes.
+ --rate <num> : Send num packets per second.
+ --host-timeout <time> : Give up on target after this long.
+MISC:
+ -h, --help : Display help information on stardard output.
+ -V, --version : Display Nping current version number.
+ -c, --count <n> : Stop after sending (and receiving) n response packets.
+ -e, --interface <name> : Use supplied network interface.
+ --privileged : Assume that the user is fully privileged.
+ --unprivileged : Assume the user lacks raw socket privileges.
+ --send-eth : Send packets at the raw ethernet layer.
+ --send-ip : Send packets using raw IP sockets.
+OUTPUT:
+ -v : Increment verbosity level by one.
+ -v[level] : Set verbosity level. E.g: -v4
+ -d : Increment debugging level by one.
+ -d[level] : Set debugging level. E.g: -d3
+ --quiet : Sets verbosity and debug level to zero. (Same as -v0 -d0)
+ --debug : Sets verbosity and debug to their highest level.
+EXAMPLES:
+ nping scanme.nmap.org
+ nping --tcp --dest-port 80 --ttl 2 192.168.1.1
+ nping --debug --icmp -I17 --delay 2s microsoft.com
+
+SEE THE MAN PAGE FOR MANY MORE OPTIONS, DESCRIPTIONS, AND EXAMPLES
+
+
+
+
+
+
+
++------------------------------------------------------------------------------+
+
+NOTES:
+
+In places where a port number, an IP address, etc, is expected, it is possible
+to specify the word "rand" or "random", so Nping sets a random value for that
+option.
+
+E.g: nping --tcp --dest-port random 192.168.1.1
+ nping --udp --source-port random --source-mac random 207.46.197.32
+ nping --arp --sender-ip random --ttl random scanme.nmap.org
+
+
+In places where a MAC address is expected, it is possible to especify a MAC
+address, a prefix or a vendor name. Missing information will be completed with
+random values.
+
++------------------------------------------------------------------------------+
+
+
+
+
+
+
+
+
+
diff --git a/nping/nping-dev/NpingExamples.txt b/nping/nping-dev/NpingExamples.txt
new file mode 100644
index 0000000..055db5d
--- /dev/null
+++ b/nping/nping-dev/NpingExamples.txt
@@ -0,0 +1,56 @@
+++++++++++++++++++++++++++
+| NPING USAGE EXAMPLES |
+++++++++++++++++++++++++++
+
+
+# These can be run with no privileges ******************************************
+
+/* Do simple TCP connect()s to one host */
+nping --tcp-connect google.com
+
+/* Do simple TCP connect()s to multiple hosts */
+nping --tcp-connect google.com ask.com yahoo.com bing.com
+
+/* Send an UDP packet with 100 bytes of random data */
+nping --udp google.com -p 53 --data-length 100
+
+/* Try to TCP connect() to a range of ports */
+nping --tcp-connect google.com -p75-85 -c 1
+
+# These require root access ****************************************************
+
+# Send TCP Syn with the ECN flag also set
+sudo nping --tcp google.com --flags syn,ecn -p80,443
+
+# Send UDP packet with a bogus checksum from port 1337
+sudo nping --udp --badsum --source-port 1337 -p 53 google.com -v6
+
+# Send ARP requests to 192.168.1.1
+sudo nping --arp 192.168.1.1
+
+# Send ARP requests to all host in network 192.168.1.0 (inter-probe delay = 100ms)
+sudo nping --arp 192.168.1.0/24 --delay 100
+
+# Send 300 TCP packets at a rate of 100pkts/sec
+sudo nping --tcp google.com --rate 100 -c 300
+
+# Send ICMP echo request wit custom ID and Seq fields
+sudo nping google.com --icmp --icmp-type echo --icmp-id 31337 --icmp-seq 1
+
+# Send ICMP echo reply
+sudo nping google.com --icmp --icmp-type echo-reply
+
+# Send ICMP Parameter problem with custom pointer
+sudo nping google.com --icmp --icmp-type parameter-problem --icmp-param-pointer 9
+
+# Send ICMP Source Quench
+sudo nping google.com --icmp --icmp-type source-quench -v6
+
+# Send ICMP Time Exceeded because time exceeded during reassembly
+sudo nping google.com --icmp --icmp-type te --icmp-code frag-exc -v5
+
+# Send ICMP Router Advertising with 2 entries
+sudo nping google.com --icmp --icmp-type 9 --icmp-advert-entry 1.1.1.1,300 --icmp-advert-entry 33.33.33.33,12345 -v6
+
+
+
diff --git a/nping/nping-dev/NpingRequirements.txt b/nping/nping-dev/NpingRequirements.txt
new file mode 100644
index 0000000..53218f4
--- /dev/null
+++ b/nping/nping-dev/NpingRequirements.txt
@@ -0,0 +1,165 @@
+++++++++++++++++++++++++++++++++
+| NPING PROJECT REQUIREMENTS |
+++++++++++++++++++++++++++++++++
+
+This document presents a list of requirements for the tool Nping that will
+be developed during this summer as a project for the program Google Summer of
+Code.
+
+Each requirement is tagged with one of the following tags:
+
+[MustHave] It definitely must be met.
+[ShouldHave] It should be met if providing there is enough time for it.
+[CouldHave] It would be nice to have but it's not essential.
+[OnRequest] It would be added to the todo-list if someone asks for it on the
+ list, provides a good reason and some usage scenarios.
+
++------------------------+
+| GENERAL |
++------------------------+
+
+* Documentation for end-users.........................................[MustHave] [DONE]
+* Documentation of the source code using Doxygen syntax..............[Couldhave] [DONE]
+* Command line interface with well-defined option flags...............[MustHave] [DONE]
+* 6 levels of verbosity (0 to 5)......................................[MustHave] [DONE]
+* 6 levels of debugging information...................................[MustHave] [DONE]
+* Written in C++......................................................[MustHave] [DONE]
+* Run and be tested under Linux.......................................[MustHave] [DONE]
+* Run and be tested under Windows.....................................[MustHave]
+* Run and be tested under OS X........................................[MustHave]
+* Compile as a single, statically-linked executable..................[CouldHave]
+* Use of libdnet......................................................[MustHave] [DONE]
+* Designed to be integrated into Nmap tarball.........................[MustHave]
+* Design to allow easy extension to other protocols...................[MustHave] [DONE]
+
+
++------------------------+
+| LINK LAYER |
++------------------------+
+* Raw Ethernet frame generation.......................................[MustHave] [DONE]
+ - Destination MAC address...........................................[MustHave] [DONE]
+ - Spoofed source MAC address........................................[MustHave] [DONE]
+ - Custom Ethertype/Length..........................................[OnRequest] [DONE]
+ - Invalid CRC32 checksum...........................................[OnRequest]
+
+* ARP ping............................................................[MustHave] [DONE]
+
+* Custom ARP packet generation
+ - Hardware type....................................................[OnRequest]
+ - Protocol type....................................................[OnRequest]
+ - Hardware length..................................................[OnRequest]
+ - Protocol length .................................................[OnRequest]
+ - Operation .......................................................[OnRequest] [DONE]
+ - Sender hardware address...........................................[MustHave] [DONE]
+ - Sender protocol address...........................................[MustHave] [DONE]
+ - Target hardware address...........................................[MustHave] [DONE]
+ - Target protocol address...........................................[MustHave] [DONE]
+* Custom RARP packet generation......................................[CouldHave] [DONE]
+
++------------------------+
+| NETWORK LAYER |
++------------------------+
+
+* Custom IPv4 packet generation.......................................[MustHave] [DONE]
+ - Custom version number............................................[OnRequest]
+ - Invalid header lengths...........................................[OnRequest]
+ - Type of Service...................................................[MustHave] [DONE]
+ - Invalid total lengths............................................[OnRequest]
+ - Custom Idenfication number........................................[MustHave] [DONE]
+ - Do Not Fragment Flag..............................................[MustHave] [DONE]
+ - More Fragments Flag...............................................[MustHave] [DONE]
+ - Reserved flag....................................................[OnRequest]
+ - Incorrect fragment offset........................................[OnRequest]
+ - Custom TTL........................................................[MustHave] [DONE]
+ - Custom Protocol number...........................................[OnRequest]
+ - Invalid header checksum...........................................[MustHave] [DONE]
+ - Spoofed source address............................................[MustHave] [DONE]
+ - Destination address...............................................[MustHave] [DONE]
+ - IP options........................................................[MustHave] [DONE]
+
+* IPv6 packet generation
+ - IPv6 support for TCP connect() ping...............................[MustHave]
+ - IPv6 support for UDP pings........................................[MustHave]
+ - IPv6 packet generation............................................[MustHave]
+
+* ICMP packet generation..............................................[MustHave] [DONE]
+ - Echo Request......................................................[MustHave] [DONE]
+ - Timestamp request.................................................[MustHave] [DONE]
+ - Information Request...............................................[MustHave] [DONE]
+ - Netmask Request...................................................[MustHave]
+ - Redirect..........................................................[MustHave] [DONE]
+ - Fake Destination Unreachable Message..............................[MustHave] [DONE]
+ - Fake Echo Reply Message..........................................[OnRequest] [DONE]
+ - Fake Source Quench Message.......................................[OnRequest] [DONE]
+ - Fake Time Exceeded message.......................................[OnRequest] [DONE]
+ - Fake Parameter Problem Message...................................[OnRequest] [DONE]
+ - Timestamp reply..................................................[OnRequest] [DONE]
+ - Information Reply................................................[OnRequest] [DONE]
+ - Netmask Reply....................................................[OnRequest]
+
+
+
++------------------------+
+| TRANSPORT LAYER |
++------------------------+
+* Custom TCP packet generation........................................[MustHave] [DONE]
+ - Source port......................................................[MustHave] [DONE]
+ - Destination port.................................................[MustHave] [DONE]
+ - Sequence Number..................................................[MustHave] [DONE]
+ - ACK Number.......................................................[MustHave] [DONE]
+ - Invalid offset values...........................................[OnRequest]
+ - Custom data in "Reserved" field.................................[OnRequest]
+ - TCP Flags (including CWR and ECE)................................[MustHave] [DONE]
+ - Window size......................................................[MustHave] [DONE]
+ - Invalid checksum.................................................[MustHave] [DONE]
+ - Custom Urgent Pointer...........................................[OnRequest]
+ - TCP Options......................................................[MustHave]
+
+* Custom UDP packet generation........................................[MustHave] [DONE]
+ - Source / Dest ports .............................................[MustHave] [DONE]
+ - Incorrect length................................................[OnRequest] [DONE]
+ - Invalid checksum.................................................[MustHave] [DONE]
+
++------------------------+
+| APPLICATION LAYER |
++------------------------+
+* Custom DNS request generation......................................[CouldHave]
+* HTTP request generation............................................[CouldHave]
+
+
++------------------------+
+| Nping ECHO SERVER |
++------------------------+
+* Encrypted communications symmetrict encryption......................[MustHave]
+* Use of covert channels to transfer information back
+ to the nping client................................................[CouldHave]
+* Echo back layers link+net+transport+payload
+* Echo back layers net+transport+payload
+* Echo back layerstransport+payload
+* Echo back only payload
+
+
+
++------------------------+
+| MISCELLANEOUS |
++------------------------+
+* Traceroute mode.....................................................[MustHave] [DONE]
+ - Traceroute to a TCP port..........................................[MustHave] [DONE]
+ - Traceroute to a UDP port..........................................[MustHave] [DONE]
+* Nmap style packet output............................................[MustHave] [DONE]
+* Provide useful stats................................................[MustHave]
+* Save responses in a pcap file......................................[CouldHave]
+* Implement student's t test to compare data-sets of timing
+ information as in QSCAN............................................[CouldHave]
+* Support for multiple target IPs.....................................[MustHave] [DONE]
+* Support for multiple target ports...................................[MustHave] [DONE]
+
+
+
+
+
+
+
+
+
+
diff --git a/nping/nping-dev/PacketDiff_RFC.txt b/nping/nping-dev/PacketDiff_RFC.txt
new file mode 100644
index 0000000..adca767
--- /dev/null
+++ b/nping/nping-dev/PacketDiff_RFC.txt
@@ -0,0 +1,538 @@
+/*****************************************************************************
+ * *
+ * o *
+ * o *
+ * o *
+ * o o *
+ * o o *
+ * o o *
+ * o o o *
+ * o o o *
+ * 888b 888 o o o *
+ * 8888b 888 o o o *
+ * 88888b 888 o o o *
+ * 888Y88b 888 o *
+ * 888 Y88b888 o *
+ * 888 Y88888 *
+ * 888 Y8888 *
+ * 888 Y888 *
+ * *
+ * *
+ * *
+ * --[PACKET DIFF]-- *
+ * --[Survey/Request for Comments.]-- *
+ * *
+ * *
+ * June 2010. *
+ * *
+ * Luis MartinGarcia *
+ * (luis.mgarc@gmail.com) *
+ * *
+ *****************************************************************************/
+
+ S!=R : Sent value differs from received value
+ S>R : Sent value is higher than received value
+ S<R : Sent value is lower than received value
+ S==R : Sent value equals received value
+
+
+ 1. IP VERSION 4
+
+ +=====================+======+================================================
+ | Version | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Header Length | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Type of Service | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Total Length | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Identification | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Don't Fragment Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | More Fragments Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Evil bit Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Fragment Offset | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Time To Live | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Protocol | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Header Checksum | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Source Address | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Destination Address | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | IP Options | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+
+ 2. IP VERSION 6
+
+ +=====================+======+================================================
+ | Version | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Traffic Class | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Flow Label | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Payload Length | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Next Header | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Hop Limit | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Source Address | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Destination Address | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+
+
+ 3. TCP
+
+ +=====================+======+================================================
+ | Source Port | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Destination Port | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Sequence Number | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Ack. Number | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Offset | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Reserved field | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | CWR Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ECN Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | URG Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ACK Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | PSH Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | RST Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | SYN Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | FIN Flag | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Window size | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Checksum | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Urgent Pointer | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | TCP Options | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+ 4. UDP
+
+ +=====================+======+================================================
+ | Source Port | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Destination Port | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Length | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Checksum | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+ 5. ICMPv4
+
+ +=====================+======+================================================
+ | Type | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Code | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Checksum | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+=======================================================
+ | === ADDITIONAL COMMENTS ON SPECIFIC ICMPv4 TYPES ==== |
+ +=====================+=======================================================
+ | Echo |
+ | |
+ | |
+ +=====================+=======================================================
+ | Destination |
+ | Unreachable |
+ | |
+ +=====================+=======================================================
+ | Source Quench |
+ | |
+ | |
+ +=====================+=======================================================
+ | Redirect |
+ | |
+ | |
+ +=====================+=======================================================
+ | Router |
+ | Advertisement |
+ | |
+ +=====================+=======================================================
+ | Router Solicitation |
+ | |
+ | |
+ +=====================+=======================================================
+ | Time Exceeded |
+ | |
+ | |
+ +=====================+=======================================================
+ | Parameter Problem |
+ | |
+ | |
+ +=====================+=======================================================
+ | Timestamp |
+ | |
+ | |
+ +=====================+=======================================================
+ | Information |
+ | |
+ | |
+ +=====================+=======================================================
+ | Address Mask |
+ | |
+ | |
+ +=====================+=======================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+
+ 6. ICMPv6
+
+ +=====================+======+================================================
+ | Type | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Code | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Checksum | S!=R |
+ | +------+------------------------------------------------
+ | | S>R |
+ | +------+------------------------------------------------
+ | | S<R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+=======================================================
+ | === ADDITIONAL COMMENTS ON SPECIFIC ICMPv6 TYPES ==== |
+ +=====================+=======================================================
+ | Destination |
+ | Unreachable |
+ | |
+ +=====================+=======================================================
+ | Packet Too Big |
+ | |
+ | |
+ +=====================+=======================================================
+ | Time Exceeded |
+ | |
+ | |
+ +=====================+=======================================================
+ | Parameter Problem |
+ | |
+ | |
+ +=====================+=======================================================
+ | Echo |
+ | |
+ | |
+ +=====================+=======================================================
+ | Router Solicitation |
+ | |
+ | |
+ +=====================+=======================================================
+ | Router Advertisement|
+ | |
+ | |
+ +=====================+=======================================================
+ | Neighbor |
+ | Solicitation |
+ | |
+ +=====================+=======================================================
+ | Neighbor |
+ | Advertisement |
+ | |
+ +=====================+=======================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
+
+ 6. Ethernet
+
+ +=====================+======+================================================
+ | Destination MAC | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Source MAC | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | Type | S!=R |
+ | +------+------------------------------------------------
+ | | S==R |
+ +=====================+======+================================================
+ | ADDITIONAL COMMENTS |
+ | |
+ | |
+ +=====================+=======================================================
+
+
diff --git a/nping/nping-dev/README b/nping/nping-dev/README
new file mode 100644
index 0000000..179157b
--- /dev/null
+++ b/nping/nping-dev/README
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * *
+ * o *
+ * o *
+ * o *
+ * o o *
+ * o o *
+ * o o *
+ * o o o *
+ * o o o *
+ * 888b 888 o o o *
+ * 8888b 888 o o o *
+ * 888Y88b 888 o o o *
+ * 888Y88b 888 o *
+ * 888 Y88b888 o *
+ * 888 Y88888 *
+ * 888 Y8888 *
+ * 888 Y888 *
+ * *
+ * --[NPING-DEV README FILE]-- *
+ * *
+ *****************************************************************************/
+
+ The nping-dev directory contains some text files and simple scripts
+ which are useful for specific development tasks, such as generating
+ getters and setters for various classes, run Nping's test battery, etc.
+ It also contains some internal development documents that are still in
+ the draft state.
+
+ Altough the contents of the directory may only be useful for a few
+ developers, the files are kept public. However, the files are not
+ intended to be used by end-users and therefore, may contain bugs or
+ inaccurate information.
+
+
+
+
+
+
+
diff --git a/nping/nping-dev/configFiles.txt b/nping/nping-dev/configFiles.txt
new file mode 100644
index 0000000..a5a2b5f
--- /dev/null
+++ b/nping/nping-dev/configFiles.txt
@@ -0,0 +1,12 @@
+These are the configure-related files that need to be distributed with Nping:
+
+configFiles.txt
+config.guess
+config.sub
+configure
+configure.ac
+depcomp
+ltmain.sh
+Makefile.in
+missing
+shtool
diff --git a/nping/nping-dev/do_valgrind.sh b/nping/nping-dev/do_valgrind.sh
new file mode 100755
index 0000000..ef13291
--- /dev/null
+++ b/nping/nping-dev/do_valgrind.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+reset && sudo valgrind --leak-check=full --show-reachable=yes --track-fds=yes --read-var-info=yes --sim-hints=lax-ioctls --track-origins=yes --malloc-fill=aa --suppressions=valgrind_supress.txt -v -v $1 $2 $3 $4 $5 $6 $7 $8 $9
diff --git a/nping/nping-dev/echo_proposal.txt b/nping/nping-dev/echo_proposal.txt
new file mode 100644
index 0000000..336202d
--- /dev/null
+++ b/nping/nping-dev/echo_proposal.txt
@@ -0,0 +1,222 @@
+
+
+ NPING NEW ECHO MODE PROPOSAL
+ June 2010
+
+ Luis MartinGarcia
+ (luis.mgarc@gmail.com)
+
+
+ TABLE OF CONTENTS
+
+ 0x01. Introduction
+ 0x02. Input
+ 0x03. Output
+ 0x04. Results
+ 0x05. Protocol
+
+== 0x01: INTRODUCTION ==
+
+ Troubleshooting routing and firewall issues is a common task nowadays.
+ The scenario is generally that some network traffic should be flowing
+ but isn't. The causes of problem can range from routing issues to
+ network firewall to host-based firewalls to all sorts of other strange
+ things. It is usually the "middle box" problem that is the hardest to
+ find.
+
+ Suppose there is some host with a TCP service listening that you can't
+ connect to for an unknown reason. If a Nmap -sS scan doesn't show the
+ port as open there are a multitude of possible problems. Maybe the SYN
+ packet never made it because of some firewall in the middle. Maybe the
+ SYN did make it but the SYN+ACK got dropped on it's way back to you.
+ Maybe the TTL expired in transit but the ICMP message got blocked by
+ another firewall before making it back to you. Maybe the SYN made it
+ but some intermediate host forged a reset packet to snipe the connection
+ before the SYN+ACK made it back to you.
+
+ When things like the above are going on, it is often the case that one
+ has to turn to Wireshark/tcpdump on one station and Nping on the other.
+ However, this is usually difficult to coordinate, specially when the
+ person at the remote host does not even know what an IP address is.
+
+ To solve this problem, Nping will have a new mode, called "Echo mode"
+ that will give it the power of a combination like hping + tcpdump.
+ This echo mode turns Nping into a client/server application. One station
+ runs Nping in server mode and the other in client mode. The way it works
+ is: the Nping client performs an initial handshake with the server over some
+ standard port (creating a side-channel). Then it notifies the server
+ what packets are about to be sent. The server sets up a liberal BPF
+ filter that captures those packets, and starts listening. When the server
+ receives a packet it encapsulates it into a packet of our own protocol,
+ the Nping Echo Protocol (NEP), and sends it back to the client.
+ This would be essentially like running tcpdump on the remote machine
+ and having it report back the packets you sent to it with Nping.
+
+ By having the side-channel to talk to the server, things like NAT would
+ become immediately apparent because you'd see your source IP (and
+ sometimes port) change. Things like "packet shapers" that change TCP
+ window sizes transparently between hosts would turn up. It would be
+ easy to tell if the traffic is being dropped in transit and never gets
+ to the box. It would also be easy to tell if the traffic does make it
+ to the box but the reply never makes it back to you.
+
+ In general, it would be like sending a postal package to someone and
+ having them email you a photo of the package when they get it. If you
+ think your packages are being abused by the parcel service then having
+ someone on the other end to send information back is a great way to
+ uncover what is going on.
+
+
+
+== 0x02: INPUT ==
+
+ From a user's perpective, this new mode would be set up from the command line.
+ Here's a possible interface:
+
+ SERVER
+ Users may start the server, using the default parameters, running:
+ nping --echo-server "Squemmish Ossifrage"
+
+ where the parameter passed to the --echo-server argument is the passphrase
+ that is used to derive encryption keys.
+
+ Obvioulsy it would be possible to override defaults running something like:
+ nping --echo-server "SquemmishOssifrage" --echo-port 9999 -vvv
+
+ CLIENT
+
+ Users would need to supply "--echo-client <passphrase>" and the usual
+ parameters used in Nping's normal operation mode.
+
+ For example, the next command tells nping to connect to the echo server at
+ echo.insecure.org, and send one TCP-SYN packet to the echo server.
+
+ nping --echo-client "SquemmishOssifrage" --tcp --flags syn --win 0 -c1 echo.insecure.org
+
+== 0x03: OUTPUT ==
+
+ About the output, Nping will print three types of packets: sent packets,
+ received reply packets, and echoed packets received through the side channel.
+ For captured packets, only the fields that differ from the original packet will
+ be displayed. This makes it easier to spot the fields that changed in transit.
+ Here's a sample output.
+
+ SENT (0.0980s) TCP 192.168.1.99:33856 > 74.207.254.18:80 S ttl=64 id=60467 iplen=40 seq=1754993861 win=0
+ CAPT (0.4504s) TCP 10.1.2.158:33856 > 10.0.23.56:80 ttl=53
+ RCVD (0.1000s) TCP 74.207.254.18:80 > 192.168.1.99:33856 SA ttl=128 id=11746 iplen=44 seq=3230736912 win=16384 <mss 1460>
+
+ Output would be more detailed if verbosity mode is incremented. For example,
+ the IP checksum, which is expected to change in virtually all cases (as it is
+ recomputed in transit for every TTL decrement operation), would only be printed
+ when the level of verbosity is higher than the default. Here's another example:
+
+ SENT (0.0760s) TCP [192.168.1.99:33856 > 74.207.254.18:80 S seq=3835079997 ack=0 off=5 res=0 win=0 csum=0x807E urp=0] IP [ver=4 ihl=5 tos=0x00 iplen=40 id=63460 foff=0 ttl=64 proto=6 csum=0x2d6b]
+ CAPT (0.4504s) TCP [10.1.2.158:33856 > 10.0.23.56:80 csum=34fd] [IP ttl=53 csum=f43d]
+ RCVD (0.0850s) TCP [74.207.254.18:80 > 192.168.1.99:18367 SA seq=507544695 ack=3835079998 off=6 res=0 win=16384 csum=0x85F9 urp=0 <mss 1460>] IP [ver=4 ihl=5 tos=0x00 iplen=44 id=17102 foff=0 ttl=128 proto=6 csum=0xa27d]
+
+ Note that the displayed time for the CAPT packet is higher than RCVD's. This is
+ because Nping will hold the RCVD packet information until it gets the echoed
+ packet. The reason for this behaviour is that it may be less confusing for end
+ users to see the differences between the SENT and the CAPT packets if they
+ are printed one after the other. Typically, network stacks will respond to
+ SENT packets before the Nping Server has time to capture them, encapsulate them
+ in a Nping Echo Protocol message and send them back to the client, so in order
+ to display SENT and CAPT packets together, the RCVD output needs to be delayed
+ for a bit.
+
+== 0x04: RESULTS ==
+
+ Apart from displaying the packets that were sent and the ones that were
+ captured, Nping should, if possible, give hints about what may have happened
+ in transit. For example, if the original source address does not match the
+ source address of the received packet, Nping could inform that with high
+ probability there is a NAT device close to the client. Nping could detect
+ things like variation of TCP window size and warn about possible transparent
+ proxies, etc.
+
+ Starting Nping 0.5.30BETA1 ( https://nmap.org/nping ) at 2010-06-30 17:20 CEST
+
+ SENT (0.0980s) TCP 192.168.1.99:33856 > 74.207.254.18:80 S ttl=64 id=60467 iplen=40 seq=1754993861 win=0
+ CAPT (0.4504s) TCP 10.1.2.158:33856 > 10.0.23.56:80 ttl=53
+ RCVD (0.1000s) TCP 74.207.254.18:80 > 192.168.1.99:33856 SA ttl=128 id=11746 iplen=44 seq=3230736912 win=16384 <mss 1460>
+
+ Packet Echo Analysis:
+ |_Source IP and Destination IP differ: possible NAT device on both ends.
+ |_TTL values differ by 11 units. Network distance between both hosts: 11 hops.
+
+ Max rtt: 8.509ms | Min rtt: 8.509ms | Avg rtt: 8.509ms
+ Raw packets sent: 1 (40B) | Rcvd: 1 (46B) | Lost: 0 (0.00%)
+ Echoed packets recv: 1 (40B) | Lost: 0 (0.00%)
+ Tx time: 0.00020s | Tx bytes/s: 202020.20 | Tx pkts/s: 5050.51
+ Rx time: 0.99984s | Rx bytes/s: 46.01 | Rx pkts/s: 1.00
+ Nping done: 1 IP address pinged in 1.08 seconds
+
+
+
+== 0x05: PROTOCOL ==
+
+ The side channel will be run over a custom application layer protocol called
+ NEP, Nping Echo Protocol. The protocol itself is described in a separate
+ document: "Nping Echo Protocol Specification", available from:
+ <https://nmap.org/svn/nping/nping-dev/EchoProtoRFC.txt>
+
+ The following flow diagram describes a typical client/server interaction.
+ Please refer to the document cited above for more information.
+
+
+ C S
+ | |
+ | TCP Handshake |
+Establish regular TCP |------------------------->|
+connection |<-------------------------|
+ |------------------------->|
+ | |
+ | |
+ | |
+Check that both | |
+understand each other | NEP Handshake and Auth |
+and authenticate the |<------------------------>|
+client |<------------------------>|
+ |<------------------------>|
+ | |
+ | |
+ | |
+Client tells the server | PacketType={IP/TCP/Syn} |
+which kind of packet is |------------------------->|
+going so send | | S
+ | | | /* Server starts */
+ | | | /* capturing packets*/
+ | ServerReadyToGo | | /* here. */
+Server indicates its |<-------------------------| |
+sniffing engine is | | |
+readty to capture the | C | |
+packet | | | |
+ | | | |
+ | | | |
+ | | | |
+Client sends the pkt | | IP/TCP/Syn Packet | |
+via raw sockets | |---------------------------->|
+ | | | | /* Server receives */
+ | | | /* the packet */
+ | Echo of the packet |....|
+Server echoes the |<-------------------------|
+packet via the NEP | |
+session they have. | . |
+ | . |
+ | . |
+ | More raw pkt/echo |
+ | exchanges |
+ | . |
+ | . |
+ | . |
+ | |
+ | |
+ | TCP Connection Close |
+TCP connection closed |<------------------------>|
+ | |
+
+
+
+
+
+
diff --git a/nping/nping-dev/nping_logo.svg b/nping/nping-dev/nping_logo.svg
new file mode 100644
index 0000000..6a09239
--- /dev/null
+++ b/nping/nping-dev/nping_logo.svg
@@ -0,0 +1,483 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="nping_logo.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="6.1230318e-14 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective2447"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.98994949"
+ inkscape:cx="309.48108"
+ inkscape:cy="704.77458"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1280"
+ inkscape:window-height="725"
+ inkscape:window-x="0"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#bd0606;stroke-width:4.31242752;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3428"
+ width="701.0907"
+ height="763.94788"
+ x="23.740343"
+ y="17.531111"
+ ry="59.213264"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Big Fish Ensemble;-inkscape-font-specification:Big Fish Ensemble"
+ x="66.428574"
+ y="815.57648"
+ id="text3583"><tspan
+ sodipodi:role="line"
+ x="66.428574"
+ y="815.57648"
+ id="tspan3587" /></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Big Fish Ensemble;-inkscape-font-specification:Big Fish Ensemble"
+ x="-76.071426"
+ y="798.79077"
+ id="text3617"><tspan
+ sodipodi:role="line"
+ id="tspan3619" /></text>
+ <path
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.97787613"
+ d="M 346.11767,231.61256 L 315.76057,509.6483 L 321.65347,509.8268 L 347.18917,257.68398 L 390.93917,507.3268 L 402.36767,508.2197 L 346.11767,231.61256 z"
+ id="path3696"
+ sodipodi:nodetypes="ccccccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.57605267;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 355.37617,284.13987 L 340.16287,300.78167 L 355.37617,284.13987 z"
+ id="path3698"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 356.92127,298.39827 L 341.02847,315.89827 L 356.92127,298.39827 z"
+ id="path3700"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.48236418;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 358.89617,314.59302 L 337.93747,336.6678 L 358.89617,314.59302 z"
+ id="path3702"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.5564518;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 341.67097,282.88006 L 356.63587,299.54146 L 341.67097,282.88006 z"
+ id="path3704"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 340.67127,298.04112 L 356.56417,315.54112 L 340.67127,298.04112 z"
+ id="path3706"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3.48010445;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 339.94527,317.06957 L 362.46877,337.58411 L 339.94527,317.06957 z"
+ id="path3708"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.55294704;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 362.84747,336.64616 L 335.10227,365.15036 L 362.84747,336.64616 z"
+ id="path3710"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4.82523584;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 337.38127,339.10373 L 368.06847,368.04993 L 337.38127,339.10373 z"
+ id="path3712"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6.27009726;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 368.06037,367.32617 L 329.53227,406.25607 L 368.06037,367.32617 z"
+ id="path3714"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:6.86690807;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 333.22347,368.33887 L 376.15477,410.24338 L 333.22347,368.33887 z"
+ id="path3716"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:8.38511753;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 375.39567,413.38368 L 323.44687,465.01999 L 375.39567,413.38368 z"
+ id="path3718"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:9.15460873;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 328.36287,414.23719 L 389.76537,466.30936 L 328.36287,414.23719 z"
+ id="path3720"
+ sodipodi:nodetypes="ccc"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g3722"
+ inkscape:transform-center-x="-46.938085"
+ inkscape:transform-center-y="5.8727482"
+ transform="matrix(-0.9561303,-0.2929416,-0.2929416,0.9561303,609.30357,9.976981)"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ inkscape:transform-center-y="-10.657344"
+ inkscape:transform-center-x="52.212657"
+ transform="matrix(-0.981146,-0.1420945,-0.1644879,1.1357697,394.1361,-27.319471)"
+ d="M 213.86119,236.41686 C 243.98514,254.69207 253.88789,295.14233 235.61268,325.26628 C 234.16521,327.65221 232.56317,329.94427 230.81985,332.12341"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-1.901365"
+ sodipodi:radius="64.68132"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="291.71732"
+ sodipodi:cx="180.31223"
+ id="path3724"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ <path
+ inkscape:transform-center-y="-7.6342974"
+ inkscape:transform-center-x="36.87777"
+ transform="matrix(-0.9887583,-3.005889e-2,-3.5626382e-2,1.1718956,358.05093,-58.695365)"
+ d="M 192.99402,260.01576 C 210.26289,266.92395 218.92197,287.13025 212.01378,304.39911 C 211.46662,305.76687 210.83085,307.09913 210.11173,308.38483"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-2.066134"
+ sodipodi:radius="34.144054"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="291.71732"
+ sodipodi:cx="180.31223"
+ id="path3726"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ <path
+ inkscape:transform-center-y="-5.3503359"
+ inkscape:transform-center-x="27.550509"
+ transform="matrix(-0.9733676,-5.6158863e-2,-7.2823914e-2,1.2622128,362.79644,-82.402223)"
+ d="M 184.75363,279.85956 C 191.76321,282.55406 195.36959,290.66437 192.67508,297.67395 C 192.46167,298.22913 192.21228,298.77047 191.92899,299.29347"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-2.0796833"
+ sodipodi:radius="13.785899"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="292.72748"
+ sodipodi:cx="179.80716"
+ id="path3728"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ </g>
+ <g
+ id="g3730"
+ inkscape:transform-center-x="46.938085"
+ inkscape:transform-center-y="5.8727482"
+ transform="matrix(0.9561303,-0.2929416,0.2929416,0.9561303,83.38406,9.774501)"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ inkscape:transform-center-y="-10.657344"
+ inkscape:transform-center-x="52.212657"
+ transform="matrix(-0.981146,-0.1420945,-0.1644879,1.1357697,394.1361,-27.319471)"
+ d="M 213.86119,236.41686 C 243.98514,254.69207 253.88789,295.14233 235.61268,325.26628 C 234.16521,327.65221 232.56317,329.94427 230.81985,332.12341"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-1.901365"
+ sodipodi:radius="64.68132"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="291.71732"
+ sodipodi:cx="180.31223"
+ id="path3732"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ <path
+ inkscape:transform-center-y="-7.6342974"
+ inkscape:transform-center-x="36.87777"
+ transform="matrix(-0.9887583,-3.005889e-2,-3.5626382e-2,1.1718956,358.05093,-58.695365)"
+ d="M 192.99402,260.01576 C 210.26289,266.92395 218.92197,287.13025 212.01378,304.39911 C 211.46662,305.76687 210.83085,307.09913 210.11173,308.38483"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-2.066134"
+ sodipodi:radius="34.144054"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="291.71732"
+ sodipodi:cx="180.31223"
+ id="path3734"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ <path
+ inkscape:transform-center-y="-5.3503359"
+ inkscape:transform-center-x="27.550509"
+ transform="matrix(-0.9733676,-5.6158863e-2,-7.2823914e-2,1.2622128,362.79644,-82.402223)"
+ d="M 184.75363,279.85956 C 191.76321,282.55406 195.36959,290.66437 192.67508,297.67395 C 192.46167,298.22913 192.21228,298.77047 191.92899,299.29347"
+ sodipodi:t0="0.34"
+ sodipodi:argument="-2.0796833"
+ sodipodi:radius="13.785899"
+ sodipodi:revolution="0.41"
+ sodipodi:expansion="0"
+ sodipodi:cy="292.72748"
+ sodipodi:cx="179.80716"
+ id="path3736"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="spiral" />
+ </g>
+ <path
+ sodipodi:type="arc"
+ style="fill:none;fill-opacity:1;stroke:#000808;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path3738"
+ sodipodi:cx="-330"
+ sodipodi:cy="843.79077"
+ sodipodi:rx="121.42857"
+ sodipodi:ry="117.14286"
+ d="M -208.57143,843.79077 A 121.42857,117.14286 0 1 1 -451.42857,843.79077 A 121.42857,117.14286 0 1 1 -208.57143,843.79077 z"
+ transform="matrix(1.6069176,0,0,0.988878,909.44047,-210.22791)"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 351.55507,229.46136 L 338.29607,214.99708 L 338.29607,231.91672 L 336.68897,231.60422 L 336.71127,233.99261 L 341.86757,234.05958 L 341.95687,232.58636 L 341.15327,232.40779 L 341.10857,220.26493 L 353.51937,234.05958 L 352.98357,217.40779 L 355.92878,216.96137 L 355.73165,214.37208 L 348.29607,215.66672 L 348.85037,217.99066 C 348.85037,217.99066 348.86657,217.99805 351.31717,217.78277"
+ id="path3742"
+ sodipodi:nodetypes="cccccccccccccccs"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3740"
+ width="474.47919"
+ height="214.71881"
+ x="14.132828"
+ y="597.36389"
+ ry="57.3451"
+ transform="matrix(0.9806229,-0.1959049,0.1476958,0.9890328,0,0)"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g3744"
+ transform="matrix(1.5381724,0,0,1.5381724,232.78947,-668.58165)"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ sodipodi:nodetypes="cccccccccccccccs"
+ id="path3746"
+ d="M 41.696422,795.64342 L 28.437492,781.17914 L 28.437492,798.09878 L 26.830352,797.78628 L 26.852672,800.17467 L 32.008922,800.24164 L 32.098212,798.76842 L 31.294632,798.58985 L 31.249992,786.44699 L 43.660712,800.24164 L 43.124992,783.58985 L 45.312502,783.14343 L 45.178562,780.55414 L 38.437492,781.84878 L 38.991702,784.17272 C 38.991702,784.17272 39.007962,784.18011 41.458542,783.96483"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(0.882353,0,0,1,-9.9504214,-11.800104)"
+ id="g3748">
+ <path
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 66.562501,792.76396 L 67.767857,810.13004 L 66.473215,810.08539 L 66.607143,812.04968 L 71.25,812.11665 L 71.22768,810.26397 L 70.089286,810.21932 L 69.866072,804.72825 L 73.794643,804.46039 L 75.825894,804.3153 L 76.796876,804.2037 L 77.723215,804.11441 L 78.214286,804.02513 L 78.917411,803.76843 L 80.223215,803.16575 L 81.517856,802.40682 L 82.142856,801.69254 L 82.767856,800.75504 L 83.169646,799.59432 L 83.124996,798.07646 L 82.901786,796.96039 L 82.142856,795.26396 L 80.892858,794.19254 L 79.241072,793.29968 L 77.589286,792.76396 L 75.758929,792.49611 L 73.794643,792.49611 L 72.544643,792.45146 L 71.026786,792.49611 L 66.562501,792.76396 z"
+ id="path3750"
+ sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
+ <path
+ style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 69.330357,795.30861 L 73.705357,794.99611 L 75.535714,794.95147 L 77.5,795.21933 L 78.919197,796.31022 L 79.583214,797.44935 L 79.705893,798.75838 L 79.346875,799.55328 L 78.72,800.57288 L 77.8125,801.29076 L 76.116071,801.51397 L 73.526786,801.60326 L 69.642857,801.78183 L 69.330357,795.30861 z"
+ id="path3752"
+ sodipodi:nodetypes="cccccccccccccc" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path3754"
+ d="M 68.683323,799.0736 L 67.507483,799.19386 L 67.768153,800.89279 L 72.076183,800.85931 L 72.145118,798.79756 L 70.600583,798.93061 L 71.183323,782.51109 L 72.388683,782.44413 L 71.942253,780.63609 L 67.321713,780.56913 L 66.897613,782.82359 L 68.326183,782.77895 L 68.683323,799.0736 z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cccccccccccccccccs"
+ id="path3758"
+ d="M 92.554618,794.98964 L 81.104488,782.18203 L 78.938545,782.1325 L 78.938545,799.27535 L 77.487655,799.59902 L 77.353725,801.12803 L 82.777832,801.15036 L 82.911765,798.73964 L 81.751042,798.91821 L 81.751045,787.40035 L 93.418412,801.00958 L 94.715875,801.0103 L 93.543954,784.27642 L 95.628852,784.36358 L 95.80275,781.5075 L 89.410565,781.07825 L 89.492755,783.71002 L 91.856983,783.97416"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ sodipodi:nodetypes="cccccccccczzzzzzzzscszzzssszcszzcczzzzzzzzzzzzzzzzzszzzcccc"
+ id="path3760"
+ d="M 109.94156,796.60971 L 109.7679,791.89014 L 118.78032,791.83961 L 120.04309,808.41587 L 121.14794,808.52636 L 121.14794,810.42039 L 115.81307,810.43618 L 116.06561,808.02128 L 117.56505,808.1949 L 117.01263,801.84988 C 117.01263,801.84988 115.78041,802.67864 115.24486,802.92317 C 114.70931,803.1677 114.08364,803.34419 113.47709,803.49138 C 112.87054,803.63857 111.85266,803.83684 111.20425,803.87018 C 110.55584,803.90352 109.8241,803.8627 109.18395,803.74392 C 108.5438,803.62514 107.5526,803.3035 106.97424,803.04944 C 106.39588,802.79538 105.84662,802.44159 105.33274,802.10242 C 104.81886,801.76325 104.0978,801.23029 103.56497,800.77659 C 103.03214,800.32289 102.22976,799.58078 101.7972,799.07196 C 101.36464,798.56314 100.96719,798.0373 100.66078,797.43046 C 100.35437,796.82362 100.04677,795.70459 99.840035,795.03135 C 99.633295,794.3581 99.396225,793.68857 99.271825,792.94791 C 99.147425,792.20725 99.079075,790.91383 99.082425,790.10686 C 99.085775,789.29989 99.122415,788.35436 99.271825,787.58147 C 99.421235,786.80858 99.766165,785.71662 100.09257,784.99296 C 100.41898,784.2693 100.92016,783.37799 101.4184,782.78325 C 101.91664,782.18851 102.6756,781.57077 103.37557,781.07862 C 104.07554,780.58647 105.29033,779.85835 106.09035,779.56339 C 106.89037,779.26843 107.8416,779.10651 108.61573,779.05831 C 109.38986,779.01011 110.46171,779.11183 111.20425,779.24772 C 111.94678,779.38362 112.90468,779.58082 113.54023,779.9422 C 124.96145,786.43644 115.02042,780.749 115.56053,781.14175 C 116.10064,781.5345 116.70163,782.07457 117.1389,782.53071 C 117.57617,782.98685 118.46472,784.17221 118.46472,784.17221 L 116.82322,787.20267 C 116.82322,787.20267 115.556,785.7581 115.05546,785.30863 C 114.55492,784.85916 114.04431,784.46922 113.54023,784.17221 C 113.03615,783.8752 112.41456,783.53532 111.70933,783.35146 C 111.0041,783.1676 109.55538,783.06644 108.86827,783.09892 C 108.18116,783.1314 107.79169,783.20411 107.16364,783.4146 C 106.53559,783.62509 105.38712,784.1483 104.76453,784.61415 C 104.14194,785.08 103.4247,785.86973 103.0599,786.44505 C 102.6951,787.02037 102.4824,787.75947 102.30228,788.33909 C 102.12216,788.91871 101.90071,789.68282 101.86034,790.29626 C 101.81997,790.9097 101.97887,791.85894 102.04974,792.3797 C 102.12061,792.90046 102.12422,793.29185 102.30228,793.76866 C 102.48034,794.24547 102.97903,794.999 103.31243,795.47329 C 103.64583,795.94758 104.05198,796.43669 104.51199,796.92539 C 104.972,797.41409 105.84992,798.35822 106.40603,798.69315 C 106.96214,799.02808 107.45111,799.10263 108.04752,799.26136 C 108.64393,799.42009 109.75134,799.67678 110.3835,799.70331 C 111.01566,799.72984 111.65367,799.617 112.2144,799.5139 C 112.77513,799.4108 113.57786,799.26241 114.10844,799.00883 C 114.65875,798.74582 115.39793,798.13499 115.74994,797.80927 C 116.10195,797.48355 116.38065,797.24181 116.50755,796.92539 C 116.63445,796.60897 116.56738,796.15504 116.5676,795.81837 C 116.56782,795.4817 116.38441,793.32963 116.38441,793.32963 L 112.18596,793.28857 L 112.34067,796.64128 L 109.94156,796.60971 z"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+ </g>
+ <flowRoot
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial"
+ id="flowRoot2535"
+ xml:space="preserve"
+ transform="translate(411.42857,34.285714)"><flowRegion
+ id="flowRegion2537"><rect
+ y="866.49414"
+ x="137.38075"
+ height="133.34013"
+ width="484.87323"
+ id="rect2539" /></flowRegion><flowPara
+ id="flowPara2541" /></flowRoot> <text
+ id="text2587"
+ y="824.88239"
+ x="116.97203"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial"
+ xml:space="preserve"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"><tspan
+ y="824.88239"
+ x="116.97203"
+ id="tspan2589"
+ sodipodi:role="line"><tspan
+ id="tspan2591"
+ y="824.88239"
+ x="116.97203">Logo designed by Luis MartinGarcia.</tspan><tspan
+ id="tspan2593"
+ y="824.88239"
+ x="442.90955"
+ dx="0" /></tspan><tspan
+ y="849.88239"
+ x="116.97203"
+ id="tspan2595"
+ sodipodi:role="line"><tspan
+ id="tspan2597"
+ y="849.88239"
+ x="116.97203" /></tspan><tspan
+ y="874.88239"
+ x="116.97203"
+ id="tspan2599"
+ sodipodi:role="line"><tspan
+ id="tspan2601"
+ y="874.88239"
+ x="116.97203">Copyright Luis MartinGarcia and Gordon Fyodor, 2009.</tspan><tspan
+ id="tspan2603"
+ y="874.88239"
+ x="604.19861"
+ dx="0" /></tspan><tspan
+ y="899.88239"
+ x="116.97203"
+ id="tspan2605"
+ sodipodi:role="line"><tspan
+ id="tspan2607"
+ y="899.88239"
+ x="116.97203" /></tspan><tspan
+ y="924.88239"
+ x="116.97203"
+ id="tspan2609"
+ sodipodi:role="line"><tspan
+ id="tspan2611"
+ y="924.88239"
+ x="116.97203">For licensing information please write to </tspan><tspan
+ id="tspan2613"
+ y="924.88239"
+ x="475.13611"
+ dx="0" /></tspan><tspan
+ y="949.88239"
+ x="116.97203"
+ id="tspan2615"
+ sodipodi:role="line"><tspan
+ id="tspan2617"
+ y="949.88239"
+ x="116.97203">fyodor@insecure.org or luis.mgarc@gmail.com</tspan></tspan></text>
+ <rect
+ style="opacity:1;fill:#ffffff;fill-opacity:0;stroke:#bd0606;stroke-width:2.54599999999999982;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect3831"
+ width="485.96863"
+ height="524.54004"
+ x="108.44424"
+ y="103.66357"
+ ry="41.855164"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <g
+ id="g3634"
+ transform="matrix(0.6,0,0,0.6,-168,138.65915)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <g
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="/home/default/Desktop/g3762.png"
+ transform="matrix(1.5381724,0,0,1.5381724,-561.49622,-806.66689)"
+ id="g3582" />
+ </g>
+ </g>
+</svg>
diff --git a/nping/nping-dev/packetDiagram.png b/nping/nping-dev/packetDiagram.png
new file mode 100644
index 0000000..45d1dd5
--- /dev/null
+++ b/nping/nping-dev/packetDiagram.png
Binary files differ
diff --git a/nping/nping-dev/pythonscripts/TemplateGettersSetters.txt b/nping/nping-dev/pythonscripts/TemplateGettersSetters.txt
new file mode 100644
index 0000000..fca7d91
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/TemplateGettersSetters.txt
@@ -0,0 +1,25 @@
+
+/* Prototypes */
+int setMETHNAME(TYPE val);
+TYPE getMETHNAME();
+
+/** Sets METHNAME.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int CLASSNAME::setMETHNAME(TYPE val){
+
+ this->ATTRNAME=val;
+
+ return OP_SUCCESS;
+
+} /* End of setMETHNAME() */
+
+
+/** Returns value of attribute ATTRNAME */
+TYPE CLASSNAME::getMETHNAME(){
+
+ return this->ATTRNAME;
+
+} /* End of getMETHNAME() */
+
+
+
diff --git a/nping/nping-dev/pythonscripts/TemplateNpingOps.txt b/nping/nping-dev/pythonscripts/TemplateNpingOps.txt
new file mode 100755
index 0000000..31adf3e
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/TemplateNpingOps.txt
@@ -0,0 +1,45 @@
+
+Prototypes for NpingOps:
+
+ int setMETHNAME(TYPE val);
+ TYPE getMETHNAME();
+ bool issetMETHNAME();
+
+Attributes for NpingOps:
+
+ TYPE ATTRNAME;
+ bool ATTRNAME_set;
+
+Initialization for NpingOps::NpingOps()
+
+ ATTRNAME=0;
+ ATTRNAME_set=false;
+
+
+/** Sets METHNAME.
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error. */
+int NpingOps::setMETHNAME(TYPE val){
+
+ 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() */
+
diff --git a/nping/nping-dev/pythonscripts/addGettersSetters.py b/nping/nping-dev/pythonscripts/addGettersSetters.py
new file mode 100644
index 0000000..b579471
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/addGettersSetters.py
@@ -0,0 +1,28 @@
+
+
+
+o = open("OutputGettersSetters.txt","a")
+
+classname = raw_input("Class Name: ")
+my_range = raw_input("Number of attrs: ")
+methname= []
+attrname = []
+attrtype= []
+
+for i in range( int(my_range) ):
+ methname.append( raw_input("Method Name:") )
+ attrname.append ( raw_input("Attr Name: ") )
+ attrtype.append(raw_input("Attr type:") )
+
+ for line in open("TemplateGettersSetters.txt"):
+ line = line.replace("METHNAME",methname[i])
+ line = line.replace("TYPE",attrtype[i])
+ line = line.replace("ATTRNAME",attrname[i])
+ line = line.replace("CLASSNAME",classname)
+ o.write(line)
+
+
+o.close()
+
+
+
diff --git a/nping/nping-dev/pythonscripts/addManSectionEntry.py b/nping/nping-dev/pythonscripts/addManSectionEntry.py
new file mode 100755
index 0000000..1d6c1e0
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/addManSectionEntry.py
@@ -0,0 +1,43 @@
+
+sectionname = raw_input("Section name: ")
+hyphname = raw_input("Hyphened name: ")
+
+
+o = open("OutputMan.txt","a")
+for line in open("man-section-template.xml"):
+ line = line.replace("SECTION_NAME",sectionname)
+ line = line.replace("SECTION_HYPHENED_NAME",hyphname)
+ o.write(line)
+
+
+my_range = raw_input("Number of options: ")
+optformat = []
+optarg= []
+optdesc= []
+optname= []
+
+for i in range( int(my_range) ):
+ optformat.append( raw_input("Option format (--tcp-connect): --") )
+ optarg.append ( raw_input("Option arg (portnumber): ") )
+ optdesc.append(raw_input("Option Description (TCP Connect Mode):") )
+ optname.append(raw_input("Option name (tcp connect): ") )
+
+
+ for line in open("man-section-entry-template.xml"):
+ line = line.replace("OPT_FORMAT",optformat[i])
+ if( optarg[i] == ""):
+ line = line.replace("OPT_ARG","")
+ else:
+ line = line.replace("OPT_ARG","<replaceable>"+optarg[i]+"</replaceable>")
+ line = line.replace("OPT_DESC",optdesc[i])
+ line = line.replace("OPT_NAME",optname[i])
+ o.write(line)
+
+line1=" </variablelist>"
+line2=" </refsect1>"
+o.write(line1);
+o.write(line2);
+o.close()
+
+
+
diff --git a/nping/nping-dev/pythonscripts/addNpingOpsAttr.py b/nping/nping-dev/pythonscripts/addNpingOpsAttr.py
new file mode 100755
index 0000000..5ed16d6
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/addNpingOpsAttr.py
@@ -0,0 +1,12 @@
+methname = raw_input("Method name: ")
+attrname = raw_input("Attr name: ")
+attrtype = raw_input("Attr type: ")
+
+
+o = open("Output.txt","a")
+for line in open("TemplateNpingOps.txt"):
+ line = line.replace("ATTRNAME",attrname)
+ line = line.replace("METHNAME",methname)
+ line = line.replace("TYPE",attrtype)
+ o.write(line)
+o.close()
diff --git a/nping/nping-dev/pythonscripts/man-section-entry-template.xml b/nping/nping-dev/pythonscripts/man-section-entry-template.xml
new file mode 100644
index 0000000..e61a3f0
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/man-section-entry-template.xml
@@ -0,0 +1,25 @@
+ <varlistentry>
+ <term>
+ <option>--OPT_FORMAT OPT_ARG</option> (OPT_DESC)
+ <indexterm significance="preferred"><primary><option>--OPT_FORMAT</option></primary></indexterm>
+ <indexterm significance="normal"><primary>OPT_NAME</primary></indexterm>
+ </term>
+ <listitem>
+
+
+<para> blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah.</para>
+
+ </listitem>
+ </varlistentry>
diff --git a/nping/nping-dev/pythonscripts/man-section-template.xml b/nping/nping-dev/pythonscripts/man-section-template.xml
new file mode 100644
index 0000000..ab41467
--- /dev/null
+++ b/nping/nping-dev/pythonscripts/man-section-template.xml
@@ -0,0 +1,34 @@
+
+ <refsect1 id="man-SECTION_HYPHENED_NAME">
+ <title>SECTION_NAME</title>
+
+<para> blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah.</para>
+
+<para> blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah
+ blah blah blah blah blah blah blah blah blah blah blah blah.</para>
+
+ <variablelist>
+
diff --git a/nping/nping-dev/test/caps/tcpconnect_T1.cap b/nping/nping-dev/test/caps/tcpconnect_T1.cap
new file mode 100644
index 0000000..1b7c3e4
--- /dev/null
+++ b/nping/nping-dev/test/caps/tcpconnect_T1.cap
Binary files differ
diff --git a/nping/nping-dev/test/caps/tcpconnect_T2.cap b/nping/nping-dev/test/caps/tcpconnect_T2.cap
new file mode 100644
index 0000000..83eba17
--- /dev/null
+++ b/nping/nping-dev/test/caps/tcpconnect_T2.cap
Binary files differ
diff --git a/nping/nping-dev/test/caps/tcpconnect_T3.cap b/nping/nping-dev/test/caps/tcpconnect_T3.cap
new file mode 100644
index 0000000..7e0a628
--- /dev/null
+++ b/nping/nping-dev/test/caps/tcpconnect_T3.cap
Binary files differ
diff --git a/nping/nping-dev/test/test_nping.sh b/nping/nping-dev/test/test_nping.sh
new file mode 100755
index 0000000..45eac56
--- /dev/null
+++ b/nping/nping-dev/test/test_nping.sh
@@ -0,0 +1,1526 @@
+#/*****************************************************************************
+# * *
+# * o *
+# * o *
+# * o *
+# * o o *
+# * o o *
+# * o o *
+# * o o o *
+# * o o o *
+# * 888b 888 o o o *
+# * 8888b 888 o o o *
+# * 88888b 888 o o o *
+# * 888Y88b 888 o *
+# * 888 Y88b888 o *
+# * 888 Y88888 *
+# * 888 Y8888 *
+# * 888 Y888 *
+# * *
+# * --[NPING TEST SPECIFICATION]-- *
+# * *
+# *****************************************************************************/
+
+
+# This document aims to list every Nping option and option syntax, with
+# the purpose of faciliatating testing whether they all work as expected.
+
+######################################
+# RUN-TIME PARAMETER CONFIGURATION #
+######################################
+
+# Target host specification. Can be just one host or varios hosts
+# separated by whitespace
+TARGETS="scanme.nmap.org"
+
+# Global options to be passed to EVERY nping invokation. This is useful
+# to specify things like verbosity level, etc.
+GLOBALOPTS="-vvv -d1"
+
+# Port numbers required by some executions.
+OPEN_PORT="80"
+CLOSED_PORT="31337"
+FILTERED_PORT="82"
+
+# This var should be set to the name of a network interface that
+# exists on the testing system.
+EXISTING_NET_IFACE="eth0"
+
+# Internal test state variables
+CURRENT_TEST=""
+FAILED_TESTS=""
+PASSED_TESTS=""
+TOTAL_TESTS_RUN=0
+TOTAL_TESTS_PASSED=0
+TOTAL_TESTS_FAILED=0
+START_TIME=`date +"%s"`
+END_TIME=0
+ELAPSED_TIME=0
+
+
+# Ask the user whether the test was passed or failed
+request_userinput_test_status() {
+ echo -n "[+] Was the test successful? [Y/N] "
+ read TESTRESPONSE
+ # Increment total counter
+ TOTAL_TESTS_RUN=`expr $TOTAL_TESTS_RUN + 1`
+
+ if [ -z $TESTRESPONSE ]; then
+ TESTRESPONSE="y"
+ fi
+
+ if [ $TESTRESPONSE = "n" -o $TESTRESPONSE = "N" ]; then
+ FAILED_TESTS="$FAILED_TESTS$TEST_ID,"
+ TOTAL_TESTS_FAILED=`expr $TOTAL_TESTS_FAILED + 1`
+ else
+ PASSED_TESTS="$PASSED_TESTS$TEST_ID,"
+ TOTAL_TESTS_PASSED=`expr $TOTAL_TESTS_PASSED + 1`
+ fi
+}
+
+# This function runs a single test and asks for success/failure confirmation.
+# Usage: t <test_id> <test_desc> nping [args]...
+t() {
+ TEST_ID="$1"
+ TEST_DESC="$2"
+ shift
+ shift
+ echo "=======================TEST START======================="
+ echo "[+] $TEST_ID: $TEST_DESC"
+ echo "$@"
+ # The next line runs the command.
+ "$@"
+ request_userinput_test_status
+ echo "========================TEST END========================"
+ echo ""
+ echo ""
+}
+
+
+# Tests still to write.
+
+# Traceroute. (What other options are possible here?)
+# Miscellaneous.
+# |_ Include a few regular executions.
+
+
+####################
+# TEST BATTERY #
+####################
+
+
+#### PRIVILEGE DETERMINATION AND DEFAULT BEHAVIOUR ####
+
+t TCPPRIVS_1 "Test default ping as non root. Expected tcp-connect mode." \
+nping $TARGETS $GLOBALOPTS
+
+t TCPPRIVS_2 "Test default ping as root. Expected ICMP Echo ping." \
+sudo nping $TARGETS $GLOBALOPTS
+
+t TCPPRIVS_3 "Test default ping as non root (IPv6). Expected tcp-connect mode." \
+nping -6 $TARGETS $GLOBALOPTS
+
+t TCPPRIVS_4 "Test default ping as root (IPv6). Expected ICMP Echo ping." \
+sudo nping -6 $TARGETS $GLOBALOPTS
+
+
+
+#### TARGET SPECIFICATION ####
+
+t TARGETSPEC_1 "Test single target spec (hostname)." \
+sudo nping $GLOBALOPTS -c1 google.com
+
+t TARGETSPEC_2 "Test single target spec (IP address)." \
+sudo nping $GLOBALOPTS 192.168.1.1
+
+t TARGETSPEC_3 "Test multiple target spec (two hostnames)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 google.com nmap.org
+
+t TARGETSPEC_4 "Test multiple target spec (two IP addresses)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 192.168.1.1 192.168.1.99
+
+t TARGETSPEC_5 "Test multiple target spec (IP range #1)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 192.168.1.1-10
+
+t TARGETSPEC_6 "Test multiple target spec (IP range #2)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 190-191.168.1-2.99-100
+
+t TARGETSPEC_7 "Test multiple target spec (IP range + hostname)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 192.168.1.1-10 google.com
+
+t TARGETSPEC_8 "Test multiple target spec (hostname with CIDR notation)." \
+sudo nping $GLOBALOPTS -c1 --rate 100 google.com/24
+
+t TARGETSPEC_9 "Test multiple target spec (IP with CIDR notation)." \
+sudo nping $GLOBALOPTS -c1 --rate 100 192.168.1.1/24
+
+t TARGETSPEC_10 "Test multiple target spec (mixed specs)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 192.168.1.1 192.168.1.99-100 google.com/29 scanme.nmap.org
+
+t TARGETSPEC_11 "Test unresolvable target spec. Expected: error message." \
+sudo nping $GLOBALOPTS -c1 bogushostname
+
+#Bug here. If our first target is not valid, then route_dst() fails. If we specify google.com first, then it works.
+t TARGETSPEC_12a "Test unresolvable target spec (some good names and some bad ones). Expected: error message for some of the targets." \
+sudo nping $GLOBALOPTS -c1 bogushostname google.com bogushostname2 insecure.org
+
+t TARGETSPEC_12b "Test unresolvable target spec (some good names and some bad ones). Expected: error message for some of the targets." \
+sudo nping $GLOBALOPTS -c1 google.com bogushostname bogushostname2 insecure.org
+
+t TARGETSPEC_13 "Don't specify any target host. Expected: error message." \
+sudo nping $GLOBALOPTS -c1
+
+# These will all fail becasue -iL is not implemmented.
+echo "google.com" > myhostlist.tmp
+t TARGETSPEC_14 "Test single target spec with -iL (hostname)." \
+sudo nping $GLOBALOPTS -c1 -iL myhostlist.tmp
+
+echo "192.168.1.1" > myhostlist.tmp
+t TARGETSPEC_15 "Test single target spec with -iL (IP address)." \
+sudo nping $GLOBALOPTS -c1 -iL myhostlist.tmp
+
+echo "google.com nmap.org" > myhostlist.tmp
+t TARGETSPEC_16 "Test multiple target spec with -iL (two hostnames)." \
+sudo nping $GLOBALOPTS -c1 -iL myhostlist.tmp
+
+echo "192.168.1.1 192.168.1.99" > myhostlist.tmp
+t TARGETSPEC_17 "Test multiple target spec with -iL (two IP addresses)." \
+sudo nping $GLOBALOPTS -c1 -iL myhostlist.tmp
+
+echo "192.168.1.1-10 " > myhostlist.tmp
+t TARGETSPEC_18 "Test multiple target spec with -iL (IP range #1)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 -iL myhostlist.tmp
+
+echo "192.168.1.1 192.168.1.99-100 google.com/29 scanme.nmap.org" > myhostlist.tmp
+t TARGETSPEC_19 "Test multiple target spec with -iL (mixed specs)." \
+sudo nping $GLOBALOPTS -c1 --rate 10 -iL myhostlist.tmp
+
+rm -f myhostlist.tmp
+
+
+
+
+#### TCP CONNECT MODE ####
+
+t TCPCONNECT_1 "Explicit TCP-CONNECT mode specification. Expected default destination port: 80" \
+sudo nping --tcp-connect $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_2 "TCP-CONNECT to an open port. Expected: Handshake complete messages." \
+sudo nping --tcp-connect -p$OPEN_PORT $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_3 "TCP-CONNECT to a closed port. Expected: <<Possible TCP RST received from>> messages." \
+sudo nping --tcp-connect -p$CLOSED_PORT $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_4 "TCP-CONNECT to a filtered port. Expected: Only <<Starting TCP Handshake>> messages." \
+sudo nping --tcp-connect -p$FILTERED_PORT $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_5 "TCP-CONNECT with a source port, as a regular user. Expected warning message [NOT_PASSED]" \
+nping --tcp-connect -g 1000 $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_6 "TCP-CONNECT with a source port, as root." \
+sudo nping --tcp-connect -g 1000 $TARGETS $GLOBALOPTS
+
+t TCPCONNECT_7 "TCP-CONNECT with the same source and target port, as root." \
+sudo nping --tcp-connect -p 1000 -g 1000 $TARGETS $GLOBALOPTS
+
+
+#### TCP MODE ####
+
+t TCP_1 "TCP default flags and port. BPF filter?" \
+sudo nping --tcp $TARGETS $GLOBALOPTS
+
+t TCP_2 "TCP open port." \
+sudo nping --tcp -p$OPEN_PORT $TARGETS $GLOBALOPTS
+
+t TCP_3 "TCP closed port." \
+sudo nping --tcp -p$CLOSED_PORT $TARGETS $GLOBALOPTS
+
+t TCP_4 "TCP filtered port." \
+sudo nping --tcp -p$FILTERED_PORT $TARGETS $GLOBALOPTS
+
+t TCP_5 "TCP source port." \
+sudo nping --tcp -g 1000 $TARGETS $GLOBALOPTS
+
+t TCP_6 "TCP source and dest port combined." \
+sudo nping --tcp -g 1000 -p1000 $TARGETS $GLOBALOPTS
+
+# Test no flags, all flags individually, all flags at once.
+t TCP_FLAG_empty "TCP flags empty string." \
+sudo nping --tcp --flags "" $TARGETS $GLOBALOPTS
+for flag in nil none cwr ecn ece urg ack psh rst syn fin all; do
+ t TCP_FLAG_$flag "TCP flags $flag." \
+ sudo nping --tcp --flags $flag $TARGETS $GLOBALOPTS
+done
+t TCP_FLAG_all_long "TCP flags cwr,ecn,ece,urg,ack,psh,rst,syn,fin." \
+sudo nping --tcp --flags cwr,ecn,ece,urg,ack,psh,rst,syn,fin $TARGETS $GLOBALOPTS
+for flag in c e u a p r s f; do
+ t TCP_FLAG_$flag "TCP flags $flag." \
+ sudo nping --tcp --flags $flag $TARGETS $GLOBALOPTS
+done
+t TCP_FLAG_all_short "TCP ceuaprsf." \
+sudo nping --tcp --flags ceuaprsf $TARGETS $GLOBALOPTS
+
+# Bogus flags.
+t TCP_7 "TCP flags ,." \
+sudo nping --tcp --flags , $TARGETS $GLOBALOPTS
+
+t TCP_8 "TCP flags dumb." \
+sudo nping --tcp --flags dumb $TARGETS $GLOBALOPTS
+
+t TCP_9 "TCP flags dumb,." \
+sudo nping --tcp --flags dumb, $TARGETS $GLOBALOPTS
+
+t TCP_10 "TCP flags 0x00." \
+sudo nping --tcp --flags 0x00 $TARGETS $GLOBALOPTS
+
+t TCP_11 "TCP flags 0xff." \
+sudo nping --tcp --flags 0xff $TARGETS $GLOBALOPTS
+
+t TCP_12 "TCP flags 0x100." \
+sudo nping --tcp --flags 0x100 $TARGETS $GLOBALOPTS
+
+t TCP_13 "TCP flags -0x11." \
+sudo nping --tcp --flags -0x11 $TARGETS $GLOBALOPTS
+
+t TCP_14 "TCP flags rand." \
+sudo nping --tcp --flags rand $TARGETS $GLOBALOPTS
+
+t TCP_15 "TCP seq decimal." \
+sudo nping --tcp --seq 12345678 $TARGETS $GLOBALOPTS
+
+t TCP_16 "TCP seq hex." \
+sudo nping --tcp --seq 0x12345678 $TARGETS $GLOBALOPTS
+
+t TCP_17 "TCP seq negative." \
+sudo nping --tcp --seq -1 $TARGETS $GLOBALOPTS
+
+t TCP_18 "TCP seq too big." \
+sudo nping --tcp --seq 10000000000 $TARGETS $GLOBALOPTS
+
+t TCP_19 "TCP seq rand." \
+sudo nping --tcp --seq rand $TARGETS $GLOBALOPTS
+
+t TCP_20 "TCP ack decimal." \
+sudo nping --tcp --ack 12345678 $TARGETS $GLOBALOPTS
+
+t TCP_21 "TCP ack hex." \
+sudo nping --tcp --ack 0x12345678 $TARGETS $GLOBALOPTS
+
+t TCP_22 "TCP ack negative." \
+sudo nping --tcp --ack -1 $TARGETS $GLOBALOPTS
+
+t TCP_23 "TCP ack too big." \
+sudo nping --tcp --ack 10000000000 $TARGETS $GLOBALOPTS
+
+t TCP_24 "TCP ack rand." \
+sudo nping --tcp --ack rand $TARGETS $GLOBALOPTS
+
+t TCP_25 "TCP win decimal." \
+sudo nping --tcp --win 1234 $TARGETS $GLOBALOPTS
+
+t TCP_26 "TCP win hex." \
+sudo nping --tcp --win 0x1234 $TARGETS $GLOBALOPTS
+
+t TCP_27 "TCP win negative." \
+sudo nping --tcp --win -1 $TARGETS $GLOBALOPTS
+
+t TCP_28 "TCP win too big." \
+sudo nping --tcp --win 70000 $TARGETS $GLOBALOPTS
+
+t TCP_29 "TCP win rand." \
+sudo nping --tcp --win rand $TARGETS $GLOBALOPTS
+
+t TCP_30 "TCP badsum." \
+sudo nping --tcp --badsum $TARGETS $GLOBALOPTS
+
+t TCP_31 "TCP mss." \
+sudo nping --tcp --mss 900 $TARGETS $GLOBALOPTS
+
+t TCP_32 "TCP ws." \
+sudo nping --tcp --ws 2 $TARGETS $GLOBALOPTS
+
+t TCP_33 "TCP ts 1234,5678." \
+sudo nping --tcp --ts 1234,5678 $TARGETS $GLOBALOPTS
+
+t TCP_34 "TCP ts rand,rand." \
+sudo nping --tcp --ts rand,rand $TARGETS $GLOBALOPTS
+
+t TCP_35 "TCP ts 1234." \
+sudo nping --tcp --ts 1234 $TARGETS $GLOBALOPTS
+
+
+
+#### UDP MODE ####
+
+# Unprivileged execution
+t UDP_UNPRIV_1 "Send UDP packet in unprivileged mode with default parameters. Expected: Packets to dport 40125 and <<UDP packet with 4 bytes>> messages." \
+nping --udp $TARGETS $GLOBALOPTS
+
+t UDP_UNPRIV_2 "Send UDP packet to custom dport. Expected: 4-byte UDP packets to port $OPEN_PORT and <<UDP packet with 4 bytes>> messages." \
+nping --udp -p $OPEN_PORT $TARGETS $GLOBALOPTS
+
+t UDP_UNPRIV_3 "Send UDP packet specifying a source port." \
+nping --udp -g 9876 $TARGETS $GLOBALOPTS
+
+t UDP_UNPRIV_4 "Send UDP packet specifying a both sport and dport." \
+nping --udp -g 9876 -p 9999 $TARGETS $GLOBALOPTS
+
+t UDP_UNPRIV_5 "Send UDP packet specifying a the same sport and dport." \
+nping --udp -g 9999 -p 9999 $TARGETS $GLOBALOPTS
+
+t UDP_UNPRIV_6 "Send UDP packet to a custom port with a custom payload. Expected: Packets to dport 9876 with 10byte payloads." \
+nping --udp -p 9876 $TARGETS $GLOBALOPTS --data-string "0123456789"
+
+
+# Privileged execution
+t UDP_PRIV_1 "Send UDP packet specifying a source port (as root). Expected: Packets to dport 40125 and sport 9876" \
+sudo nping --udp -g 9876 $TARGETS $GLOBALOPTS
+
+t UDP_PRIV_2 "Send UDP packet specifying a destination port (as root). Expected: Packets to dport $OPEN_PORT and sport 53" \
+sudo nping --udp -p$OPEN_PORT $TARGETS $GLOBALOPTS
+
+t UDP_PRIV_3 "Send UDP packet in privileged mode, speciying sport and dport. Expected: Packets to dport 33 and sport 44." \
+sudo nping --udp -p33 -g44 $TARGETS $GLOBALOPTS
+
+t UDP_PRIV_4 "Send UDP packet in privileged mode, speciying dport==sport. Expected: Packets with sport==dport==$OPEN_PORT." \
+sudo nping --udp -p$OPEN_PORT -g$OPEN_PORT $TARGETS $GLOBALOPTS
+
+t UDP_PRIV_4 "Send UDP packet in privileged mode, with a bad checksum. Expected: Packets with bad checksum. [See in wireshark]" \
+sudo nping --udp -p$OPEN_PORT --badsum $TARGETS $GLOBALOPTS
+
+
+#### ICMP MODE ####
+
+t ICMP_1 "Run icmp mode with no privileges. Expected: error message." \
+nping --icmp $TARGETS $GLOBALOPTS
+
+t ICMP_2 "Run ICMP mode with privileges. Expected: ICMP Echo packets (type=8/code=0)=to $TARGETS." \
+sudo nping --icmp $TARGETS $GLOBALOPTS
+
+t ICMP_3 "Run ICMP mode with explicit ICMP Echo especification. Expected: ICMP Echo packets (type=8/code=0)=to $TARGETS." \
+sudo nping --icmp --icmp-type echo $TARGETS $GLOBALOPTS
+
+ #sudo nping --icmp --icmp-type echo-request $TARGETS $GLOBALOPTS
+ #sudo nping --icmp --icmp-type e $TARGETS $GLOBALOPTS
+t ICMP_4 "Run ICMP mode with type Destination Unreachable." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type dest-unr
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type du
+t ICMP_5 "Run ICMP mode with type Source Quench." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type source-quench
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type sour-que
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type sq
+t ICMP_6 "Run ICMP mode with type Redirect." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redi
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type r
+t ICMP_7 "Run ICMP mode with explicit type Echo request." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo-request
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type e
+t ICMP_8 "Run ICMP mode with type Echo reply." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo-reply
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo-rep
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type er
+t ICMP_9 "Run ICMP mode with type Router Advertisement." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type router-advertisement
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type rout-adv
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra
+t ICMP_3 "Run ICMP mode with type Router Solicitation." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type router-solicitation
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type rout-sol
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type rs
+t ICMP_10 "Run ICMP mode with type time Exceeded." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time-exceeded
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time-exc
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type te
+t ICMP_11 "Run ICMP mode with type Parameter Problem." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type parameter-problem
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type para-pro
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp
+t ICMP_12 "Run ICMP mode with type Timestamp request." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type tm
+t ICMP_13 "Run ICMP mode with type Timestamp reply." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp-reply
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time-rep
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type tr
+t ICMP_14 "Run ICMP mode with type Information request." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type information
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type info
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type i
+t ICMP_15 "Run ICMP mode with type Information reply." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type information-reply
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type info-rep
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ir
+t ICMP_16 "Run ICMP mode with type Network Mask request." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type mask-request
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type mask
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type m
+t ICMP_17 "Run ICMP mode with type Network Mask reply." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type mask-reply
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type mask-rep
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type mr
+t ICMP_18 "Run ICMP mode with type Traceroute request." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type traceroute
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type trace
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type tc
+t ICMP_19 "Run ICMP mode with type Destination Unreachable and Code Network Unreachable." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code network-unreachable
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code netw-unr
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code net
+t ICMP_20 "Run ICMP mode with type Destination Unreachable and Code Host Unreachable" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-unreachable
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-unr
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host
+t ICMP_21 "Run ICMP mode with type Destination Unreachable and Code Protocol unreachable" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code protocol-unreachable
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code prot-unr
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code proto
+t ICMP_22 "Run ICMP mode with type Destination Unreachable and Code " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code port-unreachable
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code port-unr
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code port
+t ICMP_23 "Run ICMP mode with type Destination Unreachable and Code Needs Fragmentation" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code needs-fragmentation
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code need-fra
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code frag
+t ICMP_24 "Run ICMP mode with type Destination Unreachable and Code Source Route Failed" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code source-route-failed
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code sour-rou
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code routefail
+t ICMP_25 "Run ICMP mode with type Destination Unreachable and Code network-unknown" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code network-unknown
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code netw-unk
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code net?
+t ICMP_26 "Run ICMP mode with type Destination Unreachable and Code host-unknown" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-unknown
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-unk
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host?
+t ICMP_27 "Run ICMP mode with type Destination Unreachable and Code host-isolated" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-isolated
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-iso
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code isolated
+t ICMP_28 "Run ICMP mode with type Destination Unreachable and Code network-prohibited" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code network-prohibited
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code netw-pro
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code !net
+t ICMP_29 "Run ICMP mode with type Destination Unreachable and Code host-prohibited" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-prohibited
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-pro
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code !host
+t ICMP_30 "Run ICMP mode with type Destination Unreachable and Code network-tos" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code network-tos
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code unreachable-network-tos
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code netw-tos
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code tosnet
+t ICMP_31 "Run ICMP mode with type Destination Unreachable and Code host-tos" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-tos
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code unreachable-host-tos
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code toshost
+t ICMP_2 "Run ICMP mode with type Destination Unreachable and Code communication-prohibited" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code communication-prohibited
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code comm-pro
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code !comm
+t ICMP_32 "Run ICMP mode with type Destination Unreachable and Code host-precedence-violation" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code host-precedence-violation
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code precedence-violation
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code prec-vio
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code violation
+t ICMP_33 "Run ICMP mode with type Destination Unreachable and Code precedence-cutoff" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code precedence-cutoff
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code prec-cut
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type destination-unreachable --icmp-code cutoff
+t ICMP_34 "Run ICMP mode with type Redirect and Code redirect-network" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redirect-network
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redi-net
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code net
+t ICMP_35 "Run ICMP mode with type Redirect and Code redirect-host" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redirect-host
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redi-host
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code host
+t ICMP_36 "Run ICMP mode with type Redirect and Code redirect-network-tos" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redirect-network-tos
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redi-ntos
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redir-ntos
+t ICMP_37 "Run ICMP mode with type Redirect and Code redirect-host-tos" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redirect-host-tos
+
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redi-htos
+ #sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-code redir-htos
+t ICMP_38 "Run ICMP mode with type Router Advert and Code normal-advertisement" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type router-advertisement --icmp-code normal-advertisement
+
+t ICMP_39 "Run ICMP mode with type Router Advert and Code not-route-common-traffic" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type router-advertisement --icmp-code not-route-common-traffic
+
+t ICMP_40 "Run ICMP mode with type Time Exceeded and Code ttl-exceeded-in-transit" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time-exceeded --icmp-code ttl-exceeded-in-transit
+
+t ICMP_41 "Run ICMP mode with type Time Exceeded and Code fragment-reassembly-time-exceeded" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type time-exceeded --icmp-code fragment-reassembly-time-exceeded
+
+t ICMP_42 "Run ICMP mode with type Parameter Problem and Code pointer-indicates-error" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type parameter-problem --icmp-code pointer-indicates-error
+
+t ICMP_43 "Run ICMP mode with type Parameter Problem and Code missing-required-option" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type parameter-problem --icmp-code missing-required-option
+
+t ICMP_44 "Run ICMP mode with type Parameter Problem and Code bad-length" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type parameter-problem --icmp-code bad-length
+
+t ICMP_45 "Run ICMP mode supplying type as an integer" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type 8
+
+t ICMP_46 "Run ICMP mode supplying type as a bogus integer. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type 100000
+
+t ICMP_47 "Run ICMP mode supplying non-existing type. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type bogustype
+
+t ICMP_48 "Run ICMP mode supplying a numeric type, NON-RFC compliant (<18). Expected: warning message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type 55
+
+t ICMP_49 "Run ICMP mode supplying a numeric code." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 5
+
+t ICMP_50 "Run ICMP mode supplying a bogus code." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code boguscode
+
+t ICMP_51 "Run ICMP mode supplying a number code, NON-RFC compliant." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 99
+
+t ICMP_52 "Set ICMP Identifier. (Don't get confused with output for the IP id value)" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-id 2
+
+t ICMP_53 "Set bogus Identifier. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-id bogusid
+
+t ICMP_54 "Set negative Identifier. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-id -99
+
+t ICMP_55 "Set out of bounds Identifier (id>(2^16)-1). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-id 65536
+
+t ICMP_56 "Set ICMP Sequence number." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-seq 22
+
+t ICMP_57 "Set bogus ICMP sequence number. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-seq bogusseq
+
+t ICMP_58 "Set negative ICMP sequence number. Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-seq -99
+
+t ICMP_59 "Set out of bounds ICMP sequence number (seq>(2^16)-1). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-code 9 --icmp-seq 65536
+
+t ICMP_60 "Send ICMP Redirect with redirect IP=1.2.3.4." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-redirect-addr 1.2.3.4
+
+t ICMP_61 "Send ICMP Redirect with redirect IP=google.com. Expected: google.com gets resolved." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-redirect-addr google.com
+
+t ICMP_62 "Send ICMP Redirect passing a redirect IP hostname that does not resolve. Expected: error" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type redirect --icmp-redirect-addr bogushostspec
+
+t ICMP_63 "Use --icmp-redirect-addr but don't send ICMP redirect but another type. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-redirect-addr 1.2.3.4
+
+t ICMP_64 "Use --icmp-redirect-addr but don't specify ICMP type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-redirect-addr 1.2.3.4
+
+t ICMP_65 "Send ICMP Parameter problem with parameter pointer=0" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp --icmp-param-pointer 0
+
+t ICMP_66 "Send ICMP Parameter problem with nonzero parameter pointer" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp --icmp-param-pointer 128
+
+t ICMP_67 "Send ICMP Parameter problem with bogus parameter pointer. Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp --icmp-param-pointer boguspp
+
+t ICMP_68 "Send ICMP Parameter problem with negative parameter pointer. Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp --icmp-param-pointer -99
+
+t ICMP_69 "Send ICMP Parameter problem with out-of-bounds parameter pointer (pp>255). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type pp --icmp-param-pointer 256
+
+t ICMP_70 "Specify --icmp-param-pointer but use an ICMP Type != ParameterProblem. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-param-pointer 22
+
+t ICMP_71 "Specify --icmp-param-pointer but do not specify any ICMP Type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-param-pointer 15
+
+t ICMP_72 "Send ICMP Router Advertisement with advert lifetime=0" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-lifetime 0
+
+t ICMP_73 "Send ICMP Router Advertisement with a nonzero advert lifetime" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-lifetime 37556
+
+t ICMP_74 "Send ICMP Router Advertisement with a bougs advert lifetime. Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-lifetime bogusAL
+
+t ICMP_75 "Send ICMP Router Advertisement with a negative advert lifetime. Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-lifetime -56
+
+t ICMP_76 "Send ICMP Router Advertisement with an out-of-bounds (al>65535) advert lifetime. Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-lifetime 65536
+
+t ICMP_77 "Specify --icmp-advert-lifetime but use an ICMP Type != Router Advertisement. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-advert-lifetime 22
+
+t ICMP_78 "Specify --icmp-advert-lifetime but do not specify any ICMP Type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-advert-lifetime 24
+
+t ICMP_79 "Send ICMP Router Advertisement with zeroed advert entry" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 0.0.0.0,0
+
+t ICMP_80 "Send ICMP Router Advertisement with a normal preference and a zero IP" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 0.0.0.0,16777215
+
+t ICMP_81 "Send ICMP Router Advertisement with a normal advert entry" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,16777215
+
+t ICMP_82 "Send ICMP Router Advertisement with an advert entry specified as a hostname" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry google.com,16777215
+
+t ICMP_83 "Send ICMP Router Advertisement with a few advert entries" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,11111 --icmp-advert-entry 11.22.33.44,22222 --icmp-advert-entry 55.66.77.88,333333
+
+t ICMP_84 "Send ICMP Router Advertisement with bogus entry #1 (missing preference). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,
+
+t ICMP_85 "Send ICMP Router Advertisement with bogus entry #2 (IP). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry ,10
+
+t ICMP_86 "Send ICMP Router Advertisement with bogus entry #3 (missing parameter). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry
+
+t ICMP_87 "Send ICMP Router Advertisement with bogus entry #4 (unresolvable hostname). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry asdasdasdasdasd,222
+
+t ICMP_88 "Send ICMP Router Advertisement with bogus entry #5 (bad preference). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,boguspref
+
+t ICMP_89 "Send ICMP Router Advertisement with bogus entry #6 (negative preference). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,-222
+
+#This works and it should't. "5" should not be resolved to 0.0.0.5 but detected as a bad IP.
+t ICMP_90 "Send ICMP Router Advertisement with bogus entry #7 (bad IP format). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 5,222
+
+t ICMP_91 "Send ICMP Router Advertisement with bogus entry #8 (out-of-bounds IP). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 256.257.258.259,222
+
+t ICMP_92 "Send ICMP Router Advertisement with bogus entry #9 (out-of-bounds preference). Expected: error msg" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,999999999999999
+
+t ICMP_93 "Send ICMP Router Advertisement with a duplicated adevert entry. Expected: normal operation" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type ra --icmp-advert-entry 1.2.3.4,555 --icmp-advert-entry 1.2.3.4,555
+
+t ICMP_94 "Specify --icmp-advert-entry but use an ICMP type!= Router Advertisement. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-advert-entry 1.2.3.4,555
+
+t ICMP_95 "Specify --icmp-advert-entry but do not specify ICMP type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-advert-entry 1.2.3.4,555
+
+# Parameter --icmp-orig-time
+t ICMP_96 "Send ICMP Timestamp Request with zeroed originate timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time 0
+
+t ICMP_97 "Send ICMP Timestamp Request with a normal originate timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time 57509000
+
+t ICMP_98 "Send ICMP Timestamp Request with current originate timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now
+
+t ICMP_99 "Send ICMP Timestamp Request with current originate timestamp + 1 minute" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now+1m
+
+t ICMP_100 "Send ICMP Timestamp Request with current originate timestamp + 2 hours" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now+2h
+
+t ICMP_101 "Send ICMP Timestamp Request with current originate timestamp minus 200 milliseconds" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now-200ms
+
+t ICMP_102 "Send ICMP Timestamp Request with explicit positive originate timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time +10
+
+t ICMP_103 "Send ICMP Timestamp Request with negative originate timestamp. Expected: It should be ok to specify negative values" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time -10
+
+t ICMP_104 "Send ICMP Timestamp Request with bogus originate timestamp #1 (no number). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time bogusts
+
+t ICMP_105 "Send ICMP Timestamp Request with bogus originate timestamp #2 (now+bogusspec). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now+bogus
+
+t ICMP_106 "Send ICMP Timestamp Request with bogus originate timestamp #3 (now+[nothing]). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now+
+
+t ICMP_107 "Send ICMP Timestamp Request with bogus originate timestamp #4 (wrong order 1000+now). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time 1000+now
+
+t ICMP_108 "Send ICMP Timestamp Request with originate timestamp but specify ICMP Type!=Timestamp. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-orig-time now
+
+t ICMP_109 "Send ICMP Timestamp Request with originate timestamp but do not specify ICMP type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-orig-time now
+
+# Parameter --icmp-recv-time
+t ICMP_110 "Send ICMP Timestamp Request with zeroed receive timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time 0
+
+t ICMP_111 "Send ICMP Timestamp Request with a normal receive timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time 57509000
+
+t ICMP_112 "Send ICMP Timestamp Request with current receive timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now
+
+t ICMP_113 "Send ICMP Timestamp Request with current receive timestamp + 1 minute" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now+1m
+
+t ICMP_114 "Send ICMP Timestamp Request with current receive timestamp + 2 hours" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now+2h
+
+t ICMP_115 "Send ICMP Timestamp Request with current receive timestamp minus 200 milliseconds" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now-200ms
+
+t ICMP_116 "Send ICMP Timestamp Request with explicit positive receive timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time +10
+
+t ICMP_117 "Send ICMP Timestamp Request with negative receive timestamp. Expected: It should be ok to specify negative values" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time -10
+
+t ICMP_118 "Send ICMP Timestamp Request with bogus receive timestamp #1 (no number). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time bogusts
+
+t ICMP_119 "Send ICMP Timestamp Request with bogus receive timestamp #2 (now+bogusspec). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now+bogus
+
+t ICMP_120 "Send ICMP Timestamp Request with bogus receive timestamp #3 (now+[nothing]). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time now+
+
+t ICMP_121 "Send ICMP Timestamp Request with bogus receive timestamp #4 (wrong order 1000+now). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-recv-time 1000+now
+
+t ICMP_122 "Send ICMP Timestamp Request with receive timestamp but specify ICMP Type!=Timestamp. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-recv-time now
+
+t ICMP_123 "Send ICMP Timestamp Request with receive timestamp but do not specify ICMP type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-recv-time now
+
+# Parameter --icmp-trans-time
+t ICMP_124 "Send ICMP Timestamp Request with zeroed transmit timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time 0
+
+t ICMP_125 "Send ICMP Timestamp Request with a normal transmit timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time 57509000
+
+t ICMP_126 "Send ICMP Timestamp Request with current transmit timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now
+
+t ICMP_127 "Send ICMP Timestamp Request with current transmit timestamp + 1 minute" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now+1m
+
+t ICMP_128 "Send ICMP Timestamp Request with current transmit timestamp + 2 hours" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now+2h
+
+t ICMP_129 "Send ICMP Timestamp Request with current transmit timestamp minus 200 milliseconds" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now-200ms
+
+t ICMP_130 "Send ICMP Timestamp Request with explicit positive transmit timestamp" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time +10
+
+t ICMP_131 "Send ICMP Timestamp Request with negative transmit timestamp. Expected: It should be ok to specify negative values" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time -10
+
+t ICMP_132 "Send ICMP Timestamp Request with bogus transmit timestamp #1 (no number). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time bogusts
+
+t ICMP_133 "Send ICMP Timestamp Request with bogus transmit timestamp #2 (now+bogusspec). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now+bogus
+
+t ICMP_134 "Send ICMP Timestamp Request with bogus transmit timestamp #3 (now+[nothing]). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time now+
+
+t ICMP_135 "Send ICMP Timestamp Request with bogus transmit timestamp #4 (wrong order 1000+now). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-trans-time 1000+now
+
+t ICMP_136 "Send ICMP Timestamp Request with transmit timestamp but specify ICMP Type!=Timestamp. Expected: parameter ignored" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --icmp-trans-time now
+
+t ICMP_137 "Send ICMP Timestamp Request with transmit timestamp but do not specify ICMP type. Expected: parameter ignored and default ICMP mode set" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-trans-time now
+
+# --icmp-orig-time, --icmp-recv-time and --icmp-trans-time together
+t ICMP_138 "Send ICMP Timestamp Request with all timestamps" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp --icmp-orig-time now-2s --icmp-trans-time now-1s --icmp-recv-time now
+
+t ICMP_139 "Test it also works with replies." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type timestamp-reply --icmp-orig-time now-2s --icmp-trans-time now-1s --icmp-recv-time now
+
+
+
+#### ARP/RARP MODE ####
+
+t ARP_0 "Test ARP mode with default values. Expected: <<ARP Who has?>> for target host" \
+sudo nping --arp $TARGETS $GLOBALOPTS
+
+t ARP_1 "Send ARP Requests" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request
+
+t ARP_2 "Send ARP Replies" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-reply
+
+t ARP_3 "Send RARP Requests" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type rarp-request
+
+t ARP_4 "Send RARP Replies" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type rarp-reply
+
+t ARP_5 "Send DRARP Requests" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type drarp-request
+
+t ARP_6 "Send DRARP Replies" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type drarp-reply
+
+t ARP_7 "Send DRARP Error messages" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type drarp-error
+
+t ARP_8 "Send INARP Requests" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type inarp-request
+
+t ARP_9 "Send INARP Replies" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type inarp-reply
+
+t ARP_10 "Send ARP NAKs" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-nak
+
+t ARP_10b "Supply bogus ARP type" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type bogusarptype
+
+t ARP_10c "Supply NULL ARP type" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type ""
+
+t ARP_11 "Test sender MAC specification #1 (standard notation)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac AA:BB:CC:DD:EE:FF
+
+t ARP_12 "Test sender MAC specification #2 (using hyphens as octet separators)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac AA-BB-CC-DD-EE-FF
+
+t ARP_13 "Test sender MAC specification, suplying a bogus MAC #1 (too short MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac AA:BB:CC:DD:EE
+
+t ARP_14 "Test sender MAC specification, suplying a bogus MAC #2 (too long MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac AA:BB:CC:DD:EE:FF:GG
+
+t ARP_15 "Test sender MAC specification, suplying a bogus MAC #3 (empty MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac ""
+
+t ARP_16 "Test sender MAC specification, suplying a bogus MAC #4 (MAC with a colon at the end)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac AA:BB:CC:DD:EE:FF:
+
+t ARP_17 "Test sender MAC specification, suplying a bogus MAC #4 (MAC with a colon at the beginning)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-mac :AA:BB:CC:DD:EE:FF
+
+t ARP_18 "Test target MAC specification #1 (standard notation)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac AA:BB:CC:DD:EE:FF
+
+t ARP_19 "Test target MAC specification #2 (using hyphens as octet separators)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac AA-BB-CC-DD-EE-FF
+
+t ARP_20 "Test target MAC specification, suplying a bogus MAC #1 (too short MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac AA:BB:CC:DD:EE
+
+t ARP_21 "Test target MAC specification, suplying a bogus MAC #2 (too long MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac AA:BB:CC:DD:EE:FF:GG
+
+t ARP_22 "Test target MAC specification, suplying a bogus MAC #3 (empty MAC)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac ""
+
+t ARP_23 "Test target MAC specification, suplying a bogus MAC #4 (MAC with a colon at the end)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac AA:BB:CC:DD:EE:FF:
+
+t ARP_24 "Test target MAC specification, suplying a bogus MAC #4 (MAC with a colon at the beginning)" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-mac :AA:BB:CC:DD:EE:FF
+
+t ARP_25 "Test sender IP. Supply IP address in standard decimal dot notation" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-ip 1.2.3.4
+
+t ARP_26 "Test sender IP. Supply IP address as a resolvable hostname" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-ip google.com
+
+t ARP_27 "Test sender IP, supplying an unresolvable hostname. Expected: error message" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-ip bogussenderip
+
+t ARP_28 "Test sender IP, supplying a null IP. Expected: error message" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-sender-ip ""
+
+t ARP_29 "Test target IP. Supply IP address in standard decimal dot notation" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-ip 1.2.3.4
+
+t ARP_30 "Test target IP. Supply IP address as a resolvable hostname" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-ip google.com
+
+t ARP_31 "Test target IP, supplying an unresolvable hostname. Expected: error message" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-ip bogustargetip
+
+t ARP_32 "Test target IP, supplying a null IP. Expected: error message" \
+sudo nping --arp $TARGETS $GLOBALOPTS --arp-type arp-request --arp-target-ip ""
+
+
+#### IPV4 OPTIONS ####
+
+t IP_1 "IP source IP." \
+sudo nping --tcp -S 5.5.5.5 $TARGETS $GLOBALOPTS
+
+t IP_2 "IP dest IP." \
+sudo nping --tcp --dest-ip="$TARGETS" $GLOBALOPTS
+
+t IP_3 "IP dest IP with target specification." \
+sudo nping --tcp --dest-ip="5.5.5.5" $TARGETS $GLOBALOPTS
+
+t IP_4 "IP tos decimal." \
+sudo nping --tcp --tos 10 $TARGETS $GLOBALOPTS
+
+t IP_5 "IP tos hex." \
+sudo nping --tcp --tos 0x10 $TARGETS $GLOBALOPTS
+
+t IP_6 "IP tos negative." \
+sudo nping --tcp --tos -5 $TARGETS $GLOBALOPTS
+
+t IP_7 "IP tos too big." \
+sudo nping --tcp --tos 256 $TARGETS $GLOBALOPTS
+
+t IP_8 "IP tos rand." \
+sudo nping --tcp --tos rand $TARGETS $GLOBALOPTS
+
+t IP_9 "IP id decimal." \
+sudo nping --tcp --id 1234 $TARGETS $GLOBALOPTS
+
+t IP_10 "IP id hex." \
+sudo nping --tcp --id 0x1234 $TARGETS $GLOBALOPTS
+
+t IP_11 "IP id negative." \
+sudo nping --tcp --id -5 $TARGETS $GLOBALOPTS
+
+t IP_12 "IP id too big." \
+sudo nping --tcp --id 70000 $TARGETS $GLOBALOPTS
+
+t IP_13 "IP id rand." \
+sudo nping --tcp --id rand $TARGETS $GLOBALOPTS
+
+t IP_14 "IP df." \
+sudo nping --tcp --df $TARGETS $GLOBALOPTS
+
+t IP_15 "IP mf." \
+sudo nping --tcp --mf $TARGETS $GLOBALOPTS
+
+t IP_16 "IP df mf." \
+sudo nping --tcp --df --mf $TARGETS $GLOBALOPTS
+
+t IP_17 "IP ttl decimal." \
+sudo nping --tcp --ttl 10 $TARGETS $GLOBALOPTS
+
+t IP_18 "IP ttl hex." \
+sudo nping --tcp --ttl 0x10 $TARGETS $GLOBALOPTS
+
+t IP_19 "IP ttl negative." \
+sudo nping --tcp --ttl -5 $TARGETS $GLOBALOPTS
+
+t IP_20 "IP ttl too big." \
+sudo nping --tcp --ttl 256 $TARGETS $GLOBALOPTS
+
+t IP_21 "IP ttl rand." \
+sudo nping --tcp --ttl rand $TARGETS $GLOBALOPTS
+
+t IP_22 "IP badsum-ip." \
+sudo nping --tcp --badsum-ip $TARGETS $GLOBALOPTS
+
+for mtu in 0 20 600 1500 65536 70000; do
+ t IP_mtu$mtu "IP mtu $mtu." \
+ sudo nping --tcp --mtu $mtu $TARGETS $GLOBALOPTS
+done
+
+t IP_23 "IP options null." \
+sudo nping --tcp --ip-options "" $TARGETS $GLOBALOPTS
+
+t IP_24 "IP options R." \
+sudo nping --tcp --ip-options "R" $TARGETS $GLOBALOPTS
+
+t IP_25 "IP options R with trailing data." \
+sudo nping --tcp --ip-options "R bogus" $TARGETS $GLOBALOPTS
+
+t IP_26 "IP options T." \
+sudo nping --tcp --ip-options "T" $TARGETS $GLOBALOPTS
+
+t IP_27 "IP options T with trailing data." \
+sudo nping --tcp --ip-options "T bogus" $TARGETS $GLOBALOPTS
+
+t IP_28 "IP options U." \
+sudo nping --tcp --ip-options "U" $TARGETS $GLOBALOPTS
+
+t IP_29 "IP options U with trailing data." \
+sudo nping --tcp --ip-options "U bogus" $TARGETS $GLOBALOPTS
+
+t IP_30 "IP options S no hops." \
+sudo nping --tcp --ip-options "S" $TARGETS $GLOBALOPTS
+
+t IP_31 "IP options S some hops." \
+sudo nping --tcp --ip-options "S 1.1.1.1 2.2.2.2" $TARGETS $GLOBALOPTS
+
+t IP_32 "IP options S too many hops." \
+sudo nping --tcp --ip-options "S 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 5.5.5.5 6.6.6.6 7.7.7.7 8.8.8.8 9.9.9.9" $TARGETS $GLOBALOPTS
+
+t IP_33 "IP options L no hops." \
+sudo nping --tcp --ip-options "L" $TARGETS $GLOBALOPTS
+
+t IP_34 "IP options L some hops." \
+sudo nping --tcp --ip-options "L 1.1.1.1 2.2.2.2" $TARGETS $GLOBALOPTS
+
+t IP_35 "IP options L too many hops." \
+sudo nping --tcp --ip-options "L 1.1.1.1 2.2.2.2 3.3.3.3 4.4.4.4 5.5.5.5 6.6.6.6 7.7.7.7 8.8.8.8 9.9.9.9" $TARGETS $GLOBALOPTS
+
+t IP_36 "IP options RTUS." \
+sudo nping --tcp --ip-options "RTUS 1.1.1.1 2.2.2.2" $TARGETS $GLOBALOPTS
+
+t IP_37 "IP options hex." \
+sudo nping --tcp --ip-options "\xff" $TARGETS $GLOBALOPTS
+
+t IP_38 "IP options decimal." \
+sudo nping --tcp --ip-options "\255" $TARGETS $GLOBALOPTS
+
+t IP_39 "IP options repetition." \
+sudo nping --tcp --ip-options "\x12*8" $TARGETS $GLOBALOPTS
+
+
+#### IPV6 OPTIONS ####
+
+t IPV6_1 "IPv6 source IP." \
+sudo nping -6 --tcp -S 55::55 $TARGETS $GLOBALOPTS
+
+t IPV6_2 "IPv6 dest IP." \
+sudo nping -6 --tcp --dest-ip="$TARGETS" $GLOBALOPTS
+
+t IPV6_3 "IPv6 dest IP with target specification." \
+sudo nping -6 --tcp --dest-ip="55::55" $TARGETS $GLOBALOPTS
+
+t IPV6_4 "IPv6 flow decimal." \
+sudo nping -6 --tcp --flow 10 $TARGETS $GLOBALOPTS
+
+t IPV6_5 "IPv6 flow hex." \
+sudo nping -6 --tcp --flow 0x10 $TARGETS $GLOBALOPTS
+
+t IPV6_6 "IPv6 flow negative." \
+sudo nping -6 --tcp --flow -5 $TARGETS $GLOBALOPTS
+
+t IPV6_7 "IPv6 flow > 2**20." \
+sudo nping -6 --tcp --flow 2000000 $TARGETS $GLOBALOPTS
+
+t IPV6_8 "IPv6 flow > 2**32." \
+sudo nping -6 --tcp --flow 10000000000 $TARGETS $GLOBALOPTS
+
+t IPV6_9 "IPv6 flow rand." \
+sudo nping -6 --tcp --flow rand $TARGETS $GLOBALOPTS
+
+t IPV6_10 "IPv6 hop-limit decimal." \
+sudo nping -6 --tcp --hop-limit 10 $TARGETS $GLOBALOPTS
+
+t IPV6_11 "IPv6 hop-limit hex." \
+sudo nping -6 --tcp --hop-limit 0x10 $TARGETS $GLOBALOPTS
+
+t IPV6_12 "IPv6 hop-limit negative." \
+sudo nping -6 --tcp --hop-limit -5 $TARGETS $GLOBALOPTS
+
+t IPV6_13 "IPv6 hop-limit too big." \
+sudo nping -6 --tcp --hop-limit 256 $TARGETS $GLOBALOPTS
+
+t IPV6_14 "IPv6 hop-limit rand." \
+sudo nping -6 --tcp --hop-limit rand $TARGETS $GLOBALOPTS
+
+t IPV6_15 "IPv6 traffic-class decimal." \
+sudo nping -6 --tcp --traffic-class 10 $TARGETS $GLOBALOPTS
+
+t IPV6_16 "IPv6 traffic-class hex." \
+sudo nping -6 --tcp --traffic-class 0x10 $TARGETS $GLOBALOPTS
+
+t IPV6_17 "IPv6 traffic-class negative." \
+sudo nping -6 --tcp --traffic-class -5 $TARGETS $GLOBALOPTS
+
+t IPV6_18 "IPv6 traffic-class too big." \
+sudo nping -6 --tcp --traffic-class 256 $TARGETS $GLOBALOPTS
+
+t IPV6_19 "IPv6 traffic-class rand." \
+sudo nping -6 --tcp --traffic-class rand $TARGETS $GLOBALOPTS
+
+
+#### PAYLOAD RELATED OPTIONS ####
+
+t PAYLOAD_1 "Test raw hex payload specification. Data starts with 0x." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data 0xAABBCCDDEEFF
+
+t PAYLOAD_2 "Test raw hex payload specification. Data does not start with 0x." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data AABBCCDDEEFF
+
+t PAYLOAD_3 "Test raw hex payload specification. Data specified with the \xNN format." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data "\xAA\xBB\xCC\xDD\xEE\xFF"
+
+t PAYLOAD_4 "Test raw hex payload specification, specifying bogus hex data #1 (uneven hex chars) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data 0xAAB
+
+t PAYLOAD_5 "Test raw hex payload specification, specifying bogus hex data #2 (uneven hex chars without the 0x) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data AAB
+
+t PAYLOAD_6 "Test raw hex payload specification, specifying bogus hex data #3 (uneven hex chars with the \xNN format.) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data "\xAA\xB"
+
+t PAYLOAD_7 "Test raw hex payload specification, specifying bogus hex data #4 (uneven hex chars with the \xNN format.) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data "\xAA\xB"
+
+t PAYLOAD_8 "Test raw hex payload specification, specifying bogus hex data #5 (non hex digits) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data 0xFG
+
+t PAYLOAD_9 "Test raw hex payload specification, specifying bogus hex data #6 (non hex digits) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data FG
+
+t PAYLOAD_10 "Test raw hex payload specification, specifying bogus hex data #7 (no hex digits, just 0x) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data 0x
+
+t PAYLOAD_11 "Test raw hex payload specification, specifying bogus hex data #8 (no hex digits, just "\x") Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data "\x"
+
+t PAYLOAD_12 "Test raw hex payload specification, specifying bogus hex data #9 (just pass empty quotes) Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data ""
+
+t PAYLOAD_13 "Test string payload specification. Supply a single character." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-string A
+
+t PAYLOAD_14 "Test string payload specification. Supply sentence" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-string "Let me tell you about Sally Brown..."
+
+t PAYLOAD_15 "Test string payload specification. Supply hex data. Expected: treat that as a regular ASCII string, not as hex data" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-string 0xAABBCCDD
+
+t PAYLOAD_16 "Test string payload specification, specifying empty string" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-string ""
+
+t PAYLOAD_17a "Test random data payload specification. Include 0 bytes." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 0
+
+t PAYLOAD_17b "Test random data payload specification. Include 1 byte." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 1
+
+t PAYLOAD_18 "Test random data payload specification. Include 100 bytes." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 100
+
+t PAYLOAD_19 "Test random data payload specification. Include maximum recomended payload bytes." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 1400
+
+t PAYLOAD_20 "Test random data payload specification. Include more than maximum recomended payload bytes. Expected: warning message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 1401
+
+t PAYLOAD_21 "Test random data payload specification. Include maximum allowed payload bytes." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 65400
+
+t PAYLOAD_22 "Test random data payload specification. Include more tan maximum allowed payload bytes. Expected error message." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 65401
+
+t PAYLOAD_23 "Test random data payload specification. Include a lot more tan maximum allowed payload bytes. Expected error message." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len 999999999999999999
+
+t PAYLOAD_24 "Test random data payload specification, specifying bogus data (negative number of bytes)." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-len -1
+
+# The following tests are not passed because --data-file is currently unimplemented
+
+# Generate an empty file
+rm -f NPINGEMPTYFILE.tmp
+touch NPINGEMPTYFILE.tmp
+t PAYLOAD_25 "Test payload file specification, specifying an empty file. Expected: Packets with a 0-byte payload." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-file NPINGEMPTYFILE.tmp
+# And delete it after the test
+rm -f NPINGEMPTYFILE.tmp
+
+# Generate regular empty file
+echo "London's burning dial 99999..." > NPINGREGULARFILE.tmp
+t PAYLOAD_26 "Test payload file specification, specifying normal file with a normal string. Expected: Packets with the string included." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-file NPINGREGULARFILE.tmp
+# And delete it after the test
+rm -f NPINGREGULARFILE.tmp
+
+t PAYLOAD_27 "Test payload file specification, specifying a nonexisting or not-readable file. Expected: error message." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-file FILE_THAT_DOES_NOT_EXIST.tmp
+
+t PAYLOAD_28 "Test payload file specification, specifying a null filename. Expected: error message." \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --data-file ""
+
+# This doesn't give an error, it just ignores the payload spec.
+t PAYLOAD_29 "Test payload specification in TCP connect mode. Expected: warning message." \
+nping --tcp-connect $TARGETS $GLOBALOPTS --data-string "Test Payload"
+
+
+#### ECHO MODE ####
+
+# Client
+t ECHO_1 "Test client connection to echo.nmap.org." \
+sudo nping --echo-client "public" echo.nmap.org -c2
+
+t ECHO_2 "Test client connection to a bogus server" \
+sudo nping --echo-client "public" bogus.bogus
+
+t ECHO_3 "Test client connection to a server that has no NEP service running" \
+sudo nping --echo-client "public" google.com
+
+t ECHO_4 "Test client connection to echo.nmap.org using the explicit port number 9929" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port 9929 -c2
+
+t ECHO_5 "Test client connection to echo.nmap.org but using a different port" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port 34554
+
+t ECHO_6 "Test client connection to echo.nmap.org but using an invalid port number #1" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port -1
+
+t ECHO_7 "Test client connection to echo.nmap.org but using an invalid port number #2" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port BOGUSPORT
+
+t ECHO_8 "Test client connection to echo.nmap.org but using an invalid port number #3" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port 65536
+
+t ECHO_9 "Test client connection to echo.nmap.org but using an invalid port number #4" \
+sudo nping --echo-client "public" echo.nmap.org --echo-port 0
+
+t ECHO_10 "Test client connection to echo.nmap.org. TCP mode" \
+sudo nping --echo-client "public" echo.nmap.org --tcp -c2
+
+t ECHO_11 "Test client connection to echo.nmap.org. UDP mode" \
+sudo nping --echo-client "public" echo.nmap.org --udp -c2
+
+t ECHO_12 "Test client connection to echo.nmap.org. ICMP mode" \
+sudo nping --echo-client "public" echo.nmap.org --icmp -c2
+
+t ECHO_13 "Test client connection to echo.nmap.org. TCP connect mode. Expected: Failure" \
+sudo nping --echo-client "public" echo.nmap.org --tcp-connect
+
+t ECHO_14 "Test client connection to echo.nmap.org. ARP mode. Expected: Failure" \
+sudo nping --echo-client "public" echo.nmap.org --arp
+
+t ECHO_15 "Test client connection to echo.nmap.org. RARP mode. Expected: Failure" \
+sudo nping --echo-client "public" echo.nmap.org --rarp
+
+t ECHO_16 "Test client connection to echo.nmap.org, using the wrong password." \
+sudo nping --echo-client "BOGUS" echo.nmap.org
+
+t ECHO_17 "Test client connection to echo.nmap.org, using --no-crypto. Expected: Failure" \
+sudo nping --echo-client "a" echo.nmap.org --no-crypto
+
+t ECHO_18 "Test client connection to echo.nmap.org, NOT running as root. Expected: Failure" \
+nping --echo-client "a" echo.nmap.org
+
+t ECHO_19 "Test client connection to echo.nmap.org. No passphrase supplied." \
+nping echo.nmap.org --echo-client
+
+t ECHO_20 "Test client connection to echo.nmap.org. No target host supplied." \
+nping --echo-client "public"
+
+# Server
+t ECHO_21 "Test. Run the server normally" \
+sudo nping --echo-server "public"
+
+t ECHO_22 "Test. Run the server, but NOT as root. Expected: Failure" \
+nping --echo-server "public"
+
+t ECHO_23 "Test. Run the server with --no-crypto" \
+sudo nping --echo-server "" --no-crypto
+
+t ECHO_24 "Test. Run the server specifying the interface to use for capture ($EXISTING_NET_IFACE)" \
+sudo nping --echo-server "public" -e $EXISTING_NET_IFACE
+
+t ECHO_25 "Test. Run the server specifying an interface that does not exist." \
+sudo nping --echo-server "public" -e BOGUS_INTERFACE
+
+t ECHO_26 "Test. Run the server with --once. You should run a client in parallel (sudo nping --echo-client public --echo-port 33445 localhost -c1)" \
+sudo nping --once --echo-server "public" --echo-port 33445 -e lo &
+
+t ECHO_27 "Test. Run the server with --no-crypto. You should run a client in parallel (sudo nping --echo-client "" --no-crypto --echo-port 33446 localhost -c1)" \
+sudo nping --once --echo-server "" --no-crypto --echo-port 33446 -e lo &
+
+
+#### TIMING AND PERFORMANCE OPTIONS ####
+
+t TIMING_1 "Test inter packet delay. Specify 1sec" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay 1s -c 2
+
+t TIMING_2 "Test inter packet delay. Specify 10secs" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay 10s -c 2
+
+t TIMING_3 "Test inter packet delay. Specify 0.1 (100ms) " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay 100ms -c 2
+
+t TIMING_4 "Test inter packet delay. Specify 0.5ms" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay 100ms -c 2
+
+t TIMING_5 "Test inter packet delay specifying a bogus interval #1 (negative value). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay -10 -c2
+
+t TIMING_6 "Test inter packet delay specifying a bogus interval #2 (empty value). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay "" -c2
+
+t TIMING_7 "Test inter packet delay specifying a bogus interval #3 (no digits value). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay bogusdelay -c2
+
+t TIMING_8 "Test inter packet delay specifying a bogus interval #4 (bad time specifier). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --delay 10xy -c2
+
+t TIMING_9 "Test packet transmission rate. 1 packet per second " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 1
+
+t TIMING_10 "Test packet transmission rate. 5 packets per second " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 5
+
+t TIMING_11 "Test packet transmission rate. 99 packets per second " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 99
+
+t TIMING_12 "Test packet transmission rate. 10,000 packets per second " \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 10000
+
+t TIMING_13 "Test packet transmission rate, specifying a bougus rate #1 (0 pps). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 0
+
+t TIMING_14 "Test packet transmission rate, specifying a bougus rate #2 (negative rate). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate -1
+
+t TIMING_15 "Test packet transmission rate, specifying a bougus rate #3 (non numerical rate). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate bogusrate
+
+t TIMING_16 "Test packet transmission rate, specifying a bougus rate #4 (very large rate). Expected: error message" \
+sudo nping --icmp $TARGETS $GLOBALOPTS --icmp-type echo --rate 99999999999999999999999
+
+
+#### MISCELLANEOUS OPTIONS ####
+
+t MISC_1 "Test help display option (-h)" \
+nping -h
+
+t MISC_2 "Test help display option (--help)" \
+nping --help
+
+t MISC_3 "Test version display option (-V)" \
+nping -V
+
+t MISC_4 "Test version display option (--version)" \
+nping --version
+
+t MISC_5 "Test round number specification. Just send one packet to each target " \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -c 1
+
+t MISC_6 "Test round number specification. Send two packets to each target " \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -c 2
+
+t MISC_7 "Test round number specification. Send infinite packets [Press CTRL-C to quit]" \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -c 0
+
+t MISC_8 "Test round number specification, specifying a bogus number #1 (negative value) " \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -c -1
+
+t MISC_9 "Test round number specification, specifying a bogus number #2 (non-numeric value) " \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -c boguscount
+
+t MISC_10 "Test network interface specification. Supply an interface that exists ($EXISTING_NET_IFACE) " \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -e $EXISTING_NET_IFACE
+
+t MISC_11 "Test network interface specification. Supply an interface that does not exist. Expected: error message." \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -e bogusinterface
+
+t MISC_12 "Test network interface specification, specifying a bogus interface name (null). Expected: error message" \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn -e ""
+
+t MISC_13 "Test --hide-sent option. Expected: sent packets not shown." \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn --hide-sent
+
+t MISC_14 "Test --no-capture option. Expected: no replies captured. This is run against localhost (overriding global TARGETS) to make sure we get TCP RST packets but we don't capure them." \
+sudo nping --tcp localhost $GLOBALOPTS --flags psh,fin,syn --no-capture
+
+t MISC_15 "Force unprivileged execution. Expected: Error message complaining about TCP more requiring privileges" \
+sudo nping --tcp $TARGETS $GLOBALOPTS --flags psh,fin,syn --unprivileged
+
+t MISC_16 "Force unprivileged execution. Expected: Operation in TCP-Connect mode" \
+sudo nping $TARGETS $GLOBALOPTS --unprivileged
+
+t MISC_17 "Force privileged execution (being non-root). Expected: Error caused by a failed system call." \
+nping $TARGETS $GLOBALOPTS --privileged
+
+t MISC_18 "Force privileged execution (being root). Expected: Normal operation." \
+sudo nping $TARGETS $GLOBALOPTS --privileged
+
+# This works on normal connection but fails when working through a VPN
+t MISC_19 "Test --send-eth. Expected: Normal operation, sending packet at ethernet level." \
+sudo nping $TARGETS $GLOBALOPTS --send-eth
+
+t MISC_20 "Test --send-ip. Expected: Normal operation in Linux, etc. Possible failure on windows." \
+sudo nping $TARGETS $GLOBALOPTS --send-ip
+
+t MISC_21 "Test custom BPF filter specification. Capture all IP traffic. [You need to browse the web or generate another traffic in parallel]. Expected: ICMP traffic and any other IP traffic shown" \
+sudo nping $TARGETS $GLOBALOPTS --bpf-filter "ip" -c 30
+
+t MISC_21 "Test custom BPF filter specification. Capture only TCP. Expected: no ICMP replies shown." \
+sudo nping $TARGETS $GLOBALOPTS --bpf-filter "tcp"
+
+t MISC_22 "Test custom BPF filter specification, specifying a bogus BPF filter spec #1 (null spec). Expected: capture all traffic" \
+sudo nping $TARGETS $GLOBALOPTS --bpf-filter ""
+
+t MISC_23 "Test custom BPF filter specification, specifying a bogus BPF filter spec #2 (incorrect spec). Expected: error message." \
+sudo nping $TARGETS $GLOBALOPTS --bpf-filter "bogus_spec"
+
+
+
+
+
+#####################
+# PRINT RESULTS #
+#####################
+END_TIME=`date +"%s"`
+ELAPSED_TIME=`expr $END_TIME - $START_TIME`
+echo "[+] ============== RESULTS =============="
+echo "[+] Total tests run : $TOTAL_TESTS_RUN"
+echo "[+] Total tests PASSED : $TOTAL_TESTS_PASSED"
+echo "[+] Total tests FAILED : $TOTAL_TESTS_FAILED"
+echo "[+] List of PASSED Tests : $PASSED_TESTS"
+echo "[+] List of FAILED Tests : $FAILED_TESTS"
+echo "[+] Time elapsed : $ELAPSED_TIME seconds"
+exit
diff --git a/nping/nping-dev/valgrind_supress.txt b/nping/nping-dev/valgrind_supress.txt
new file mode 100644
index 0000000..615344c
--- /dev/null
+++ b/nping/nping-dev/valgrind_supress.txt
@@ -0,0 +1,85 @@
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+ obj:*
+ obj:*
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+ obj:*
+ obj:*
+}
+
+{
+ <SUPPRESSION_PCAP_SETSOCKOPT>
+ Memcheck:Param
+ socketcall.setsockopt(optval)
+ fun:setsockopt
+ obj:/usr/lib/libpcap.so.1.0.0
+ obj:/usr/lib/libpcap.so.1.0.0
+ fun:nsock_pcap_set_filter
+ fun:nsock_pcap_open
+ fun:_ZN9ProbeMode5startEv
+ fun:_ZN10EchoClient5startEP11NpingTargett
+ fun:main
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+}
+
+{
+ <SUPPRESSION_AES_cbc_encrypt>
+ Memcheck:Addr8
+ fun:AES_cbc_encrypt
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+ obj:*
+}
diff --git a/nping/nping.cc b/nping/nping.cc
new file mode 100644
index 0000000..d569c20
--- /dev/null
+++ b/nping/nping.cc
@@ -0,0 +1,251 @@
+
+/***************************************************************************
+ * Nping.cc -- This file contains function main() and some other general *
+ * high level functions. *
+ * *
+ ***********************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 "output.h"
+#include "NpingOps.h"
+#include "utils.h"
+#include "utils_net.h"
+#include "nsock.h"
+#include "global_structures.h"
+#include "ArgParser.h"
+#include "EchoHeader.h"
+#include "EchoClient.h"
+#include "EchoServer.h"
+#include "ProbeMode.h"
+#include "common.h"
+#include "dnet.h"
+#include "pcap.h"
+#include <signal.h>
+#include <time.h>
+
+NpingOps o;
+EchoClient ec;
+EchoServer es;
+
+int do_safe_checks();
+void test_stuff();
+void signal_handler(int signo);
+
+
+/** Main function. It basically inits Nping working environment, calls the
+ * command-line argument parser, and enters the appropriate mode (normal
+ * probe mode, echo client or echo server). */
+int main(int argc, char *argv[] ){
+
+ struct tm tm; /* For time display */
+ int err;
+ time_t now; /* Stores current time */
+ char tbuf[128]; /* Stores current time as a string */
+ ArgParser a; /* Command line argument parser */
+ unsigned long int i=0;
+ ProbeMode prob;
+ NpingTarget *t=NULL;
+
+ /* Get current time */
+ tzset();
+ now = time(NULL);
+ err = n_localtime(&now, &tm);
+ if (err)
+ nping_fatal(QT_3,"Error in localtime: %s", strerror(err));
+ o.stats.startRuntime();
+
+ /* Some run-time tests to ensure everything works as expected */
+ do_safe_checks();
+
+ /* Init a few things on Windows */
+ #ifdef WIN32
+ win_pre_init();
+ #endif
+
+ /* Register the SIGINT signal so when the users presses CTRL-C we print stats
+ * before quitting. */
+ #if HAVE_SIGNAL
+ signal(SIGINT, signal_handler);
+ #endif
+
+ /* Let's parse and validate user supplied args */
+ a.parseArguments(argc, argv);
+ #ifdef WIN32
+ // Must come after parseArguments because of --unprivileged
+ // Must come before validateOptions because it sets o.isRoot
+ win_init();
+ #endif
+ o.validateOptions();
+
+ /* ISO 8601 date/time -- http://www.cl.cam.ac.uk/~mgk25/iso-time.html */
+ if ( strftime(tbuf, sizeof(tbuf), "%Y-%m-%d %H:%M %Z", &tm) <= 0)
+ nping_fatal(QT_3,"Unable to properly format time");
+ nping_print(QT_1, "\nStarting %s %s ( %s ) at %s", NPING_NAME, NPING_VERSION, NPING_URL, tbuf);
+
+ /*If nping is called on something that doesn't take port scanning
+ * we should alert the user that their port command is going to be ignored
+ * I choose to print out a Fatal error since the scan doesn't make sense.
+ */
+ if(o.issetTargetPorts() && !o.scan_mode_uses_target_ports(o.getMode()))
+ nping_fatal(QT_3, "You cannot use -p (explicit port selection) in your current scan mode.\n(Perhaps you meant to use --tcp or --udp)");
+
+
+
+ /* Resolve and cache target specs */
+ nping_print(DBG_2,"Resolving specified targets...");
+ o.targets.processSpecs();
+ if( ((i=o.targets.getTargetsFetched())<=0) && o.getRole()!=ROLE_SERVER )
+ nping_fatal(QT_3, "Execution aborted. Nping needs at least one valid target to operate.");
+ else
+ nping_print(DBG_2,"%lu target IP address%s determined.", i, (i==1)? "":"es" );
+
+ switch( o.getRole() ){
+
+ case ROLE_NORMAL:
+ prob.start();
+ prob.cleanup();
+ break;
+
+ case ROLE_CLIENT:
+ t=o.targets.getNextTarget();
+ o.targets.rewind();
+ ec.start(t, o.getEchoPort() );
+ ec.cleanup();
+ break;
+
+ case ROLE_SERVER:
+ o.stats.startClocks();
+ es.start();
+ // Cleanup currently does nothing, but needs to be called in case
+ // it does something in the future.
+ es.cleanup(); // lgtm [cpp/useless-expression]
+ o.stats.stopClocks();
+ break;
+
+ default:
+ nping_fatal(QT_3, "Invalid role %d\n", o.getRole() );
+ break;
+ }
+
+ /* Display stats, clean up and quit */
+ o.stats.stopRuntime();
+ o.displayStatistics();
+ o.displayNpingDoneMsg();
+ o.cleanup();
+ exit(EXIT_SUCCESS);
+
+ exit(EXIT_SUCCESS);
+} /* End of main() */
+
+
+/* Things that should be guaranteed by the compiler, standard library, OS etc,
+ * but that we check just in case... */
+int do_safe_checks(){
+ if( (sizeof(u32) != 4) || (sizeof(u16) != 2) || (sizeof(u8) != 1) )
+ nping_fatal(QT_3,"Types u32, u16 and u8 do not have the correct sizes on your system.");
+ test_stuff(); /* Little function that is called quite early to test some misc stuff. */
+ return OP_SUCCESS;
+} /* End of do_safe_checks() */
+
+
+
+/** Use this function whenever you have some code that you want to test, but
+ * you don't want to bother creating a new dummy main.c file, etc. This
+ * function is called by do_safe_checks() at the beginning of nping execution.
+ * Command line arguments have not been parsed yet so even if you run nping
+ * with no arguments you will not get an error, and this function will be
+ * called. You probably want to place an exit() call at the end of your
+ * testing code so Nping does not actually continue its normal execution path
+ * but exit after your tests. */
+void test_stuff(){
+ return;
+} /* End of test_stuff() */
+
+
+/** This function is called whenever user presses CTRL-C. Basically what we
+ * do here is stop Tx and Rx clocks, stop global clock, display statistics,
+ * do a bit of cleanup and exit the program. The exit() call makes the
+ * program return EXIT_FAILURE instead of the usual EXIT_SUCCESS.
+ *
+ * TODO: Many of the things done in this function may not be safe due to
+ * reentrancy issues. Check http://seclists.org/nmap-dev/2009/q3/0596.html
+ * and http://seclists.org/nmap-dev/2009/q3/0596.html */
+void signal_handler(int signo){
+ fflush(stdout);
+ nping_print(DBG_1,"signal_handler(): Received signal %d", signo);
+ switch(signo) {
+ case SIGINT:
+ o.stats.stopTxClock();
+ o.stats.stopRxClock();
+ o.stats.stopRuntime();
+ o.displayStatistics();
+ o.displayNpingDoneMsg();
+ o.cleanup();
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+ break;
+
+ default:
+ nping_warning(QT_2, "signal_handler(): Unexpected signal received (%d). Please report a bug.", signo);
+ break;
+ }
+ fflush(stderr);
+ exit(EXIT_FAILURE);
+} /* End of signal_handler() */
diff --git a/nping/nping.h b/nping/nping.h
new file mode 100644
index 0000000..88578e4
--- /dev/null
+++ b/nping/nping.h
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Nping.h -- This file contains general defines and constants used *
+ * throughout Nping's code. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef NPING_H
+#define NPING_H 1
+
+/* Common library requirements and definitions *******************************/
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <nbase.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "../libnetutil/netutil.h"
+#include "../libnetutil/npacket.h"
+
+#ifdef HAVE_CONFIG_H
+ #include "nping_config.h"
+#else
+ #ifdef WIN32
+ #include "nping_winconfig.h"
+ #endif /* WIN32 */
+#endif /* HAVE_CONFIG_H */
+
+#ifndef WIN32
+ #include <sysexits.h>
+#endif
+
+#if HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
+
+#ifdef STDC_HEADERS
+ #include <stdlib.h>
+#else
+ void *malloc();
+ void *realloc();
+#endif
+
+#if STDC_HEADERS || HAVE_STRING_H
+ #include <string.h>
+ #if !STDC_HEADERS && HAVE_MEMORY_H
+ #include <memory.h>
+ #endif
+#endif
+
+#if HAVE_STRINGS_H
+ #include <strings.h>
+#endif
+
+#ifdef HAVE_BSTRING_H
+ #include <bstring.h>
+#endif
+
+#ifndef WIN32
+ #include <sys/wait.h>
+#endif /* !WIN32 */
+
+#if HAVE_SYS_SOCKET_H
+ #include <sys/socket.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+ #include <netinet/in.h>
+#endif
+
+#if HAVE_NETDB_H
+ #include <netdb.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+ #include <sys/time.h>
+ #include <time.h>
+#else
+ #if HAVE_SYS_TIME_H
+ #include <sys/time.h>
+ #else
+ #include <time.h>
+ # endif
+#endif
+
+#ifdef HAVE_PWD_H
+ #include <pwd.h>
+#endif
+
+#if HAVE_ARPA_INET_H
+ #include <arpa/inet.h>
+#endif
+
+#if HAVE_SYS_RESOURCE_H
+ #include <sys/resource.h>
+#endif
+
+/* Keep assert() defined for security reasons */
+#undef NDEBUG
+
+#define MAXLINE 255
+
+/* CONSTANT DEFINES ***********************************************************
+ * @warning It's better not to play with these, because the code may make *
+ * SOME assumptions like "defined value A is an integer greater than defined *
+ * value B" or "value C is an odd integer greater than 0", etc. */
+
+/* VERBOSITY LEVELS */
+/* These are the defines for Nping's internal verbosity levels. Every time
+ * you write code for Nping and you have to print something to the terminal,
+ * you'll have to choose a verbosity level. You choose a level so your message
+ * gets printed only when the user has requested messages from that level to be
+ * printed. For example, we have some calls to output functions that print out
+ * things like "%d target IPs resolved". We don't want that message to always
+ * get printed during Nping's execution. We only want it out when the user
+ * has increase the verbosity.
+ *
+ * So the thing here is that there are two things that should be taken
+ * into account:
+ * 1. The current verbosity level that user has supplied from the command line
+ * 2. The verbosity level that we supply in our print calls ( nping_print(),
+ * nping_warning(), etc...)
+ *
+ * Fortunately Nping output functions already take care of checking the
+ * current verbosity level, so programmers only have to decide which level
+ * should they specify in their output calls. If you are a programmer and
+ * you are using nping_print(), nping_warning() or nping_fatal() calls in Nping's code,
+ * you have to ask yourself: Do I want to print extra information that
+ * shouldn't be printed by default? Or am I printing important stuff like
+ * errors, etc, that should almost always be printed out?
+ *
+ * In the first case, you will call the output function using a verbosity
+ * level of VB_0 or higher. Calls that specify VB_0 are printed by default
+ * as VB_0 is the base verbosity level. Calls that specify VB_1 get printed
+ * only when the user has incremented verbosity level by at least one using
+ * option "-v". Same with VB_2 for which the users needs to have specified
+ * either "-v2" or "-v -v".
+ *
+ * In the other case, where you are printing errors etc, you have supply
+ * levels like QT_1, QT_2, QT_3 or QT_4. Those are called quiet levels.
+ * They are called quiet levels from a user point of view but they are
+ * verbose to us, programmers, because calls that supply QT_X levels almost
+ * always get printed. This is because base verbosity is VB_0 and that
+ * includes all QT_X levels. So you have to be careful with those. QT_ levels
+ * should only be used to print important stuff like fatal errors, warnings,
+ * and some basic running time information. Level QT_4 is the quiet-est one
+ * and nothing is ever printed out.
+ *
+ * Check the comments after each level definition to see how they should be
+ * used. Here are some examples:
+ *
+ * nping_fatal(QT_3,"createIPv4(): NULL pointer supplied.");
+ * nping_print(DBG_2,"Resolving specified targets...");
+ * nping_print(VB_0, "Raw packets sent: %llu ", this->stats.getSentPackets() );
+ *
+ * */
+
+/* Less verbosity */
+#define QT_4 0 /**< No output at all */
+#define QT_3 1 /**< Fatal error messages, help info, version number */
+#define QT_2 2 /**< Warnings and very limited output(just some statistics) */
+#define QT_1 3 /**< Start and timing information but no sent/recv packets */
+
+/* Base level (QT_0 is provided for consistency but should not be used) */
+#define QT_0 4 /**< Normal info (sent/recv packets, statistics...) (DEFAULT */
+#define VB_0 4 /**< Normal info (sent/recv packets, statistics...) (DEFAULT)*/
+
+/* More verbosity */
+#define VB_1 5 /**< Detailed information about times, flags, etc. */
+#define VB_2 6 /**< Very detailed information about packets, */
+#define VB_3 7 /**< Reserved for future use */
+#define VB_4 8 /**< Reserved for future use */
+
+
+
+/* DEBUGGING LEVELS */
+#define DBG_0 30 /**< No debug information at all (DEFAULT) */
+#define DBG_1 31 /**< Very important or high level debug information */
+#define DBG_2 32 /**< Important or medium level debug information */
+#define DBG_3 33 /**< Regular and low level debug information */
+#define DBG_4 34 /**< Messages only a real Nping freak would want to see */
+#define DBG_5 35 /**< Enables Nsock (and other libs) basic tracing */
+#define DBG_6 36 /**< Enables full Nsock (and other libs) tracing */
+#define DBG_7 37 /**< Reserved for future use */
+#define DBG_8 38 /**< Reserved for future use */
+#define DBG_9 39 /**< Reserved for future use */
+
+
+#define MAX_IP_PACKET_LEN 65535 /**< Max len of an IP datagram */
+#define MAX_UDP_PAYLOAD_LEN 65507 /**< Check comments in UDPHeader::setSum() */
+
+#define MAX_DEV_LEN 128 /**< Max network interface name length */
+
+#define NO_NEWLINE 0x8000 /**< Used in nping_fatal(), nping_warning() and nping_print() */
+
+/** Bit count for number parsing functions */
+#define RANGE_8_BITS 8
+#define RANGE_16_BITS 16
+#define RANGE_32_BITS 32
+#define RANGE_64_BITS 64
+
+/* Crypto Lengths */
+#define CIPHER_BLOCK_SIZE (128/8)
+#define CIPHER_KEY_LEN (128/8)
+#define MAC_KEY_LEN (128/8)
+
+/* General tunable defines **************************************************/
+#define NPING_NAME "Nping"
+#define NPING_URL "https://nmap.org/nping"
+#define NPING_VERSION "0.7.94SVN"
+
+
+#define DEFAULT_VERBOSITY VB_0
+#define DEFAULT_DEBUGGING DBG_0
+
+
+/**< Default number of probes that are sent to each target */
+#define DEFAULT_PACKET_COUNT 5
+
+/* When doing traceroute, the number of packets sent to each host must be
+ * higher because 5 is probably not enough to reach the average target on the
+ * Internet. The following paper suggests that internet hosts are no more than
+ * 30 hops apart, so setting the packet count to 48 when --traceroute is set
+ * seems like a safe choice.
+ * Cheng, J., Haining, W. and Kang, GS. (2006). Hop-Count Filtering: An
+ * Effective Defense Against Spoofed DDoS Traffic. Australian Telecommu-
+ * nication Networks & Applications Conference (ATNAC). Australia.
+ * <http://portal.acm.org/citation.cfm?id=948109.948116>
+ */
+#define TRACEROUTE_PACKET_COUNT 48
+
+#define DEFAULT_DELAY 1000 /**< Milliseconds between each probe */
+
+ /** Milliseconds Nping waits for replies after all probes have been sent */
+#define DEFAULT_WAIT_AFTER_PROBES 1000
+
+#define DEFAULT_IP_TTL 64 /**< Default IP Time To Live */
+#define DEFAULT_IP_TOS 0 /**< Default IP Type of Service */
+
+#define DEFAULT_IPv6_TTL 64 /**< Default IPv6 Hop Limit */
+#define DEFAULT_IPv6_TRAFFIC_CLASS 0x00 /**< Default IPv6 Traffic Class */
+
+
+#define DEFAULT_TCP_TARGET_PORT 80 /**< Default TCP target port */
+#define DEFAULT_UDP_TARGET_PORT 40125 /**< Default UDP target port */
+#define DEFAULT_UDP_SOURCE_PORT 53 /**< Default UDP source port */
+#define DEFAULT_TCP_WINDOW_SIZE 1480 /**< Default TCP Window size */
+
+/**< MTU used when user just supplies option -f but no MTU value */
+#define DEFAULT_MTU_FOR_FRAGMENTATION 72
+
+#define DEFAULT_ICMP_TYPE 8 /**< Default ICMP message: Echo Request */
+#define DEFAULT_ICMP_CODE 0 /**< Default ICMP code: 0 (standard) */
+
+#define DEFAULT_ICMPv6_TYPE 128 /**< Default ICMPv6 message: Echo Request */
+#define DEFAULT_ICMPv6_CODE 0 /**< Default ICMPv6 code: 0 (standard) */
+
+#define DEFAULT_ARP_OP 1 /**< Default ARP operation: OP_ARP_REQUEST */
+
+/* WARNING: This is the max length for UDP and TCP payloads. Whatever you set
+ * here, it cannot exceed the worst case:
+ * 65535 bytes - IPv6Header with options - TCP Header with options. */
+#define MAX_PAYLOAD_ALLOWED 65400
+
+/* I've tested this on a GNU/Linux 2.6.24 and I've seen that if the length
+ * of the whole IP packet is more than 16436 when using loopback interface or
+ * more than 1500 when using a normal network interface, the kernel complains
+ * and says "Message too long". This is obviously caused by the configured
+ * MTU. So the thing is that although we allow users to specify payloads up to
+ * MAX_PAYLOAD_ALLOWED bytes, when we generate random payloads, we set our
+ * on limit on 1500-20-20=1460 bytes. Let's be conservative and consider that
+ * IP packet has 40bytes of options and TCP has 20. So max length should be
+ * 1500-60-40 = 1400. */
+#define MAX_RANDOM_PAYLOAD 1400
+#define MAX_RECOMMENDED_PAYLOAD 1400
+
+
+/* Cached hosts in resolveChached() and gethostbynameCached() */
+#define MAX_CACHED_HOSTS 512
+#define MAX_CACHED_HOSTNAME_LEN 512
+
+/* (9929 because is prime as has not been assigned by IANA yet) */
+#define DEFAULT_ECHO_PORT 9929
+
+/* The echo server tries to zero any application layer data before echoing
+ * network packets. However, sometimes we may not be able to successfully
+ * parse a given packet (decide whether the packet contains application data
+ * or not), so this define specifies the amount of bytes of a packet that the
+ * server does not zero in such case. 40 bytes allows IPv4+TCP, an IPv6 header,
+ * an IPv4+UDP+12payload bytes, etc. In the case of UDP, the first 12 data bytes
+ * would be leaked. However, we should be able to parse simple IPv4-UDP packets
+ * without problem, so it should never happen. We expect to use this constant
+ * when received packets are really weird (eg. tunneled traffic, protocols we
+ * don't understand, etc. The 40 bytes are a compromise between dropping the
+ * packet but provide total protection against data leakage due to attacks to
+ * the echo server, and providing some flexibility at the risk of leaking
+ * a few bytes if an attacker is able to trick the echo server into echoing
+ * packets that were not originated by him. */
+#define PAYLOAD_ECHO_BYTES_IN_DOUBT 40
+
+#define NSOCK_INFINITE -1
+
+/* Prototypes for nping.cc shared functions */
+char *getBPFFilterString();
+
+#endif
diff --git a/nping/nping.spec b/nping/nping.spec
new file mode 100644
index 0000000..345ccee
--- /dev/null
+++ b/nping/nping.spec
@@ -0,0 +1,54 @@
+%define prerelease BETA2
+
+Name: nping
+Version: 0.1
+Release: 0.1.%{prerelease}%{?dist}
+Summary: Network packet generation, response analysis and response time measurement
+
+Group: Applications/Internet
+License: GPLv2 with exceptions
+URL: https://nmap.org/nping/
+Source0: https://nmap.org/%{name}/dist/%{name}-%{version}%{prerelease}/%{name}-%{version}%{prerelease}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+
+%description
+Nping is an open source tool for network packet generation, response analysis
+and response time measurement. Nping allows to generate network packets of a
+wide range of protocols, letting users to tune virtually any field of the
+protocol headers. While Nping can be used as a simple ping utility to detect
+active hosts, it can also be used as a raw packet generator for network stack
+stress tests, ARP poisoning, Denial of Service attacks, route tracing, etc.
+
+
+%prep
+%setup -q -n %{name}-%{version}%{prerelease}
+sed -i '/\$(STRIP)/d' Makefile.in
+# Remove exec bit from source files
+find | egrep "*\.[cc,h]" | xargs chmod a-x
+
+
+%build
+%configure
+make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%files
+%defattr(-,root,root,-)
+%doc CHANGELOG
+%{_bindir}/nping
+%{_mandir}/man1/nping.1*
+
+
+%changelog
+* Thu Sep 24 2009 Steve 'Ashcrow' Milner <me@stevemilner.org> 0.1-0.1.BETA2
+- Initial package
diff --git a/nping/nping.vcxproj b/nping/nping.vcxproj
new file mode 100644
index 0000000..6d2bedb
--- /dev/null
+++ b/nping/nping.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CDB10BBA-9085-4B9B-AC8F-BA31D3906B36}</ProjectGuid>
+ <RootNamespace>nmap</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <TypeLibraryName>.\Debug/nmap.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..;..\mswin32;../nbase;..\nsock\include;..\..\nmap-mswin32-aux\Npcap\Include;..\libdnet-stripped\include;..\..\nmap-mswin32-aux\OpenSSL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CONSOLE;BPF_MAJOR_VERSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessToFile>false</PreprocessToFile>
+ <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers>
+ <PreprocessKeepComments>false</PreprocessKeepComments>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderOutputFile>.\Debug/nmap.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <WarningLevel>Level2</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>nsock.lib;nbase.lib;libdnet-stripped.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libcrypto.lib;libssl.lib;shell32.lib;libnetutil.lib</AdditionalDependencies>
+ <OutputFile>.\Debug\nping.exe</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>..\..\nmap-mswin32-aux\Npcap\Lib;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <DelayLoadDLLs>packet.dll;wpcap.dll</DelayLoadDLLs>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Debug/nmap.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy "..\..\nmap-mswin32-aux\OpenSSL\bin\*.dll" "$(SolutionDir)\$(Configuration)\" /y </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <TypeLibraryName>.\Release/nmap.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <AdditionalIncludeDirectories>.;..;..\mswin32;../nbase;..\nsock\include;..\..\nmap-mswin32-aux\Npcap\Include;..\libdnet-stripped\include;..\..\nmap-mswin32-aux\OpenSSL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CONSOLE;BPF_MAJOR_VERSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <PrecompiledHeaderOutputFile>.\Release/nping.pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+ <ObjectFileName>.\Release/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <CompileAs>CompileAsCpp</CompileAs>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>nsock.lib;nbase.lib;libdnet-stripped.lib;ws2_32.lib;IPHlpAPI.Lib;wpcap.lib;packet.lib;advapi32.lib;libcrypto.lib;libssl.lib;shell32.lib;libnetutil.lib</AdditionalDependencies>
+ <OutputFile>.\Release/nping.exe</OutputFile>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>..\..\nmap-mswin32-aux\Npcap\Lib;..\nsock;..\nbase;..\libdnet-stripped;../libnetutil;..\..\nmap-mswin32-aux\OpenSSL\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <DelayLoadDLLs>packet.dll;wpcap.dll</DelayLoadDLLs>
+ <ProgramDatabaseFile>.\Release/nping.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <RandomizedBaseAddress>true</RandomizedBaseAddress>
+ <DataExecutionPrevention>true</DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy "..\..\nmap-mswin32-aux\OpenSSL\bin\*.dll" "$(SolutionDir)\$(Configuration)\" /y </Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="ArgParser.cc" />
+ <ClCompile Include="common.cc" />
+ <ClCompile Include="common_modified.cc" />
+ <ClCompile Include="Crypto.cc" />
+ <ClCompile Include="EchoClient.cc" />
+ <ClCompile Include="EchoHeader.cc" />
+ <ClCompile Include="EchoServer.cc" />
+ <ClCompile Include="NEPContext.cc" />
+ <ClCompile Include="nping.cc" />
+ <ClCompile Include="NpingOps.cc" />
+ <ClCompile Include="NpingTarget.cc" />
+ <ClCompile Include="NpingTargets.cc" />
+ <ClCompile Include="output.cc" />
+ <ClCompile Include="ProbeMode.cc" />
+ <ClCompile Include="stats.cc" />
+ <ClCompile Include="utils.cc" />
+ <ClCompile Include="utils_net.cc" />
+ <ClCompile Include="winfix.cc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="ArgParser.h" />
+ <ClInclude Include="common.h" />
+ <ClInclude Include="common_modified.h" />
+ <ClInclude Include="Crypto.h" />
+ <ClInclude Include="EchoClient.h" />
+ <ClInclude Include="EchoHeader.h" />
+ <ClInclude Include="EchoServer.h" />
+ <ClInclude Include="global_structures.h" />
+ <ClInclude Include="NEPContext.h" />
+ <ClInclude Include="nping.h" />
+ <ClInclude Include="NpingOps.h" />
+ <ClInclude Include="NpingTarget.h" />
+ <ClInclude Include="NpingTargets.h" />
+ <ClInclude Include="output.h" />
+ <ClInclude Include="ProbeMode.h" />
+ <ClInclude Include="stats.h" />
+ <ClInclude Include="utils.h" />
+ <ClInclude Include="utils_net.h" />
+ <ClInclude Include="winfix.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\libdnet-stripped\libdnet-stripped.vcxproj">
+ <Project>{5328e0be-bc0a-4c2a-8cb9-ce00b61b9c4c}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="..\libnetutil\libnetutil.vcxproj">
+ <Project>{99157c3f-39f6-4663-99d7-1d9c1484494e}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="..\nbase\nbase.vcxproj">
+ <Project>{b630c8f7-3138-43e8-89ed-78742fa2ac5f}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ <ProjectReference Include="..\nsock\nsock.vcxproj">
+ <Project>{f8d6d1e3-d4ea-402c-98aa-168e5309baf4}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/nping/nping_config.h.in b/nping/nping_config.h.in
new file mode 100644
index 0000000..9b6f971
--- /dev/null
+++ b/nping/nping_config.h.in
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * nping_config.h.in -- Autoconf uses this template, combined with the *
+ * configure script knowledge about system capabilities, to build this *
+ * include file that lets nmap better understand system particulars. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* $Id: $ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#undef PCAP_TIMEOUT_IGNORED
+
+#undef HAVE_STRUCT_IP
+
+#undef HAVE_STRUCT_ICMP
+
+#undef HAVE_IP_IP_SUM
+
+#undef HAVE_SIGNAL
+
+#undef inline
+
+#undef STDC_HEADERS
+
+#undef HAVE_UNISTD_H
+
+#undef HAVE_STRING_H
+
+#undef HAVE_STRINGS_H
+
+#undef HAVE_PWD_H
+
+#undef HAVE_BSTRING_H
+
+#undef WORDS_BIGENDIAN
+
+#undef HAVE_MEMORY_H
+
+#undef HAVE_STRERROR
+
+#undef HAVE_SYS_SOCKIO_H
+
+#undef HAVE_SYS_STAT_H
+
+#undef HAVE_FCNTL_H
+
+#undef HAVE_TERMIOS_H
+
+#undef BSD_NETWORKING
+
+#undef IN_ADDR_DEEPSTRUCT
+
+#undef HAVE_SOCKADDR_SA_LEN
+
+#undef HAVE_SOCKADDR_IN_SIN_LEN
+
+#undef HAVE_SOCKADDR_IN6_SIN6_LEN
+
+#undef HAVE_NETINET_IF_ETHER_H
+
+#undef HAVE_OPENSSL
+
+#undef STUPID_SOLARIS_CHECKSUM_BUG
+
+#undef SPRINTF_RETURNS_STRING
+
+#undef TIME_WITH_SYS_TIME
+#undef HAVE_SYS_TIME_H
+
+#undef recvfrom6_t
+
+#undef NEED_USLEEP_PROTO
+#undef NEED_GETHOSTNAME_PROTO
+
+#ifdef NEED_USLEEP_PROTO
+#ifdef __cplusplus
+extern "C" int usleep (unsigned int);
+#endif
+#endif
+
+#ifdef NEED_GETHOSTNAME_PROTO
+#ifdef __cplusplus
+extern "C" int gethostname (char *, unsigned int);
+#endif
+#endif
+
+#undef DEC
+#undef LINUX
+#undef FREEBSD
+#undef OPENBSD
+#undef SOLARIS
+#undef SUNOS
+#undef BSDI
+#undef IRIX
+#undef HPUX
+#undef NETBSD
+#undef MACOSX
+
+#endif /* CONFIG_H */
diff --git a/nping/nping_winconfig.h b/nping/nping_winconfig.h
new file mode 100644
index 0000000..f623db0
--- /dev/null
+++ b/nping/nping_winconfig.h
@@ -0,0 +1,90 @@
+
+/***************************************************************************
+ * nping_winconfig.h -- Since the Windows port is currently eschewing *
+ * autoconf-style configure scripts, nping_winconfig.h contains the *
+ * platform-specific definitions for Windows and is used as a replacement *
+ * for config.h *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* $Id: nmap_winconfig.h 12955 2009-04-15 00:37:03Z fyodor $ */
+
+#ifndef NPING_WINCONFIG_H
+#define NPING_WINCONFIG_H
+/* Without this, Windows will give us all sorts of crap about using functions
+ like strcpy() even if they are done safely */
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+//#ifndef NPING_NAME
+// #define NPING_NAME "Nmap"
+// #define NPING_URL "https://nmap.org"
+//#endif
+
+#ifdef NPING_PLATFORM
+ #undef NPING_PLATFORM
+#endif
+
+#define NPING_PLATFORM "i686-pc-windows-windows"
+
+#define HAVE_OPENSSL 1
+#define HAVE_SSL_SET_TLSEXT_HOST_NAME 1
+/* Apparently __func__ isn't yet supported */
+#define __func__ __FUNCTION__
+typedef unsigned __int32 u_int32_t;
+typedef unsigned __int16 u_int16_t;
+typedef unsigned __int8 u_int8_t;
+
+#endif /* NPING_WINCONFIG_H */
diff --git a/nping/output.cc b/nping/output.cc
new file mode 100644
index 0000000..2537216
--- /dev/null
+++ b/nping/output.cc
@@ -0,0 +1,244 @@
+
+/***************************************************************************
+ * output.h -- Some simple error and regular message output functions. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* This file contains the functions that are used to print stuff to stout or
+ * stderr in Nping. All of them take a "level" and then a variable list of
+ * argument. The "level" parameter states which is the minimum level of
+ * verbosity that should NpingOps::vb contain to print the message to stdout.
+ * For a more detailed explanation, check documentation of verbosity and
+ * debugging levels in nping.h */
+
+#include "NpingOps.h"
+#include "output.h"
+
+extern NpingOps o;
+
+#ifdef WIN32
+#include <windows.h>
+#endif /* WIN32 */
+
+
+/** Print fatal error messages to stderr and then exits.
+ * @warning This function does not return because it calls exit() */
+int nping_fatal(int level, const char *str, ...) {
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ memset(errstr,0, MAX_ERR_STR_LEN);
+
+ fflush(stdout);
+ fflush(stderr);
+
+ int current_vb_level= o.getVerbosity();
+ int current_dbg_level= o.getDebugging();
+
+ /* If supplied level is more than current level, do nothing */
+ if( level>=QT_4 && level<=VB_4 && level>current_vb_level )
+ return OP_SUCCESS;
+ if( level>=DBG_0 && level<=DBG_9 && level>current_dbg_level )
+ return OP_SUCCESS;
+
+
+ if ( (level>=QT_3 && level<=VB_4) || (level>=DBG_1 && level<=DBG_9) ){
+ va_start(list, str);
+ vfprintf(stderr, str, list);
+ va_end(list);
+ fprintf(stderr,"\n"); /* Print to stderr */
+ }
+
+ exit(EXIT_FAILURE);
+ return OP_SUCCESS;
+} /* End of nping_fatal() */
+
+
+/** Prints recoverable error message to stderr and returns. This function
+ * inserts one \n newline automatically in every call. To avoid that
+ * behaviour it is possible to OR the supplied level with the constant
+ * NO_NEWLINE like this:
+ *
+ * nping_warning(QT_2|NO_NEWLINE, "I don't want newlines in this string");
+ * */
+int nping_warning(int level, const char *str, ...) {
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ bool skipnewline=false;
+ memset(errstr,0, MAX_ERR_STR_LEN);
+
+ fflush(stdout);
+ fflush(stderr);
+
+ int current_vb_level= o.getVerbosity();
+ int current_dbg_level= o.getDebugging();
+
+ /* Determine if caller requested that we don't print a newline character */
+ if ( level & NO_NEWLINE ){
+ level ^= NO_NEWLINE; /* Unset the flag restoring the original level */
+ skipnewline=true;
+ }
+
+ /* If supplied level is more than current level, do nothing */
+ if( level>=QT_4 && level<=VB_4 && level>current_vb_level )
+ return OP_SUCCESS;
+ if( level>=DBG_0 && level<=DBG_9 && level>current_dbg_level )
+ return OP_SUCCESS;
+
+ /* Otherwise, print the info to stderr*/
+ if ( (level>=QT_3 && level<=VB_4) || (level>=DBG_1 && level<=DBG_9) ){
+ va_start(list, str);
+ vfprintf(stderr, str, list); /* Print to stderr */
+ va_end(list);
+ if( !skipnewline )
+ fprintf(stderr,"\n");
+ }
+ return OP_SUCCESS;
+} /* End of nping_warning() */
+
+
+/** Print regular messages to stdout. This function inserts one \n newline
+ * automatically in every call. To avoid that behaviour it is possible to
+ * OR the supplied level with constant NO_NEWLINE like this:
+ *
+ * nping_print(VB_2|NO_NEWLINE, "I don't want newlines in this string");
+ * */
+int nping_print(int level, const char *str, ...){
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ bool skipnewline=false;
+ memset(errstr,0, MAX_ERR_STR_LEN);
+
+ fflush(stdout);
+
+ int current_vb_level= o.getVerbosity();
+ int current_dbg_level= o.getDebugging();
+
+ /* Determine if caller requested that we don't print a newline character */
+ if ( level & NO_NEWLINE ){
+ level ^= NO_NEWLINE; /* Unset the flag restoring the original level */
+ skipnewline=true;
+ }
+
+ /* If supplied level is more than current level, do nothing */
+ if( level>=QT_4 && level<=VB_4 && level>current_vb_level )
+ return OP_SUCCESS;
+ if( level>=DBG_0 && level<=DBG_9 && level>current_dbg_level )
+ return OP_SUCCESS;
+
+ /* Otherwise, print the info to stderr*/
+ if ( (level>=QT_3 && level<=VB_4) || (level>=DBG_1 && level<=DBG_9) ){
+ va_start(list, str);
+ vfprintf(stdout, str, list); /* Print to stderr */
+ va_end(list);
+ if( !skipnewline )
+ fprintf(stdout,"\n");
+ }
+ return OP_SUCCESS;
+} /* End of nping_print() */
+
+
+/*****************************************************************************/
+/* The following functions are provided only for compatibility with some */
+/* code from Nmap. They should NOT be used in any new piece of code unless */
+/* the code you are writing needs to be shared with nmap. */
+/*****************************************************************************/
+/** Print fatal error messages to stderr and then exits.
+ * @warning This function does not return because it calls exit() */
+int fatal(const char *str, ...) {
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ memset(errstr,0, MAX_ERR_STR_LEN);
+ va_start(list, str);
+ fflush(stdout);
+ /* Print error msg to strerr */
+ vfprintf(stderr, str, list);
+ fprintf(stderr,"\n");
+ va_end(list);
+ exit(EXIT_FAILURE);
+ return OP_SUCCESS;
+} /* End of fatal() */
+
+
+/** Print error messages to stderr and then return. */
+int error(const char *str, ...) {
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ memset(errstr,0, MAX_ERR_STR_LEN);
+ va_start(list, str);
+ fflush(stdout);
+ /* Print error msg to strerr */
+ vfprintf(stderr, str, list);
+ fprintf(stderr,"\n");
+ va_end(list);
+ return OP_SUCCESS;
+} /* End of error() */
+
+
+/** Needed by struct interface_info *getinterfaces(int *howmany) in common.h
+ * (taken originally from nmap tcpip.cc */
+int pfatal(const char *str, ...) {
+ va_list list;
+ char errstr[MAX_ERR_STR_LEN];
+ memset(errstr,0, MAX_ERR_STR_LEN);
+ va_start(list, str);
+ fflush(stdout);
+ /* Print error msg to strerr */
+ vfprintf(stderr, str, list);
+ fprintf(stderr,"\n");
+ va_end(list);
+ exit(EXIT_FAILURE);
+ return OP_SUCCESS;
+} /* End of fatal() */
diff --git a/nping/output.h b/nping/output.h
new file mode 100644
index 0000000..83c0de4
--- /dev/null
+++ b/nping/output.h
@@ -0,0 +1,114 @@
+
+/***************************************************************************
+ * output.h -- Some simple error and regular message output functions. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+#ifdef HAVE_CONFIG_H
+#include "nping_config.h"
+#else
+#ifdef WIN32
+#include "nping_winconfig.h"
+#endif /* WIN32 */
+#endif /* HAVE_CONFIG_H */
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define MAX_ERR_STR_LEN 1024 /* Max length of an error message */
+#define MAX_OUTPUT_STR_LEN 2048 /* Max length of an output message */
+
+/* For backwards compatibility with Nmap's code */
+int fatal(const char *str, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+int error(const char *str, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+/* For backwards compatibility with Nmap's code */
+int pfatal(const char *str, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+int nping_fatal(int level, const char *str, ...)
+ __attribute__((format(printf, 2, 3)));
+
+int nping_warning(int level, const char *str, ...)
+ __attribute__((format(printf, 2, 3)));
+
+int nping_print(int level, const char *str, ...)
+ __attribute__((format(printf, 2, 3)));
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NPING_ERROR_H */
+
diff --git a/nping/stats.cc b/nping/stats.cc
new file mode 100644
index 0000000..d2a9276
--- /dev/null
+++ b/nping/stats.cc
@@ -0,0 +1,390 @@
+
+/***************************************************************************
+ * PacketStats.cc -- The PacketStats class handles packet statistics. It *
+ * is intended to keep track of the number of packets and bytes sent and *
+ * received, keep track of start and finish times, etc. *
+ * *
+ ***********************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 "stats.h"
+#include "NpingOps.h"
+#include "output.h"
+
+
+
+/*****************************************************************************/
+/* Implementation of NpingTimer class. */
+/*****************************************************************************/
+
+NpingTimer::NpingTimer(){
+ this->reset();
+}
+
+NpingTimer::~NpingTimer(){
+
+}
+
+void NpingTimer::reset(){
+ this->start_tv.tv_sec=0;
+ this->start_tv.tv_usec=0;
+ this->stop_tv.tv_sec=0;
+ this->stop_tv.tv_usec=0;
+}
+
+
+int NpingTimer::start(){
+ if( timeval_set(&start_tv) || timeval_set(&stop_tv) )
+ return OP_FAILURE;
+ gettimeofday(&start_tv, NULL);
+ return OP_SUCCESS;
+}
+
+
+int NpingTimer::stop(){
+ if( !timeval_set(&start_tv) || timeval_set(&stop_tv) )
+ return OP_FAILURE;
+ gettimeofday(&stop_tv, NULL);
+ return OP_SUCCESS;
+}
+
+
+double NpingTimer::elapsed(struct timeval *now){
+ struct timeval tv;
+ const struct timeval *end_tv=NULL;
+ /* If for some reason the clock has not been started,
+ * just return 0 seconds elapsed. */
+ if(!timeval_set(&start_tv)){
+ return 0.0;
+ }
+ /* If the caller supplied a time, use it */
+ if(now!=NULL){
+ end_tv=now;
+ /* If the clock has been stopped already, use the stop time */
+ }else if(timeval_set(&stop_tv)){
+ end_tv = &stop_tv;
+ }else{
+ gettimeofday(&tv, NULL);
+ end_tv = &tv;
+ }
+ return TIMEVAL_FSEC_SUBTRACT(*end_tv, start_tv);
+}
+
+
+bool NpingTimer::is_started(){
+ return timeval_set(&this->start_tv);
+}
+
+
+bool NpingTimer::is_stopped(){
+ return timeval_set(&this->stop_tv);
+}
+
+
+/* Returns true if tv has been initialized; i.e., its members are not all zero. */
+bool NpingTimer::timeval_set(const struct timeval *tv) {
+ return (tv->tv_sec != 0 || tv->tv_usec != 0);
+}
+
+
+
+/*****************************************************************************/
+/* Implementation of NpingStats class. */
+/*****************************************************************************/
+
+NpingStats::NpingStats(){
+ this->reset();
+}
+
+
+NpingStats::~NpingStats(){
+
+}
+
+
+void NpingStats::reset(){
+ this->packets_sent=0;
+ this->packets_received=0;
+ this->packets_echoed=0;
+
+ this->bytes_sent=0;
+ this->bytes_received=0;
+ this->bytes_echoed=0;
+
+ this->echo_clients_served=0;
+
+ this->tx_timer.reset();
+ this->rx_timer.reset();
+ this->run_timer.reset();
+
+} /* End of reset() */
+
+
+/** Updates packet and byte count for transmitted packets. */
+int NpingStats::addSentPacket(u32 len){
+ this->packets_sent++;
+ this->bytes_sent+=len;
+ return OP_SUCCESS;
+} /* End of addSentPacket() */
+
+
+/** Updates packet and byte count for received packets. */
+int NpingStats::addRecvPacket(u32 len){
+ this->packets_received++;
+ this->bytes_received+=len;
+ return OP_SUCCESS;
+} /* End of addRecvPacket() */
+
+
+/** Updates packet and byte count for echoed packets. */
+int NpingStats::addEchoedPacket(u32 len){
+ this->packets_echoed++;
+ this->bytes_echoed+=len;
+ return OP_SUCCESS;
+} /* End of addEchoedPacket() */
+
+
+/** Updates count for echo clients served by the echo server. */
+int NpingStats::addEchoClientServed(){
+ this->echo_clients_served++;
+ return OP_SUCCESS;
+} /* End of addEchoClientServed() */
+
+
+int NpingStats::startClocks(){
+ this->startTxClock();
+ this->startRxClock();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::stopClocks(){
+ this->stopTxClock();
+ this->stopRxClock();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::startTxClock(){
+ this->tx_timer.start();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::stopTxClock(){
+ this->tx_timer.stop();
+ return OP_SUCCESS;
+}
+
+int NpingStats::startRxClock(){
+ this->rx_timer.start();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::stopRxClock(){
+ this->rx_timer.stop();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::startRuntime(){
+ this->run_timer.start();
+ return OP_SUCCESS;
+}
+
+
+int NpingStats::stopRuntime(){
+ this->run_timer.start();
+ return OP_SUCCESS;
+}
+
+
+double NpingStats::elapsedTx(){
+ return this->tx_timer.elapsed();
+}
+
+
+double NpingStats::elapsedRx(){
+ return this->rx_timer.elapsed();
+}
+
+
+double NpingStats::elapsedRuntime(struct timeval *now){
+ return this->run_timer.elapsed(now);
+}
+
+
+u64_t NpingStats::getSentPackets(){
+ return this->packets_sent;
+} /* End of getSentPackets() */
+
+
+u64_t NpingStats::getSentBytes(){
+ return this->bytes_sent;
+} /* End of getSentBytes() */
+
+
+u64_t NpingStats::getRecvPackets(){
+ return this->packets_received;
+} /* End of getRecvPackets() */
+
+
+u64_t NpingStats::getRecvBytes(){
+ return this->bytes_received;
+} /* End of getRecvBytes() */
+
+
+u64_t NpingStats::getEchoedPackets(){
+ return this->packets_echoed;
+} /* End of getEchoedPackets() */
+
+
+u64_t NpingStats::getEchoedBytes(){
+ return this->bytes_echoed;
+} /* End of getEchoedBytes() */
+
+u32 NpingStats::getEchoClientsServed(){
+ return this->echo_clients_served;
+} /* End of getEchoClientsServed() */
+
+
+u64_t NpingStats::getLostPackets(){
+ if(this->packets_sent <= this->packets_received)
+ return 0;
+ else
+ return this->packets_sent - this->packets_received;
+} /* End of getLostPackets() */
+
+
+double NpingStats::getLostPacketPercentage(){
+ u32 pkt_rcvd=this->packets_received;
+ u32 pkt_sent=this->packets_sent;
+ u32 pkt_lost=(pkt_rcvd>=pkt_sent) ? 0 : (u32)(pkt_sent-pkt_rcvd);
+ /* Only compute percentage if we actually sent packets, don't do divisions
+ * by zero! (this could happen when user presses CTRL-C and we print the
+ * stats */
+ double percentlost=0.0;
+ if( pkt_lost!=0 && pkt_sent!=0)
+ percentlost=((double)pkt_lost)/((double)pkt_sent);
+ return percentlost;
+} /* End of getLostPacketPercentage() */
+
+
+double NpingStats::getLostPacketPercentage100(){
+ return this->getLostPacketPercentage()*100;
+} /* End of getLostPacketPercentage100() */
+
+
+u64_t NpingStats::getUnmatchedPackets(){
+ if(this->packets_received <= this->packets_echoed)
+ return 0;
+ else
+ return this->packets_received - this->packets_echoed;
+} /* End of getUnmatchedPackets() */
+
+
+double NpingStats::getUnmatchedPacketPercentage(){
+ u32 pkt_captured=this->packets_received;
+ u32 pkt_echoed=this->packets_echoed;
+ u32 pkt_unmatched=(pkt_captured<=pkt_echoed) ? 0 : (u32)(pkt_captured-pkt_echoed);
+ double percentunmatched=0.0;
+ if( pkt_unmatched!=0 && pkt_captured!=0)
+ percentunmatched=((double)pkt_unmatched)/((double)pkt_captured);
+ return percentunmatched;
+} /* End of getUnmatchedPacketPercentage() */
+
+
+double NpingStats::getUnmatchedPacketPercentage100(){
+ return this->getUnmatchedPacketPercentage()*100;
+} /* End of getUnmatchedPacketPercentage100() */
+
+
+double NpingStats::getOverallTxPacketRate(){
+ double elapsed = this->tx_timer.elapsed();
+ if(elapsed <= 0.0)
+ return 0.0;
+ else
+ return this->packets_sent / elapsed;
+}
+
+
+double NpingStats::getOverallTxByteRate(){
+ double elapsed = this->tx_timer.elapsed();
+ if(elapsed <= 0.0)
+ return 0.0;
+ else
+ return this->bytes_sent / elapsed;
+}
+
+
+double NpingStats::getOverallRxPacketRate(){
+ double elapsed = this->rx_timer.elapsed();
+ if(elapsed <= 0.0)
+ return 0.0;
+ else
+ return this->packets_received / elapsed;
+}
+
+
+double NpingStats::getOverallRxByteRate(){
+ double elapsed = this->rx_timer.elapsed();
+ if(elapsed <= 0.0)
+ return 0.0;
+ else
+ return this->bytes_received / elapsed;
+}
+
diff --git a/nping/stats.h b/nping/stats.h
new file mode 100644
index 0000000..0ba2cbe
--- /dev/null
+++ b/nping/stats.h
@@ -0,0 +1,210 @@
+
+/***************************************************************************
+ * PacketStats.h -- The PacketStats class handles packet statistics. It is *
+ * intended to keep track of the number of packets and bytes sent and *
+ * received, keep track of start and finish times, etc. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+#ifndef __STATS_H__
+#define __STATS_H__ 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include "nping.h"
+
+#ifndef WIN32
+#include <sys/types.h>
+
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#include <sys/mman.h>
+#include "nping_config.h"
+#endif
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+/* Make sure we define a 64bit integer type */
+#ifndef u64_t
+ #if WIN32
+ typedef unsigned __int64 u64_t;
+ #else
+ typedef unsigned long long u64_t;
+ #endif
+#endif
+
+/* Timeval subtraction in microseconds */
+#define TIMEVAL_SUBTRACT(a,b) (((a).tv_sec - (b).tv_sec) * 1000000 + (a).tv_usec - (b).tv_usec)
+/* Timeval subtract in milliseconds */
+#define TIMEVAL_MSEC_SUBTRACT(a,b) ((((a).tv_sec - (b).tv_sec) * 1000) + ((a).tv_usec - (b).tv_usec) / 1000)
+/* Timeval subtract in seconds; truncate towards zero */
+#define TIMEVAL_SEC_SUBTRACT(a,b) ((a).tv_sec - (b).tv_sec + (((a).tv_usec < (b).tv_usec) ? - 1 : 0))
+/* Timeval subtract in fractional seconds; convert to float */
+#define TIMEVAL_FSEC_SUBTRACT(a,b) ((a).tv_sec - (b).tv_sec + (((a).tv_usec - (b).tv_usec)/1000000.0))
+
+
+class NpingTimer {
+
+ private:
+ struct timeval start_tv;
+ struct timeval stop_tv;
+
+ public:
+ NpingTimer();
+ ~NpingTimer();
+ void reset();
+ int start();
+ int stop();
+ double elapsed(struct timeval *now=NULL);
+ bool is_started();
+ bool is_stopped();
+
+
+ private:
+ bool timeval_set(const struct timeval *tv);
+};
+
+
+class NpingStats {
+
+ private:
+ u64_t packets_sent;
+ u64_t packets_received;
+ u64_t packets_echoed;
+
+ u64_t bytes_sent;
+ u64_t bytes_received;
+ u64_t bytes_echoed;
+
+ u32 echo_clients_served;
+
+ NpingTimer tx_timer; /* Timer for packet transmission. */
+ NpingTimer rx_timer; /* Timer for packet reception. */
+ NpingTimer run_timer; /* Timer to measure Nping execution time. */
+
+ public:
+ NpingStats();
+ ~NpingStats();
+
+ void reset();
+
+ int addSentPacket(u32 len);
+ int addRecvPacket(u32 len);
+ int addEchoedPacket(u32 len);
+ int addEchoClientServed();
+
+ int startClocks();
+ int stopClocks();
+
+ int startTxClock();
+ int stopTxClock();
+
+ int startRxClock();
+ int stopRxClock();
+
+ int startRuntime();
+ int stopRuntime();
+
+ double elapsedTx();
+ double elapsedRx();
+ double elapsedRuntime(struct timeval *now=NULL);
+
+ u64_t getSentPackets();
+ u64_t getSentBytes();
+
+ u64_t getRecvPackets();
+ u64_t getRecvBytes();
+
+ u64_t getEchoedPackets();
+ u64_t getEchoedBytes();
+ u32 getEchoClientsServed();
+
+ u64_t getLostPackets();
+ double getLostPacketPercentage();
+ double getLostPacketPercentage100();
+
+ u64_t getUnmatchedPackets();
+ double getUnmatchedPacketPercentage();
+ double getUnmatchedPacketPercentage100();
+
+ double getOverallTxPacketRate();
+ double getOverallTxByteRate();
+
+ double getOverallRxPacketRate();
+ double getOverallRxByteRate();
+
+};
+
+
+#endif /* __STATS_H__ */
diff --git a/nping/utils.cc b/nping/utils.cc
new file mode 100644
index 0000000..61fa7e2
--- /dev/null
+++ b/nping/utils.cc
@@ -0,0 +1,438 @@
+
+/***************************************************************************
+ * utils.cc -- Miscellaneous utils that didn't fit into any of the other *
+ * source files. *
+ * *
+ ***********************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 "utils.h"
+#include "NpingOps.h"
+#include "global_structures.h"
+#include "output.h"
+#include "nbase.h"
+#include "pcap.h"
+#include "dnet.h"
+
+#include <errno.h>
+#include <vector>
+
+extern NpingOps o;
+
+
+/** Returns true if "source" contains at least one instance of "substring" */
+bool contains(const char *source, const char *substring){
+ if(source==NULL || substring==NULL )
+ nping_fatal(QT_3,"contains(): NULL value received.");
+ if( strcasestr(source, substring) )
+ return true;
+ else
+ return false;
+} /* End of contains() */
+
+
+/** Returns true if the supplied string matches "rand" or "random" (not case
+ * sensitive)*/
+bool meansRandom(const char *source){
+ if(source==NULL)
+ nping_fatal(QT_3,"meansRandom(): NULL value received.");
+ if( !strcasecmp(source, "rand") || !strcasecmp(source, "random") )
+ return true;
+ else
+ return false;
+} /* End of meansRandom() */
+
+
+/** Returns true if source contains the representation of a number >= min and
+ * <= max in the given base (with nothing following). */
+static bool isNumber_range(const char *source, int base,
+ unsigned long min, unsigned long max){
+ unsigned long ul;
+ char *tail;
+ errno = 0;
+ ul = strtoul(source, &tail, base);
+ if (errno != 0 || tail == source || *tail != '\0')
+ return false;
+
+ return ul >= min && ul <= max;
+}
+
+
+/** Returns true if "source" is a number in the supplied base that can fit
+ * into a 8-bit var */
+bool isNumber_u8(const char *source, int base){
+ return isNumber_range(source, base, 0UL, 0xFFUL);
+}
+
+
+/** Returns true if "source" is a number in the supplied base that can fit
+ * into a 16-bit var */
+bool isNumber_u16(const char *source, int base){
+ return isNumber_range(source, base, 0UL, 0xFFFFUL);
+}
+
+
+/** Returns true if "source" is a number in the supplied base that can fit
+ * into a 32-bit var */
+bool isNumber_u32(const char *source, int base){
+ return isNumber_range(source, base, 0UL, 0xFFFFFFFFUL);
+}
+
+
+/** Returns a buffer that contains the binary equivalent to the supplied
+ * hex spec or NULL in case of error.
+ * @warning Returned pointer points to a static buffer that subsequent calls
+ * will overwrite. */
+u8 *parseBufferSpec(char *str, size_t *outlen){
+ char auxbuff[1024];
+ static u8 dst[16384];
+ size_t dstlen=16384;
+ unsigned int i=0, j=0;
+ char *start=NULL;
+
+ if(str==NULL || outlen==NULL)
+ return NULL;
+ /* This catches the empty string possibility "" */
+ if(strlen(str) == 0)
+ return NULL;
+ else
+ memset(auxbuff,0,1024);
+
+ /* String should be treated as a hex number in this format: 0xAABBCCDDEE...
+ * We process it the way it is specified, we don't perform byte order
+ * conversions so if the users says 0x00AA we write dst[0]=0x00, dst[1]==0xAA
+ * no matter the endianness of the host system. */
+ if( !strncmp("0x", str, 2) ){
+ /* This catches the case of an empty "0x" */
+ if(strlen(str) == 2)
+ return NULL;
+ start=str+2;
+ }
+ /* String should be treated as list of hex char in this format: \x00\xFF\x0A*/
+ else if( !strncmp("\\x", str, 2) ){
+ /* This catches the case of an empty "\x" */
+ if(strlen(str) == 2)
+ return NULL;
+ /* Copy all interesting bytes to an aux array, discard "\x" */
+ for(i=0; i<strlen(str) && j<1023; i++){
+ if( str[i]!='\\' && str[i]!='x' && str[i]!='X')
+ auxbuff[j++]=str[i];
+ }
+ auxbuff[j]='\0'; /* NULL terminate the string */
+ start=auxbuff;
+ }
+ /* It must be a hex number in this format: AABBCCDDEE (without 0x or \x) */
+ else{
+ start=str;
+ }
+
+ /*OK, here we should have "start" pointing to the beginning of a string
+ * in the format AABBCCDDEE... */
+ /* Check if all we've got are hex chars */
+ for(i=0; i<strlen(start); i++){
+ if( !isxdigit(start[i]) )
+ return NULL;
+ }
+ /* Check if we have an even number of hex chars */
+ if( strlen(start)%2 != 0 )
+ return NULL;
+
+ /* We are ready to parse this string */
+ for(i=0, j=0; j<dstlen && i<strlen(start)-1; i+=2){
+ char twobytes[3];
+ twobytes[0]=start[i];
+ twobytes[1]=start[i+1];
+ twobytes[2]='\0';
+ dst[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+ /* Store final length */
+ *outlen=j;
+ return dst;
+} /* End of parseBufferSpec*/
+
+
+/* Determines how many bits "a" and "b" have in common until they differ. For
+ * example, if A is 11111111 and B is 11111101, this function will return 6,
+ * as the first 6 bits of A and B are equal.
+ * @param len is the length in BYTES of "a" and "b".
+ *
+ * TODO: Check if this function is endian-safe.
+ */
+int bitcmp(u8 *a, u8*b, int len){
+ int equal=0;
+ int firstpart=len-1;
+
+ if(a==NULL || b==NULL || len<=0)
+ return -1;
+
+ for(int i=0; i<len; i++){
+ if(a[i]!=b[i]){
+ firstpart=i;
+ break;
+ }
+ }
+
+ /* Do all bits match? */
+ if(firstpart==len)
+ return len*8;
+ else
+ equal=firstpart*8;
+
+ /* Take the first byte that didn't match completely and determine how
+ * many bits they have in common until they differ */
+ for(int i=0, j=0x80; i<8; i++, j/=2){
+ if( (a[firstpart] & j) == (b[firstpart] & j) )
+ equal++;
+ else
+ return equal;
+ }
+ return equal;
+} /* End of bitcmp() */
+
+
+
+/** Removes every instance of the character stored in parameter "c" in the
+ * supplied string.
+ * @warning the supplied buffer is modified by this function. */
+int removechar(char *string, char c){
+ size_t i=0, j=0;
+ if(string==NULL)
+ return OP_FAILURE;
+
+ while(string[j] != '\0') {
+ if(string[j] != c)
+ string[i++] = string[j];
+ j++;
+ }
+ string[i] = '\0';
+ return OP_SUCCESS;
+} /* End of removechar() */
+
+
+
+/** Removes every instance of ':' in the supplied string.
+ * @warning the supplied buffer is modified by this function. Whenever a
+ * colon is found, the rest of the string is moved one position to the left
+ * so the colon gets overwritten. */
+int removecolon(char *string){
+ return removechar(string, ':');
+}/* End of removecolon() */
+
+
+
+/* lamont_hdump() has a bug so 3-byte lines are not printed correctly.
+ * This function is a better version of hdump written by Luis MartinGarcia.
+ * It uses current locale to determine if a character is printable or
+ * not. It prints 73char wide lines like these:
+
+0000 e8 60 65 86 d7 86 6d 30 35 97 54 87 ff 67 05 9e .`e...m05.T..g..
+0010 07 5a 98 c0 ea ad 50 d2 62 4f 7b ff e1 34 f8 fc .Z....P.bO{..4..
+0020 c4 84 0a 6a 39 ad 3c 10 63 b2 22 c4 24 40 f4 b1 ...j9.<.c.".$@..
+
+ * The lines look basically like Wireshark hex dump.
+ * */
+void luis_hdump(char *cp, unsigned int length) {
+ static char asciify[257]; /* Stores character table */
+ static bool asc_init=false; /* Flag to generate table only once */
+ unsigned int i=0, hex=0, asc=0; /* Array indexes */
+ int line_count=0; /* For byte count at line start */
+ u8 current_char=0; /* Current character to print */
+ #define LINE_LEN 70 /* Length of printed line */
+ char line2print[LINE_LEN]; /* Stores current line */
+ char printbyte[16]; /* For byte conversion */
+ memset(line2print, ' ', LINE_LEN);
+ line2print[LINE_LEN-1]='\0';
+
+ /* On the first run, generate a list of nice printable characters
+ * (according to current locale) */
+ if( asc_init==false){
+ asc_init=true;
+ for(int i=0; i<256; i++){
+ if( isalnum(i) || isdigit(i) || ispunct(i) ){ asciify[i]=i; }
+ else{ asciify[i]='.'; }
+ }
+ }
+
+#define HEX_START 3
+#define ASC_START 53
+ for(i=0, hex=HEX_START, asc=ASC_START; i<length; i++){
+ current_char=cp[i];
+ if( hex==HEX_START+24) hex++; /* Insert space every 8 bytes */
+ /* First print the hex number */
+ sprintf(printbyte,"%02x", current_char);
+ line2print[hex++]=printbyte[0];
+ line2print[hex++]=printbyte[1];
+ line2print[hex++]=' ';
+ /* Then print its ascii equivalent */
+ line2print[asc++]=asciify[ current_char ];
+ /* Every 16 buffer bytes, print the line. */
+ if( (((i+1)%16)==0 && i!=0) || i+1==length ){
+ printf("%04x%s\n", (16*line_count++), line2print);
+ hex=HEX_START; asc=ASC_START;
+ memset(line2print, ' ', LINE_LEN);
+ line2print[LINE_LEN-1]='\0';
+ }
+ }
+ return;
+} /* End of luis_hdump() */
+
+
+/** Takes a string representing a number, converts it to an unsigned
+ * long, and stores it in *dst.
+ * @param str is the string to be converted. The number may be in any
+ * of the following forms:
+ * - Hexadecimal number: It must start with "0x" and have an even
+ * number of hex digits after it.
+ * - Octal number: It must start with "0" and have any number of
+ * octal digits ([0,7]) after it.
+ * - Decimal number: Any string that does not start with "0x" or
+ * "0" will be treated as a decimal number. It may only contain
+ * decimal digits (no whitespace, no weird symbols, and not even
+ * a sign character (+ or -).
+ * - Random number: The number specification may contain the special
+ * value "rand" or "random". In that case, a random number of the
+ * requested length will be generated and stored in the supplied
+ * buffer.
+ * @param min values less than this cause an error.
+ * @param max values greater than this cause an error.
+ * @param dst should be the address of an unsigned long variable.
+ * @return OP_SUCCESS if conversion was successful or OP_FAILURE in
+ * case of error. */
+static int parse_unsigned_number(const char *str, unsigned long min, unsigned long max, unsigned long *dst){
+ unsigned long int result;
+ char *tail=NULL;
+
+ if(str==NULL || dst==NULL)
+ return OP_FAILURE;
+
+ /* Check if the spec contains a sign character */
+ if(strpbrk(str, "-+") != NULL)
+ return OP_FAILURE;
+
+ /* Case 1: User wants a random value */
+ if(!strcasecmp(str, "rand") || !strcasecmp(str, "random")){
+ u32 r = get_random_u32();
+ *dst = min + (unsigned long) ((max - min + 1) * ((double) r / 0xffffffffUL));
+ return OP_SUCCESS;
+ }
+
+ /* Case 2: User supplied an actual number */
+ errno=0;
+ result=strtoul(str, &tail, 0);
+ if(errno!=0 || tail==str || *tail!='\0')
+ return OP_FAILURE;
+
+ if (result >= min && result <= max) {
+ *dst = result;
+ return OP_SUCCESS;
+ } else {
+ return OP_FAILURE;
+ }
+} /* End of parse_number() */
+
+
+
+/** Takes a string representing an 8-bit number and converts it into an
+ * actual integer. The result is stored in memory area pointed by
+ * "dstbuff". Returns OP_SUCCESS if conversion was successful or
+ * OP_FAILURE in case of error.*/
+int parse_u8(const char *str, u8 *dst){
+ unsigned long ul;
+ int ret;
+ ret = parse_unsigned_number(str, 0UL, 0xffUL, &ul);
+ if (ret == OP_SUCCESS)
+ *dst = ul;
+ return ret;
+}
+
+
+/** Takes a string representing a 16-bit number and converts it into an
+ * actual integer. The result is stored in memory area pointed by
+ * "dstbuff". Returns OP_SUCCESS if conversion was successful or
+ * OP_FAILURE in case of error.*/
+int parse_u16(const char *str, u16 *dst){
+ unsigned long ul;
+ int ret;
+ ret = parse_unsigned_number(str, 0UL, 0xffffUL, &ul);
+ if (ret == OP_SUCCESS)
+ *dst = ul;
+ return ret;
+}
+
+
+/** Takes a string representing a 32-bit number and converts it into an
+ * actual integer. The result is stored in memory area pointed by
+ * "dstbuff". Returns OP_SUCCESS if conversion was successful or
+ * OP_FAILURE in case of error.*/
+int parse_u32(const char *str, u32 *dst){
+ unsigned long ul;
+ int ret;
+ ret = parse_unsigned_number(str, 0UL, 0xffffffffUL, &ul);
+ if (ret == OP_SUCCESS)
+ *dst = ul;
+ return ret;
+}
+
+
+/** Prints the hexadecimal dump of the supplied buffer to standard output */
+int print_hexdump(int level, const u8 *cp, u32 length){
+ char *str = hexdump(cp, length);
+ if(str==NULL)
+ return OP_FAILURE;
+ nping_print(level, "%s", str);
+ free(str);
+ return OP_SUCCESS;
+} /* End of print_hexdump() */
diff --git a/nping/utils.h b/nping/utils.h
new file mode 100644
index 0000000..9ae124d
--- /dev/null
+++ b/nping/utils.h
@@ -0,0 +1,105 @@
+
+/***************************************************************************
+ * utils.cc -- Miscellaneous utils that didn't fit into any of the other *
+ * source files. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+#ifndef UTILS_H
+#define UTILS_H 1
+
+#include "common.h"
+
+#include <stdlib.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "global_structures.h"
+
+/* Function prototypes */
+bool contains(const char *source, const char *substring);
+bool meansRandom(const char *source);
+bool isNumber_u8(const char *source, int base = 10);
+bool isNumber_u16(const char *source, int base = 10);
+bool isNumber_u32(const char *source, int base = 10);
+u8 *parseBufferSpec(char *str, size_t *outlen);
+int bitcmp(u8 *a, u8*b, int len);
+int removechar(char *string, char c);
+int removecolon(char *string);
+void luis_hdump(char *cp, unsigned int length);
+int validate_number_spec(const char *str);
+int parse_u8(const char *str, u8 *dstbuff);
+int parse_u16(const char *str, u16 *dstbuff);
+int parse_u32(const char *str, u32 *dstbuff);
+int print_hexdump(int level, const u8 *cp, u32 length);
+
+#endif /* UTILS_H */
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nping/utils_net.cc b/nping/utils_net.cc
new file mode 100644
index 0000000..e7acbad
--- /dev/null
+++ b/nping/utils_net.cc
@@ -0,0 +1,1941 @@
+
+/***************************************************************************
+ * utils_net.cc -- Miscellaneous network-related functions that perform *
+ * various tasks. *
+ * *
+ ***********************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 "utils.h"
+#include "utils_net.h"
+#include "NpingOps.h"
+#include "global_structures.h"
+#include "output.h"
+#include "nbase.h"
+#include "pcap.h"
+#include "dnet.h"
+#include <vector>
+
+extern NpingOps o;
+
+int atoIP(const char *hostname, struct in_addr *dst){
+ struct sockaddr_in i;
+ unsigned int stlen=0;
+ if ( resolve(hostname, 0, (sockaddr_storage*)&i, (size_t *)&stlen , PF_INET) != 0 )
+ return OP_FAILURE;
+ *dst=i.sin_addr;
+ return OP_SUCCESS;
+} /* End of atoIP */
+
+int atoIP(const char *hostname, struct sockaddr_storage *ss, int family){
+ size_t stlen=0;
+ if(ss==NULL || hostname==NULL)
+ return OP_FAILURE;
+ if(family!=AF_INET && family!=AF_INET6)
+ return OP_FAILURE;
+ if ( resolve(hostname, 0, ss, &stlen , family) != 0 )
+ return OP_FAILURE;
+ return OP_SUCCESS;
+} /* End of atoIP */
+
+
+/** @warning The string is returned in a statically allocated buffer, which
+ * subsequent calls will overwrite.*/
+char *IPtoa(u32 i){
+ static char buffer[24];
+ char *aux=NULL;
+ memset(buffer, 0, 24);
+ struct in_addr myip;
+ myip.s_addr=i;
+ aux=inet_ntoa(myip);
+ /* Get our own copy of the data so only subsequent calls to IPtoa overwrite
+ * the returned buffer (not subsequent calls to inet_ntoa() made by other
+ * methods. */
+ if(aux!=NULL){
+ strncpy(buffer, aux, 23);
+ return buffer;
+ }
+ else
+ return NULL;
+} /* End of IPtoa() */
+
+
+/** @warning The string is returned in a statically allocated buffer, which
+ * subsequent calls will overwrite.*/
+char *IPtoa(struct sockaddr_storage *ss){
+ struct sockaddr_in *s4=(struct sockaddr_in *)ss;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)ss;
+ static char ipstring[256];
+ memset(ipstring, 0, 256);
+ if( ss==NULL ){
+ snprintf(ipstring,256, "[[NULL address supplied to IPtoa()]]");
+ return ipstring;
+ }
+ if(s6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &s6->sin6_addr, ipstring, sizeof(ipstring));
+ }else if( s4->sin_family == AF_INET ) {
+ inet_ntop(AF_INET, &s4->sin_addr, ipstring, sizeof(ipstring));
+ }else{
+ snprintf(ipstring,256,"[[Unknown address family sockaddr supplied to IPtoa()]]");
+ }
+ return ipstring;
+} /* End of IPtoa() */
+
+
+char *IPtoa(struct sockaddr_storage ss){
+ return IPtoa(&ss);
+} /* End of IPtoa() */
+
+char *IPtoa(struct sockaddr_storage *ss, int family){
+ if(ss==NULL){
+ return NULL;
+ }else if(family==AF_INET){
+ struct sockaddr_in *s4=(struct sockaddr_in *)ss;
+ return IPtoa(s4->sin_addr);
+ }else if(family==AF_INET6){
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)ss;
+ return IPtoa(s6->sin6_addr);
+ }else{
+ return NULL;
+ }
+} /* End of IPtoa() */
+
+
+/** @warning The string is returned in a statically allocated buffer, which
+ * subsequent calls will overwrite.*/
+char *IPtoa(struct in_addr addr){
+ static char ipstring[256];
+ memset(ipstring, 0, 256);
+ inet_ntop(AF_INET, &addr, ipstring, sizeof(ipstring));
+ return ipstring;
+} /* End of IPtoa() */
+
+
+/** @warning The string is returned in a statically allocated buffer, which
+ * subsequent calls will overwrite.*/
+char *IPtoa(struct in6_addr addr){
+ static char ipstring[256];
+ memset(ipstring, 0, 256);
+ inet_ntop(AF_INET6, &addr, ipstring, sizeof(ipstring));
+ return ipstring;
+} /* End of IPtoa() */
+
+
+/** @warning The string is returned in a statically allocated buffer, which
+ * subsequent calls will overwrite.*/
+char *IPtoa(u8 *ipv6addr){
+ static char ipstring[256];
+ memset(ipstring, 0, 256);
+ struct in6_addr s6;
+ memcpy(s6.s6_addr, ipv6addr, 16);
+ inet_ntop(AF_INET6, &s6, ipstring, sizeof(ipstring));
+ return ipstring;
+} /* End of IPtoa() */
+
+
+/** Returns true if supplied value corresponds to a valid RFC compliant ICMP
+ * type. Otherwise it returns false. */
+bool isICMPType(u8 type){
+ switch (type){
+ case 0:
+ case 3:
+ case 4:
+ case 5:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 30:
+ return true;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ return false;
+} /* End of isICMPType() */
+
+
+u16 sockaddr2port(struct sockaddr_storage ss){
+ return sockaddr2port(&ss);
+}
+
+
+u16 sockaddr2port(struct sockaddr_storage *ss){
+ assert(ss!=NULL);
+ if(ss->ss_family==AF_INET)
+ return sockaddr2port( (struct sockaddr_in *)ss );
+ else if( ss->ss_family==AF_INET6){
+ return sockaddr2port( (struct sockaddr_in6 *)ss );
+ }else{
+ return 0;
+ }
+}
+
+
+u16 sockaddr2port(struct sockaddr_in *s4){
+ assert(s4!=NULL);
+ return ntohs(s4->sin_port);
+}
+
+
+u16 sockaddr2port(struct sockaddr_in6 *s6){
+ assert(s6!=NULL);
+ return ntohs(s6->sin6_port);
+}
+
+
+/* Sets the address family member of the supplied sockaddr. */
+int setsockaddrfamily(struct sockaddr_storage *ss, int family){
+ struct sockaddr_in *s4=(struct sockaddr_in *)ss;
+ s4->sin_family=family;
+ return OP_SUCCESS;
+} /* End of setsockaddrfamily() */
+
+
+/* Sets the special INADDR_ANY or in6addr_an constant on the sin_family or
+ * sin6_addr member of the supplied sockaddr. Note that for this to work,
+ * the supplied sockaddr_storage MUST have a correct address family set
+ * already (sin_family or sin6_family). */
+int setsockaddrany(struct sockaddr_storage *ss){
+ struct sockaddr_in *s4=(struct sockaddr_in *)ss;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)ss;
+ if(s4->sin_family==AF_INET)
+ s4->sin_addr.s_addr=INADDR_ANY;
+ else if(s6->sin6_family==AF_INET6)
+ s6->sin6_addr=in6addr_any;
+ else
+ return OP_FAILURE;
+ return OP_SUCCESS;
+} /* End of setsockaddrany() */
+
+
+/** Returns true if supplied value corresponds to a valid RFC compliant ICMP
+ * Code. Otherwise it returns false.
+ * @warning The fact that a given value matches a standard code does not
+ * mean the code is correct because it depends on the type being used */
+bool isICMPCode(u8 code){
+ /* Correct as of 25 June 09.
+ * http://www.iana.org/assignments/icmp-parameters */
+ if( code<=16 )
+ return true;
+ else
+ return false;
+} /* End of isICMPType() */
+
+
+
+/** Returns true if supplied value corresponds to a valid RFC compliant ICMP
+ * Code for the supplied type
+ * @warning The fact that a given value matches a standard code does not
+ * mean the code is correct because it depends on the type being used */
+bool isICMPCode(u8 code, u8 type){
+ /* Correct as of 25 June 09.
+ * http://www.iana.org/assignments/icmp-parameters */
+ switch (type){
+ case 0: /* Echo Reply */
+ if(code==0) return true;
+ break;
+
+ case 3: /* Destination Unreachable */
+ if(code<=15) return true;
+ break;
+
+ case 4: /* Source Quench */
+ if(code==0) return true;
+ break;
+
+ case 5: /* Redirect */
+ if(code<=3) return true;
+ break;
+
+ case 6: /* Alternate Address for Host */
+ if(code==0) return true;
+ break;
+
+ case 8: /* Echo */
+ if(code==0) return true;
+ break;
+
+ case 9: /* Router Advertisement */
+ if(code==0 || code==16) return true;
+ break;
+
+ case 10: /* Router Selection */
+ if(code==0) return true;
+ break;
+
+ case 11: /* Time Exceeded */
+ if(code==0 || code==1) return true;
+ break;
+
+ case 12: /* Parameter Problem */
+ if(code<=2) return true;
+ break;
+
+ case 13: /* Timestamp */
+ if(code==0) return true;
+ break;
+
+ case 14: /* Timestamp Reply */
+ if(code==0) return true;
+ break;
+
+ case 15: /* Information Request */
+ if(code==0) return true;
+ break;
+
+ case 16: /* Information Reply */
+ if(code==0) return true;
+ break;
+
+ case 17: /* Address Mask Request */
+ if(code==0) return true;
+ break;
+
+ case 18: /* Address Mask Reply */
+ if(code==0) return true;
+ break;
+
+ case 30: /* Traceroute */
+ return true;
+ break;
+
+ case 40: /* Experimental ICMP Security Failures Messages [RFC 2521] */
+ if(code<=5) return true;
+ break;
+
+ default:
+ return false;
+ break;
+ }
+ return false;
+} /* End of isICMPType() */
+
+
+/* This function fills buffer "dstbuff" with a printable string that
+ * represents the supplied packet. When sending IPv6 packet at raw TCP
+ * level, the caller may specify source and/or destination address so they
+ * also get included in the returned information. However, this is optional
+ * and is safe to pass NULL values. */
+int getPacketStrInfo(const char *proto, const u8 *packet, u32 len, u8 *dstbuff,
+ u32 dstlen, struct sockaddr_storage *ss_src, struct sockaddr_storage *ss_dst){
+ char *b=NULL;
+ int detail;
+
+ if ( dstbuff == NULL || dstlen < 512 )
+ nping_fatal(QT_3,"safe_ippackethdrinfo() Invalid values supplied.");
+
+ if(o.getVerbosity()>=VB_2)
+ detail=HIGH_DETAIL;
+ else if (o.getVerbosity()==VB_1)
+ detail=MEDIUM_DETAIL;
+ else
+ detail=LOW_DETAIL;
+
+ if( !strcasecmp(proto, "IP") || !strcasecmp(proto, "IPv4") || !strcasecmp(proto, "IPv6")){
+ b=(char *)ippackethdrinfo(packet, len, detail);
+ strncpy((char*)dstbuff, b, dstlen);
+ dstbuff[dstlen-1]=0; /* Just to be sure, NULL-terminate the last position*/
+ }else if( !strcasecmp(proto, "ARP") || !strcasecmp(proto, "RARP") ){
+ return arppackethdrinfo(packet, len, dstbuff, dstlen);
+ }else if( !strcasecmp(proto, "IPv6_NO_HEADER") || o.ipv6UsingSocket() ){
+ if( o.getMode()==TCP )
+ return tcppackethdrinfo(packet, len, dstbuff, dstlen, detail, ss_src, ss_dst);
+ else if ( o.getMode()==UDP )
+ return udppackethdrinfo(packet, len, dstbuff, dstlen, detail, ss_src, ss_dst);
+ else
+ nping_fatal(QT_3, "getPacketStrInfo(): Unable to determinate transport layer protocol");
+ }else{
+ nping_fatal(QT_3, "getPacketStrInfo(): Unknown protocol");
+ }
+ return OP_SUCCESS;
+} /* getPacketStrInfo() */
+
+
+/* Same as previous one but passes NULL sockaddr values automatically. */
+int getPacketStrInfo(const char *proto, const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen){
+ return getPacketStrInfo(proto,packet,len,dstbuff,dstlen,NULL,NULL);
+} /* getPacketStrInfo() */
+
+
+/** This function converts a port ranges specification into an array of u16
+ * integers that represent each of the specified ports. It allocates space
+ * for the port lists and stores the pointer in the supplied "list" parameter.
+ * Also, the number of ports in the array is returned through the supplied
+ * "count" pointer.
+ * @warning the caller is the one responsible for free()ing the allocated
+ * list of ports.
+ */
+int nping_getpts_simple(const char *origexpr, u16 **list, int *count) {
+ u8 *porttbl;
+ int portwarning = 0;
+ int i, j;
+
+ /* Allocate array to hold 2^16 ports */
+ porttbl = (u8 *) safe_zalloc(65536);
+
+ /* Get the ports but do not allow changing the type with T:, U:, or P:. */
+ getpts_aux(origexpr, 0, porttbl, &portwarning);
+
+ /* Count how many are set. */
+ *count = 0;
+ for (i = 0; i <= 65535; i++) {
+ if (porttbl[i])
+ (*count)++;
+ }
+
+ if (*count == 0){
+ free(porttbl);
+ return OP_FAILURE;
+ }
+
+ *list = (unsigned short *) safe_zalloc(*count * sizeof(u16));
+
+ /* Fill in the list. */
+ for (i = 0, j = 0; i <= 65535; i++) {
+ if (porttbl[i])
+ (*list)[j++] = i;
+ }
+ free(porttbl);
+ return OP_SUCCESS;
+} /* End of nping_getpts_simple() */
+
+
+
+
+/** Determines the net iface that should be used when sending packets
+ * to "destination".
+ * @return OP_SUCCESS on success and OP_FAILUIRE in case of error.
+ * @warning "*dev" must be able to hold at least 16 bytes */
+int getNetworkInterfaceName(u32 destination, char *dev){
+ struct route_nfo rnfo;
+ struct sockaddr_in dst, src;
+ bool result=false;
+ if(dev==NULL)
+ nping_fatal(QT_3, "getNetworkInterfaceName(): NULL value supplied.");
+ memset(&rnfo, 0, sizeof(struct route_nfo) );
+ memset(&dst, 0, sizeof(struct sockaddr_in) );
+ memset(&src, 0, sizeof(struct sockaddr_in) );
+ dst.sin_addr.s_addr = destination;
+ dst.sin_family = AF_INET;
+ result=route_dst((struct sockaddr_storage *)&dst, &rnfo, NULL, NULL);
+ if( result == false )
+ return OP_FAILURE;
+ strncpy( dev, rnfo.ii.devname, 16 );
+ return OP_SUCCESS;
+} /* End of getSourceAddress() */
+
+
+
+/** Determines the net iface that should be used when sending packets
+ * to "destination".
+ * @return OP_SUCCESS on success and OP_FAILUIRE in case of error.
+ * @warning "*dev" must be able to hold at least 16 bytes */
+int getNetworkInterfaceName(struct sockaddr_storage *dst, char *dev){
+ struct route_nfo rnfo;
+ struct sockaddr_storage src;
+ bool result=false;
+ if(dev==NULL)
+ nping_fatal(QT_3, "getNetworkInterfaceName(): NULL value supplied.");
+ memset(&rnfo, 0, sizeof(struct route_nfo) );
+ memset(&src, 0, sizeof(struct sockaddr_in) );
+ result=route_dst(dst, &rnfo, NULL, NULL);
+ if( result == false )
+ return OP_FAILURE;
+ strncpy( dev, rnfo.ii.devname, 16 );
+ return OP_SUCCESS;
+} /* End of getSourceAddress() */
+
+
+typedef struct cached_host{
+ char hostname[MAX_CACHED_HOSTNAME_LEN];
+ struct sockaddr_storage ss;
+ size_t sslen;
+}cached_host_t;
+
+
+int resolveCached(char *host, struct sockaddr_storage *ss, size_t *sslen, int pf) {
+ static cached_host_t archive[MAX_CACHED_HOSTS];
+ static int cached_count=0;
+ static int current_index=0; /* Used when we reach the end of the array and we do circular buffer */
+ int result=0;
+ //static int way=1;
+ static int misses=0, hits=0;
+
+ /* Used for debug. When called with NULL,0x1337, print stats */
+ if(host==NULL && pf == 1337){
+ nping_print(DBG_4, "resolveCached(): MISSES: %d, HITS: %d\n", misses, hits);
+ return OP_SUCCESS;
+ }
+
+
+ if( ss==NULL || sslen==NULL || host==NULL)
+ nping_fatal(QT_3, "resolveCached(): NULL values supplied");
+
+ /* First we check if we have the host already cached */
+ for(int i=0; i<MAX_CACHED_HOSTS && i<cached_count; i++){
+ if( !strcasecmp( archive[i].hostname , host ) ){ /* Cache hit */
+ *sslen=archive[i].sslen;
+ memcpy(ss, &(archive[i].ss) , *sslen);
+ hits++;
+ nping_print(DBG_4, "resolveCached(): Cache hit %d for %s\n", hits, host);
+ return OP_SUCCESS;
+ }
+ }
+
+ /* Cache miss */
+ misses++;
+ nping_print(DBG_4, "resolveCached(): Cache miss %d for %s\n", misses, host);
+
+ if( (result=resolve(host, 0, ss, sslen, pf)) == 0 ){
+
+ /* Increment count */
+ if( cached_count < MAX_CACHED_HOSTS )
+ cached_count++;
+
+ /* Store info */
+ memset(&(archive[current_index]), 0, sizeof(cached_host_t) );
+ strncpy(archive[current_index].hostname, host, MAX_CACHED_HOSTNAME_LEN);
+ archive[current_index].sslen = *sslen;
+ memcpy(&(archive[current_index].ss), ss, *sslen);
+
+
+ /* I run some tests to see what is the best approach when the cache
+ * is full. The thing is that in Nping, we are likely to call
+ * this function over and over with specifying the same hosts. Deleting
+ * the oldest entry results in 100% cache misses. I also tried to start
+ * overwriting entries first backwards and then upwards. That showed
+ * much better results. However, if we simply overwrite the last
+ * cache entry over an over we get the best results. */
+ if( current_index < MAX_CACHED_HOSTS-1 )
+ current_index++;
+ return 0;
+
+
+
+ ///* Watch out for the overflow. If cache is full, */
+ //if( cached_count == MAX_CACHED_HOSTS ){
+ //if( way%2==1 ){
+ //if( current_index > 0 )
+ //current_index--;
+ //else{
+ //current_index=1;
+ //way++;
+ //}
+ //}
+ //else{
+ //if( current_index < MAX_CACHED_HOSTS-1 )
+ //current_index++;
+ //else{
+ //current_index=MAX_CACHED_HOSTS-2;
+ //way++;
+ //}
+ //}
+ //}
+ //else
+ //current_index++;
+ //return OP_SUCCESS;
+
+ }else{
+ nping_warning(QT_2, "Error resolving %s\n",host);
+ return OP_FAILURE;
+ }
+} /* End of resolveCached() */
+
+
+typedef struct gethostbyname_cached{
+ char hostname[MAX_CACHED_HOSTNAME_LEN];
+ struct hostent *h;
+}gethostbynamecached_t;
+
+
+struct hostent *gethostbynameCached(char *host){
+ static gethostbynamecached_t archive[MAX_CACHED_HOSTS];
+ static int cached_count=0;
+ static int current_index=0;
+ struct hostent *result=NULL;
+ static int misses=0, hits=0;
+ int i=0;
+
+ if( host==NULL)
+ nping_fatal(QT_3, "gethostbynameCached(): NULL values supplied");
+
+ /* First we check if we have the host already cached */
+ for(i=0; i<MAX_CACHED_HOSTS && i<cached_count; i++){
+ if( !strcasecmp( archive[i].hostname , host ) ){ /* Cache hit */
+ hits++;
+ nping_print(DBG_4, "gethostbynameCached(): Cache hit %d for %s", hits, host);
+ return archive[i].h;
+ }
+ }
+
+ /* Cache miss */
+ misses++;
+ nping_print(DBG_4, "gethostbynameCached(): Cache miss %d for %s", misses, host);
+
+ if( (result=gethostbyname(host) ) != NULL ){
+
+ /* Increment cache entry count */
+ if( cached_count < MAX_CACHED_HOSTS )
+ cached_count++;
+
+ /* If we've reached the max number of cached hosts, free the
+ * hostent entry that is in the last slot so we can insert a new
+ * one in its place */
+ if ( current_index==MAX_CACHED_HOSTS-1 && archive[current_index].h != NULL )
+ hostentfree( archive[current_index].h );
+
+ /* Store the hostent entry in the cache */
+ memset(&(archive[current_index]), 0, sizeof(gethostbynamecached_t) );
+ strncpy(archive[current_index].hostname, host, MAX_CACHED_HOSTNAME_LEN);
+ archive[current_index].h = hostentcpy( result );
+
+ /* Return the entry that we've just added */
+ if( current_index < MAX_CACHED_HOSTS-1 ){
+ current_index++;
+ return archive[current_index-1].h;
+ }
+ else{
+ return archive[current_index].h;
+ }
+
+ }else{
+ return NULL;
+ }
+} /* End of resolveCached() */
+
+
+struct hostent *hostentcpy(struct hostent *src){
+ struct hostent *st=NULL;
+ int aliases=0;
+ int addrs=0;
+
+ if( src == NULL )
+ return NULL;
+
+ st=(struct hostent *)safe_zalloc( sizeof(struct hostent) );
+
+ /* Copy host name */
+ if( src->h_name!= NULL )
+ st->h_name = strdup( src->h_name );
+
+ /* Copy aliases */
+ if( src->h_aliases != NULL ){
+ while( src->h_aliases[aliases] ) /* Fist count how many*/
+ aliases++;
+ st->h_aliases = (char **)safe_zalloc( aliases * sizeof(char*) ); /* Allocate array */
+ for( int i=0; i<aliases; i++) /* Copy all entries */
+ st->h_aliases[i] = strdup( src->h_aliases[i] );
+ }
+ /* Copy address type an length */
+ st->h_addrtype=src->h_addrtype;
+ st->h_length=src->h_length;
+
+ /* Copy list of addresses */
+ if( src->h_addr_list != NULL ){
+
+ while( src->h_addr_list[addrs] ) /* Fist count how many*/
+ addrs++;
+
+ st->h_addr_list = (char **)safe_zalloc( addrs * sizeof(char*) ); /* Allocate array */
+
+ for( int j=0; j<addrs; j++) /* Copy all entries */
+ st->h_addr_list[j] = strdup( src->h_addr_list[j] );
+
+ /* Create dummy synonym for h_addr_list[0]*/
+ st->h_addr=st->h_addr_list[0];
+ }
+ return st;
+} /* End of hostentcpy() */
+
+
+/** Free a hostend structure.
+ * @warning This function can ONLY be used with hostent structs returned by
+ * hostentcpy. Do NOT attempt to use this on a hostent returned by
+ * gethostbyname() because the structure may contain pointers to statically
+ * allocated memory regions.*/
+int hostentfree(struct hostent *src){
+ int aliases=0;
+ int addrs=0;
+
+ if( src == NULL )
+ return OP_SUCCESS;
+
+ /* Free host name */
+ if ( src->h_name != NULL )
+ free( src->h_name );
+
+ /* Free aliases */
+ if( src->h_aliases != NULL ){
+ while( src->h_aliases[aliases] ){
+ free(src->h_aliases[aliases]);
+ aliases++;
+ }
+ free(src->h_aliases);
+ }
+
+ /* Free list of addresses */
+ if( src->h_addr_list != NULL ){
+
+ while( src->h_addr_list[addrs] ){
+ addrs++;
+ free( src->h_addr_list[addrs] );
+ }
+ free( src->h_addr_list );
+ }
+
+ /* Finally free the base hostent struct */
+ free( src );
+ return OP_SUCCESS;
+} /* End of hostentfree() */
+
+
+
+/** Receives a MAC address as a string of format 00:13:01:e6:c7:ae or
+ * 00-13-01-e6-c7-ae and stores in targetbuff the 6 corresponding bytes.
+ * The "txt" parameter may take the special value "rand" or "random",
+ * in which case, 6 random bytes will be stored in "targetbuff".
+ * @return OP_SUCCESS on success and OP_FAILURE in case of error.
+ * Buffer targetbuff is NOT modified if "txt" does not have the proper
+ * format */
+int parseMAC(const char *txt, u8 *targetbuff){
+ u8 mac_data[6];
+ char tmphex[3];
+ int i=0, j=0;
+
+ if( txt==NULL || targetbuff==NULL )
+ return OP_FAILURE;
+
+ /* Set up a random MAC if user requested so. */
+ if( meansRandom(txt) ){
+ get_random_bytes(targetbuff, 6);
+ return OP_SUCCESS;
+ /* Or set it to FF:FF:FF:FF:FF:FF if user chose broadcast */
+ }else if( !strcasecmp(optarg, "broadcast") || !strcasecmp(optarg, "bcast") ){
+ memset(targetbuff, 0xFF, 6);
+ return OP_SUCCESS;
+ }
+
+ /* Array should look like 00:13:01:e6:c7:ae or 00-13-01-e6-c7-ae
+ Array positions: 01234567890123456 01234567890123456 */
+ if( strlen(txt)!=17 )
+ return OP_FAILURE;
+ /* Check MAC has the correct ':' or '-' characters */
+ if( (txt[2]!=':' && txt[2]!='-') || (txt[5]!=':' && txt[5]!='-') ||
+ (txt[8]!=':' && txt[8]!='-') || (txt[11]!=':' && txt[11]!='-') ||
+ (txt[14]!=':' && txt[14]!='-') )
+ return OP_FAILURE;
+
+ /* Convert txt into actual bytes */
+ for(i=0, j=0; i<6; i++, j+=3 ){
+ if( !isxdigit(txt[j]) || !isxdigit(txt[j+1]) )
+ return OP_FAILURE;
+ tmphex[0] = txt[j];
+ tmphex[1] = txt[j+1];
+ tmphex[2] = '\0';
+ mac_data[i] = (u8) strtol(tmphex, NULL, 16);
+ }
+ memcpy(targetbuff, mac_data, 6);
+ return OP_SUCCESS;
+} /* End of parseMAC() */
+
+
+
+char *MACtoa(u8 *mac){
+ static char macinfo[24];
+ memset(macinfo, 0, 24);
+ sprintf(macinfo,"%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+ return macinfo;
+} /* End of MACtoa() */
+
+
+
+
+/* Returns a buffer of ASCII information about an ARP/RARP packet that may look
+ like "ARP who has 192.168.10.1? Tell 192.168.10.98"
+ Since this is a static buffer, don't use threads or call twice
+ within (say) printf(). And certainly don't try to free() it! The
+ returned buffer is NUL-terminated */
+const char *arppackethdrinfo(const u8 *packet, u32 len, int detail){
+ static char protoinfo[512];
+ if (packet==NULL)
+ nping_fatal(QT_3, "arppackethdrinfo(): NULL value supplied");
+ if( len < 28 )
+ return "BOGUS! Packet too short.";
+ u16 *htype = (u16 *)packet;
+ u16 *ptype = (u16 *)(packet+2);
+ u8 *hlen = (u8 *)(packet+4);
+ u8 *plen = (u8 *)(packet+5);
+ u16 *op = (u16 *)(packet+6);
+ u8 *sMAC= (u8 *)(packet+8);
+ u32 *sIP = (u32 *)(packet+14);
+ u8 *tMAC = (u8 *)(packet+18);
+ u32 *tIP = (u32 *)(packet+24);
+
+ if( ntohs(*op) == 1 ){ /* ARP Request */
+ sprintf(protoinfo, "ARP who has %s? ", IPtoa(*tIP));
+ sprintf(protoinfo+strlen(protoinfo),"Tell %s", IPtoa(*sIP) );
+ }
+ else if( ntohs(*op) == 2 ){ /* ARP Reply */
+ sprintf(protoinfo, "ARP reply %s ", IPtoa(*sIP));
+ sprintf(protoinfo+strlen(protoinfo),"is at %s", MACtoa(sMAC) );
+ }
+ else if( ntohs(*op) == 3 ){ /* RARP Request */
+ sprintf(protoinfo, "RARP who is %s? Tell %s", MACtoa(tMAC), MACtoa(sMAC) );
+ }
+ else if( ntohs(*op) ==4 ){ /* RARP Reply */
+ sprintf(protoinfo, "RARP reply: %s is at %s", MACtoa(tMAC), IPtoa(*tIP) );
+ }
+ else{
+ sprintf(protoinfo, "HTYPE:%04X PTYPE:%04X HLEN:%d PLEN:%d OP:%04X SMAC:%s SIP:%s DMAC:%s DIP:%s",
+ *htype, *ptype, *hlen, *plen, *op, MACtoa(sMAC), IPtoa(*sIP), MACtoa(tMAC), IPtoa(*tIP));
+ }
+ return protoinfo;
+} /* End of arppackethdrinfo() */
+
+
+
+
+int arppackethdrinfo(const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen){
+ char *b=NULL;
+ int detail=0;
+
+ if ( dstbuff == NULL || dstlen < 512 )
+ nping_fatal(QT_3,"safe_arppackethdrinfo() Invalid values supplied.");
+
+ /* Determine level of detail in packet output from current verbosity level */
+ if(o.getVerbosity()>=VB_2)
+ detail=HIGH_DETAIL;
+ else if (o.getVerbosity()==VB_1)
+ detail=MEDIUM_DETAIL;
+ else
+ detail=LOW_DETAIL;
+
+ b=(char *)arppackethdrinfo(packet, len, detail);
+ strncpy((char*)dstbuff, b, dstlen);
+ dstbuff[dstlen-1]=0; /* Just to be sure, NULL-terminate the last position*/
+ return OP_SUCCESS;
+} /* End of arppackethdrinfo() */
+
+
+
+int tcppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen,
+ int detail, struct sockaddr_storage *src, struct sockaddr_storage *dst){
+
+ struct tcp_hdr *tcp=NULL; ; /* TCP header structure. */
+ char *p = NULL; /* Aux pointer. */
+ static char protoinfo[1024] = ""; /* Stores final info string. */
+ char tflags[10];
+ char tcpinfo[64] = "";
+ char buf[32];
+ char tcpoptinfo[256] = "";
+ struct sockaddr_in *s4=(struct sockaddr_in *)src;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)src;
+ struct sockaddr_in *d4=(struct sockaddr_in *)dst;
+ struct sockaddr_in6 *d6=(struct sockaddr_in6 *)dst;
+ char srcipstring[128];
+ char dstipstring[128];
+
+ assert(packet);
+ assert(dstbuff);
+ assert(len>=20);
+
+ tcp=(struct tcp_hdr *)packet;
+
+ /* Ensure we end up with a valid detail number */
+ if( detail!=LOW_DETAIL && detail!=MEDIUM_DETAIL && detail!=HIGH_DETAIL)
+ detail=LOW_DETAIL;
+
+
+ /* Determine target IP address */
+ if(src!=NULL){
+ if( s4->sin_family==AF_INET ){
+ inet_ntop(AF_INET, &s4->sin_addr, srcipstring, sizeof(srcipstring));
+ }
+ else if( s6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &s6->sin6_addr, srcipstring, sizeof(srcipstring));
+ }else{
+ sprintf(dstipstring, "unknown_addr_family");
+ }
+ }else{
+ sprintf(srcipstring, "this_host");
+ }
+
+ /* Determine source IP address */
+ if(dst!=NULL){
+ if( d4->sin_family==AF_INET ){
+ inet_ntop(AF_INET, &d4->sin_addr, dstipstring, sizeof(dstipstring));
+ }
+ else if( d6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &d6->sin6_addr, dstipstring, sizeof(dstipstring));
+ }else{
+ sprintf(dstipstring, "unknown_addr_family");
+ }
+ }else{
+ sprintf(dstipstring, "unknown_host");
+ }
+
+ /* TCP Flags */
+ p = tflags;
+ /* These are basically in tcpdump order */
+ if (tcp->th_flags & TH_SYN) *p++ = 'S';
+ if (tcp->th_flags & TH_FIN) *p++ = 'F';
+ if (tcp->th_flags & TH_RST) *p++ = 'R';
+ if (tcp->th_flags & TH_PUSH) *p++ = 'P';
+ if (tcp->th_flags & TH_ACK){ *p++ = 'A';
+ Snprintf(buf, sizeof(buf), " ack=%lu",
+ (unsigned long) ntohl(tcp->th_ack));
+ strncat(tcpinfo, buf, sizeof(tcpinfo) - strlen(tcpinfo) - 1);
+ }
+ if (tcp->th_flags & TH_URG) *p++ = 'U';
+ if (tcp->th_flags & TH_ECE) *p++ = 'E'; /* rfc 2481/3168 */
+ if (tcp->th_flags & TH_CWR) *p++ = 'C'; /* rfc 2481/3168 */
+ *p++ = '\0';
+
+
+ /* TCP Options */
+ if((u32) tcp->th_off * 4 > sizeof(struct tcp_hdr)) {
+ if(len < (u32) tcp->th_off * 4) {
+ Snprintf(tcpoptinfo, sizeof(tcpoptinfo), "option incomplete");
+
+ } else {
+ tcppacketoptinfo((u8*) tcp + sizeof(struct tcp_hdr),
+ tcp->th_off*4 - sizeof(struct tcp_hdr),
+ tcpoptinfo, sizeof(tcpoptinfo));
+ }
+ }
+
+ /* Rest of header fields */
+ if( detail == LOW_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "TCP %s:%d > %s:%d %s seq=%lu win=%hu %s",
+ srcipstring, ntohs(tcp->th_sport), dstipstring, ntohs(tcp->th_dport),
+ tflags, (unsigned long) ntohl(tcp->th_seq),
+ ntohs(tcp->th_win), tcpoptinfo);
+ }else if( detail == MEDIUM_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%d > %s:%d %s seq=%lu win=%hu csum=0x%04X%s%s]",
+ srcipstring, ntohs(tcp->th_sport), dstipstring, ntohs(tcp->th_dport),
+ tflags, (unsigned long) ntohl(tcp->th_seq),
+ ntohs(tcp->th_win), ntohs(tcp->th_sum),
+ (tcpoptinfo[0]!='\0') ? " " : "",
+ tcpoptinfo);
+ }else if( detail==HIGH_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "TCP [%s:%d > %s:%d %s seq=%lu ack=%lu off=%d res=%d win=%hu csum=0x%04X urp=%d%s%s] ",
+ srcipstring, ntohs(tcp->th_sport),
+ dstipstring, ntohs(tcp->th_dport),
+ tflags, (unsigned long) ntohl(tcp->th_seq),
+ (unsigned long) ntohl(tcp->th_ack),
+ (u8)tcp->th_off, (u8)tcp->th_x2, ntohs(tcp->th_win),
+ ntohs(tcp->th_sum), ntohs(tcp->th_urp),
+ (tcpoptinfo[0]!='\0') ? " " : "",
+ tcpoptinfo);
+ }
+
+ strncpy((char*)dstbuff, protoinfo, dstlen);
+
+ return OP_SUCCESS;
+
+} /* End of tcppackethdrinfo() */
+
+
+
+
+int udppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen,
+ int detail, struct sockaddr_storage *src, struct sockaddr_storage *dst){
+
+ struct udp_hdr *udp = NULL; /* UDP header structure. */
+ static char protoinfo[1024] = ""; /* Stores final info string. */
+ struct sockaddr_in *s4=(struct sockaddr_in *)src;
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)src;
+ struct sockaddr_in *d4=(struct sockaddr_in *)dst;
+ struct sockaddr_in6 *d6=(struct sockaddr_in6 *)dst;
+ char srcipstring[128];
+ char dstipstring[128];
+
+ assert(packet);
+ assert(dstbuff);
+ assert(len>=8);
+
+ udp=(struct udp_hdr *)packet;
+
+ /* Ensure we end up with a valid detail number */
+ if( detail!=LOW_DETAIL && detail!=MEDIUM_DETAIL && detail!=HIGH_DETAIL)
+ detail=LOW_DETAIL;
+
+
+ /* Determine target IP address */
+ if(src!=NULL){
+ if( s4->sin_family==AF_INET ){
+ inet_ntop(AF_INET, &s4->sin_addr, srcipstring, sizeof(srcipstring));
+ }
+ else if( s6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &s6->sin6_addr, srcipstring, sizeof(srcipstring));
+ }else{
+ sprintf(dstipstring, "unknown_addr_family");
+ }
+ }else{
+ sprintf(srcipstring, "this_host");
+ }
+
+ /* Determine source IP address */
+ if(dst!=NULL){
+ if( d4->sin_family==AF_INET ){
+ inet_ntop(AF_INET, &d4->sin_addr, dstipstring, sizeof(dstipstring));
+ }
+ else if( d6->sin6_family==AF_INET6){
+ inet_ntop(AF_INET6, &d6->sin6_addr, dstipstring, sizeof(dstipstring));
+ }else{
+ sprintf(dstipstring, "unknown_addr_family");
+ }
+ }else{
+ sprintf(dstipstring, "unknown_host");
+ }
+
+ if( detail == LOW_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "UDP %s:%d > %s:%d",
+ srcipstring, ntohs(udp->uh_sport), dstipstring, ntohs(udp->uh_dport));
+ }else if( detail == MEDIUM_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "UDP [%s:%d > %s:%d csum=0x%04X]",
+ srcipstring, ntohs(udp->uh_sport), dstipstring, ntohs(udp->uh_dport), ntohs(udp->uh_sum));
+ }else if( detail==HIGH_DETAIL ){
+ Snprintf(protoinfo, sizeof(protoinfo), "UDP [%s:%d > %s:%d len=%d csum=0x%04X]",
+ srcipstring, ntohs(udp->uh_sport), dstipstring, ntohs(udp->uh_dport),
+ ntohs(udp->uh_ulen), ntohs(udp->uh_sum));
+ }
+
+ strncpy((char*)dstbuff, protoinfo, dstlen);
+
+ return OP_SUCCESS;
+
+} /* End of udppackethdrinfo() */
+
+
+
+/** Returns a random (null-terminated) ASCII string with no special
+ * meaning. Returned string may be between 1 and 512 bytes and contain
+ * random letters and some whitespace.
+ * @warning Returned string is stored in a static buffer that subsequent
+ * calls will overwrite.
+ * Note that the entropy of the returned data is very low (returned
+ * values are always formed by lowercase letters and whitespace). */
+const char *getRandomTextPayload(){
+ int len=0, i=0;
+ static char buffer[512+1];
+ const char letters[26]={'a','b','c','d','e','f','g','h','i','j','k',
+ 'l','m','n','o','p','q','r','s','t','u','v',
+ 'w','z','y','z'};
+
+ /* Determine how long the text should be */
+ while( (len=(2*get_random_u8())-1) == 0 );
+ /* Create the string */
+ for(i=0; i<len; i++){
+ if( get_random_u8()%5==0 )
+ buffer[i] = ' '; // Whitespace
+ else
+ buffer[i] = letters[ get_random_u8()%26 ];
+ }
+ buffer[len]='\0';
+ return buffer;
+} /* End of getRandomTextPayload() */
+
+
+
+/** UNIMPLEMENTED */
+int send_packet(NpingTarget *target, int rawfd, u8 *pkt, size_t pktLen){
+ int res;
+ struct sockaddr_in6 s6;
+ assert(pkt);
+ assert(target);
+ assert(pktLen > 0);
+
+ if ( o.sendEth() ){
+ eth_t *ethsd = eth_open_cached(o.getDevice());
+ eth_send(ethsd, pkt, pktLen);
+ }else{
+ if( o.ipv6() ){ /* IPv6 */
+ memset(&s6, 0, sizeof(struct sockaddr_in6));
+ s6.sin6_family=AF_INET6;
+ s6.sin6_addr = target->getIPv6Address();
+
+ /*
+ if( o.getMode()==TCP ){
+ dport=getDstPortFromTCPHeader(pkt, pktLen);
+ if(dport!=NULL)
+ s6.sin6_port = *dport;
+ else
+ nping_fatal(QT_3, "send_packet(): Could not determine TCP destination port.");
+ }
+ else if( o.getMode()==UDP){
+ dport=getDstPortFromUDPHeader(pkt, pktLen);
+ if(dport!=NULL)
+ s6.sin6_port = *dport;
+ else
+ nping_fatal(QT_3, "send_packet(): Could not determine UDP destination port.");
+ }
+ */
+
+ /* Linux doesn't seem to like sin6_port to be set to other value
+ * than 0. Unless we set it to zero, the sendto() call returns
+ * "Invalid argument" error. Does this happen in other systems?
+ * TODO: Should we check here if #ifdef LINUX and set the port to
+ * zero? */
+ s6.sin6_port=0;
+
+ res = Sendto("send_packet", rawfd, pkt, pktLen, 0, (struct sockaddr *)&s6, (int) sizeof(struct sockaddr_in6));
+ /*Sendto returns errors as -1 according to netutil.cc so lets catch that and return OP_FAILURE*/
+ if (res == -1) return OP_FAILURE;
+ }else{ /* IPv4 */
+ struct sockaddr_storage dst;
+ size_t dstlen;
+
+ dstlen = sizeof(dst);
+ target->getTargetSockAddr(&dst, &dstlen);
+ assert(dst.ss_family == AF_INET);
+ if( o.issetMTU() == true )
+ res = send_frag_ip_packet(rawfd, NULL, (struct sockaddr_in *) &dst, pkt, pktLen, o.getMTU() );
+ else
+ res = send_ip_packet_sd(rawfd, (struct sockaddr_in *) &dst, pkt, pktLen);
+ /*send_ip_packet_sd calls Sendto which returns errors as -1 according to netutil.cc so lets catch that and return OP_FAILURE*/
+ if (res == -1) return OP_FAILURE;
+ }
+ }
+ return OP_SUCCESS;
+} /* End of send_packet() */
+
+
+
+int print_dnet_interface(const struct intf_entry *entry, void *arg) {
+ if (entry==NULL)
+ return 0;
+ printf("*************************************************\n");
+ printf("intf_len = %d\n", entry->intf_len);
+ printf("intf_name = %s\n", entry->intf_name);
+ printf("intf_type = %u\n", entry->intf_type);
+ printf("intf_flags = %02x\n", entry->intf_flags);
+ printf("intf_mtu = %d\n", entry->intf_mtu);
+ printf("intf_addr = %s\n", addr_ntoa(&entry->intf_addr));
+ printf("intf_dst_addr = %s\n", addr_ntoa(&entry->intf_dst_addr));
+ printf("intf_link_addr = %s\n", addr_ntoa(&entry->intf_link_addr));
+ printf("intf_alias_num = %d\n", entry->intf_alias_num);
+ for(unsigned int i=0; i<entry->intf_alias_num; i++)
+ printf("intf_alias_addrs[%d] = %s\n", i, addr_ntoa(&entry->intf_alias_addrs[i]));
+ return 0;
+}
+
+
+/* Get a list of interfaces using dnet and intf_loop. */
+int print_interfaces_dnet() {
+ intf_t *it;
+ /* Initialize the interface array. */
+ it = intf_open();
+ if (!it)
+ fatal("%s: intf_open() failed. NULL descriptor", __func__);
+ if (intf_loop(it, print_dnet_interface, NULL) != 0)
+ fatal("%s: intf_loop() failed", __func__);
+ intf_close(it);
+ return 0;
+}
+
+
+
+/** @warning Returns pointer to an internal static buffer */
+struct sockaddr_storage *getSrcSockAddrFromIPPacket(u8 *pkt, size_t pktLen){
+ static struct sockaddr_storage ss;
+ struct sockaddr_in *s_ip4=(struct sockaddr_in *)&ss;
+ struct sockaddr_in6 *s_ip6=(struct sockaddr_in6 *)&ss;
+ struct ip *i4=(struct ip*)pkt;
+ memset(&ss, 0, sizeof(struct sockaddr_storage));
+
+ if(pkt==NULL || pktLen < 20)
+ return NULL;
+
+ if( i4->ip_v == 4 ){
+ s_ip4->sin_family=AF_INET;
+ memcpy(&(s_ip4->sin_addr.s_addr), pkt+12, 4);
+ }
+ else if(i4->ip_v == 6 ){
+ if(pktLen<40) /* Min length of an IPv6 header: 40 bytes*/
+ return NULL;
+ s_ip6->sin6_family=AF_INET6;
+ memcpy(s_ip6->sin6_addr.s6_addr, pkt+8, 16);
+ }
+ else{
+ return NULL;
+ }
+ return &ss;
+} /* End of getSrcSockAddrFromPacket() */
+
+
+
+
+
+u8 *getUDPheaderLocation(u8 *pkt, size_t pktLen){
+ struct ip *i4=(struct ip*)pkt;
+ if(pkt==NULL || pktLen < 40)
+ return NULL;
+
+ /* Packet is IPv4 */
+ if( i4->ip_v == 4 ){
+ if (i4->ip_p == IPPROTO_UDP) {
+ if( pktLen >= ((size_t)(i4->ip_hl*4 + 8)) ) /* We have a full IP+UDP packet */
+ return pkt+(i4->ip_hl*4);
+ }
+ else
+ return NULL;
+ }
+ /* Packet is IPv6 */
+ else if(i4->ip_v == 6 ){
+ if(pktLen<40 + 8 )
+ return NULL;
+ if( pkt[6] == IPPROTO_UDP ) /* Next Header is UDP? */
+ return pkt+40;
+ else /* Extension headers not supported, return NULL TODO: support it? */
+ return NULL;
+ }
+ else{
+ return NULL;
+ }
+ return NULL;
+} /* End of getUDPheaderLocation */
+
+
+u8 *getTCPheaderLocation(u8 *pkt, size_t pktLen){
+ struct ip *i4=(struct ip*)pkt;
+ if(pkt==NULL || pktLen < 40)
+ return NULL;
+
+ /* Packet is IPv4 */
+ if( i4->ip_v == 4 ){
+ if (i4->ip_p == IPPROTO_TCP) { /* Next proto is TCP? */
+ if( pktLen >= ((size_t)(i4->ip_hl*4 + 20)) ) /* We have a full IP+TCP packet */
+ return pkt+(i4->ip_hl*4);
+ }
+ else
+ return NULL;
+ }
+ /* Packet is IPv6 */
+ else if(i4->ip_v == 6 ){
+ if(pktLen<40 + 20 )
+ return NULL;
+ if( pkt[6] == IPPROTO_TCP ) /* Next Header is TCP? */
+ return pkt+40;
+ else /* Extension headers not supported, return NULL TODO: support it? */
+ return NULL;
+ }
+ else{
+ return NULL;
+ }
+
+ return NULL;
+
+} /* End of getTCPHeaderLocation() */
+
+
+
+
+/* Returns the IP protocol of the packet or -1 in case of failure */
+u8 getProtoFromIPPacket(u8 *pkt, size_t pktLen){
+ struct ip *i4=(struct ip*)pkt;
+ static u8 proto;
+
+ if(pkt==NULL || pktLen < 28)
+ return -1;
+
+ /* Packet is IPv4 */
+ if( i4->ip_v == 4 ){
+ proto = i4->ip_p;
+ return proto;
+ }
+
+ /* Packet is IPv6 */
+ else if(i4->ip_v == 6 ){
+ proto = pkt[6];
+ return proto;
+ }
+ return -1;
+} /* End of getProtoFromIPPacket() */
+
+
+
+/** @warning Returns pointer to an internal static buffer
+ * @return pointer on success, NULL in case of failure */
+u16 *getSrcPortFromIPPacket(u8 *pkt, size_t pktLen){
+ static u16 port;
+ u16 *pnt=NULL;
+ u8 *header=NULL;
+
+ if(pkt==NULL || pktLen < 28)
+ return NULL;
+
+ if((header=getTCPheaderLocation(pkt, pktLen))==NULL){
+ if ((header=getUDPheaderLocation(pkt, pktLen))==NULL)
+ return NULL;
+
+ }
+ pnt=(u16*)&(header[0]);
+ port= ntohs(*pnt);
+ return &port;
+} /* End of getSrcPortFromIPPacket() */
+
+
+/** @warning Returns pointer to an internal static buffer
+ * @return pointer on success, NULL in case of failure */
+u16 *getDstPortFromIPPacket(u8 *pkt, size_t pktLen){
+ static u16 port;
+ u16 *pnt=NULL;
+ u8 *header=NULL;
+
+ if(pkt==NULL || pktLen < 28)
+ return NULL;
+
+ if((header=getTCPheaderLocation(pkt, pktLen))==NULL){
+ if ((header=getUDPheaderLocation(pkt, pktLen))==NULL)
+ return NULL;
+ }
+ pnt=(u16*)&(header[2]);
+ port= ntohs(*pnt);
+ return &port;
+} /* End of getDstPortFromIPPacket() */
+
+
+/** @warning Returns pointer to an internal static buffer
+ * @return pointer on success, NULL in case of failure */
+u16 *getDstPortFromTCPHeader(u8 *pkt, size_t pktLen){
+ static u16 port;
+ u16 *pnt=NULL;
+
+ if(pkt==NULL || pktLen < 20)
+ return NULL;
+ pnt=(u16*)&(pkt[2]);
+ port= ntohs(*pnt);
+ return &port;
+} /* End of getDstPortFromTCPHeader() */
+
+
+/** @warning Returns pointer to an internal static buffer
+ * @return pointer on success, NULL in case of failure */
+u16 *getDstPortFromUDPHeader(u8 *pkt, size_t pktLen){
+ static u16 port;
+ u16 *pnt=NULL;
+
+ if(pkt==NULL || pktLen < 8)
+ return NULL;
+ pnt=(u16*)&(pkt[2]);
+ port= ntohs(*pnt);
+ return &port;
+} /* End of getDstPortFromUDPHeader() */
+
+
+int obtainRawSocket(){
+ int rawipsd=0;
+ int protocol=0;
+ int one=1;
+
+ if( o.ipv6() ){
+ switch( o.getMode() ){
+
+ case TCP:
+ protocol = IPPROTO_TCP;
+ break;
+
+ case UDP:
+ protocol = IPPROTO_UDP;
+ break;
+
+ case ICMP:
+ protocol = IPPROTO_ICMPV6;
+ break;
+
+ case ARP:
+ nping_warning(QT_2,"Warning: createRawSocket() should not be called in ARP mode.");
+ return 0;
+ break;
+
+ default:
+ nping_fatal(QT_3, "createRawSocket(): NpingOps::getMode() does not return a valid mode. Please report this bug.");
+ break;
+
+ }
+ if ((rawipsd = socket(AF_INET6, SOCK_RAW, protocol)) < 0 )
+ nping_fatal(QT_3,"Couldn't acquire IPv6 raw socket. Are you root?");
+
+ }else{
+ if ((rawipsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 )
+ nping_fatal(QT_3,"Couldn't acquire IPv4 raw socket. Are you root?");
+ /* Tell the kernel we are including our own IP Header (call to
+ * setsockopt passing option IP_HDRINCL) */
+ sethdrinclude(rawipsd);
+ }
+
+ /* Allow broadcast addresses */
+ if (setsockopt(rawipsd, SOL_SOCKET, SO_BROADCAST, (const char *)&one, sizeof(int)) == -1)
+ nping_warning(QT_2,"Failed to set SO_BROADCAST on raw socket.");
+
+ return rawipsd;
+} /* End of obtainRawSocket() */
+
+
+/** This function parses Linux file /proc/net/if_inet6 and returns a list
+ of network interfaces that are configured for IPv6.
+ @param ifbuff should be a buffer big enough to hold info for max_ifaces
+ interfaces.
+
+ Here is some info about the format of /proc/net/if_inet6, written by
+ Peter Bieringer and taken from:
+ http://tldp.org/HOWTO/Linux+IPv6-HOWTO/proc-net.html :
+
+ # cat /proc/net/if_inet6
+ 00000000000000000000000000000001 01 80 10 80 lo
+ +------------------------------+ ++ ++ ++ ++ ++
+ | | | | | |
+ 1 2 3 4 5 6
+
+ 1. IPv6 address displayed in 32 hexadecimal chars without colons as separator
+ 2. Netlink device number (interface index) in hexadecimal (see “ip addr” , too)
+ 3. Prefix length in hexadecimal
+ 4. Scope value (see kernel source “ include/net/ipv6.h” and “net/ipv6/addrconf.c” for more)
+ 5. Interface flags (see “include/linux/rtnetlink.h” and “net/ipv6/addrconf.c” for more)
+ 6. Device name
+
+
+ @warning This function is NOT portable. It will only work on Linux systems
+ and may not work in chroot-ed environments because it needs to be able
+ to access /proc/net/if_inet6.
+
+ */
+int getinterfaces_inet6_linux(if6_t *ifbuf, int max_ifaces){
+ FILE *if6file=NULL;
+ size_t i=0, j=0;
+ int readlines=0;
+ int parsed_ifs=0;
+ bool badaddr=false;
+ bool hasifname=false;
+ char buffer[2048];
+ char twobytes[3];
+ memset(buffer, 0, sizeof(buffer));
+
+ if(ifbuf==NULL || max_ifaces<=0)
+ nping_fatal(QT_3,"getinterfaces_inet6_linux() NULL values supplied");
+
+ /* TODO: Do we fatal() or should we just error and return OP_FAILURE? */
+ if ( !file_is_readable(PATH_PROC_IFINET6) )
+ nping_fatal(QT_3, "Couldn't get IPv6 interface information. File %s does not exist or you don't have read permissions.", PATH_PROC_IFINET6);
+ if( (if6file=fopen(PATH_PROC_IFINET6, "r"))==NULL )
+ nping_fatal(QT_3, "Failed to open %s.", PATH_PROC_IFINET6);
+
+ while( fgets(buffer,sizeof(buffer), if6file) ){
+
+ if(parsed_ifs>=max_ifaces)
+ break;
+
+ nping_print(DBG_4, "Read %s:%d: %s\n", PATH_PROC_IFINET6, ++readlines, buffer);
+
+ /* Check the line has the expected format ********************************/
+ /* Some versions of the kernel include colons in the IPv6 address, some
+ * others don't. E.g:
+ * fe80:0000:0000:0000:0333:a5ff:4444:9306 03 40 20 80 wlan0
+ * fe800000000000000333a5ff44449306 03 40 20 80 wlan0
+ * So what we do is to remove the colons so we can process the line
+ * no matter the format of the IPv6 addresses.
+ *
+ * TODO: Can interfaces with format eth0:1 appear on /proc/net/if_inet6?
+ * If they can, then we need to change the code to skip the last : */
+ removecolon(buffer);
+
+ /* 1. Check it has the correct length */
+ if( strlen(buffer) < strlen("00000000000000000000000000000001 01 80 10 80 lo") ){
+ continue;
+ }
+ /* 2. Check the inet6 address only contains hex digits */
+ for(i=0; i<32; i++){
+ if( !isxdigit(buffer[i]) ){
+ badaddr=true;
+ break;
+ }
+ }
+ if(badaddr){
+ badaddr=false;
+ continue;
+ }
+ /* 2. Check spaces are in the appropriate place */
+ if( buffer[32]!=' ' || buffer[35]!=' ' || buffer[38]!=' ' || buffer[41]!=' ' || buffer[44]!=' ' ){
+ continue;
+ }
+
+ /* 3. Check we have numbers in the part where we are supposed to have them */
+ if( !isxdigit( buffer[33] ) || !isxdigit( buffer[34] ) ||
+ !isxdigit( buffer[36] ) || !isxdigit( buffer[37] ) ||
+ !isxdigit( buffer[39] ) || !isxdigit( buffer[40] ) ||
+ !isxdigit( buffer[42] ) || !isxdigit( buffer[43] ) ){
+ continue;
+ }
+
+ /* 4. Check we actually have an interface name afterwards */
+ for(i=44; i<strlen(buffer); i++){
+ if( isalpha(buffer[i]) )
+ hasifname=true;
+ }
+ if(!hasifname){
+ hasifname=false;
+ continue;
+ }
+
+ /* If we get here means the read line has the expected format so we
+ * read the information and store it in a interface_info structure *
+ */
+
+ /* Store IPv6 address */
+ u8 ipv6addr[16];
+ for(i=0, j=0; j<16 && i<32; i+=2){
+ twobytes[0]=buffer[i];
+ twobytes[1]=buffer[i+1];
+ twobytes[2]='\0';
+ ipv6addr[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store Netlink device number */
+ u8 dev_no;
+ twobytes[0]=buffer[33]; twobytes[1]=buffer[34]; twobytes[2]='\0';
+ dev_no=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store prefix length */
+ u8 prefix_len;
+ twobytes[0]=buffer[36]; twobytes[1]=buffer[37]; twobytes[2]='\0';
+ prefix_len=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store scope value */
+ u8 scope_value;
+ twobytes[0]=buffer[39]; twobytes[1]=buffer[40]; twobytes[2]='\0';
+ scope_value=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store interface flags */
+ u8 dev_flags;
+ twobytes[0]=buffer[42]; twobytes[1]=buffer[43]; twobytes[2]='\0';
+ dev_flags=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store interface name */
+ char devname[DEVNAMELEN];
+ memset(devname, 0, DEVNAMELEN);
+ for(i=44, j=0; i<strlen(buffer) && j<DEVNAMELEN-1; i++){
+ if( buffer[i]==' ' || buffer[i]=='\n')
+ continue;
+ else
+ devname[j++]=buffer[i];
+ }
+ devname[j]='\0';
+
+
+ /* Once we have all the info, copy it to user supplied buffer */
+ memset(&ifbuf[parsed_ifs], 0, sizeof(if6_t));
+ memcpy( ifbuf[parsed_ifs].devname, devname, DEVNAMELEN);
+ struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ifbuf[parsed_ifs].ss;
+ s6->sin6_family=AF_INET6;
+ memcpy(s6->sin6_addr.s6_addr, ipv6addr, 16);
+ memcpy(ifbuf[parsed_ifs].addr, ipv6addr, 16);
+ ifbuf[parsed_ifs].netmask_bits=prefix_len;
+ ifbuf[parsed_ifs].dev_no=dev_no;
+ ifbuf[parsed_ifs].scope=scope_value;
+ ifbuf[parsed_ifs].flags=dev_flags;
+ /* ifbuf[parsed_ifs].mac = ??? (we don't know, we don't set it) */
+
+ parsed_ifs++;
+
+/* Debugging code: This should print the exact same lines that
+ * /proc/net/if_inet6 contains. (well, unless that kernel includes colons
+ * in the ipv6 address)
+ *
+ for(i=0; i<16; i++)
+ printf("%02x", ipv6addr[i]);
+ printf(" %02x", dev_no);
+ printf(" %02x", prefix_len);
+ printf(" %02x", scope_value);
+ printf(" %02x", dev_flags);
+ printf(" %8s\n", devname);
+ */
+
+ } /* End of loop */
+
+ /* Cleanup */
+ if(if6file)
+ fclose(if6file);
+ return parsed_ifs;
+} /* End of getinterfaces_inet6_linux() */
+
+
+/** This function parses Linux file /proc/net/ipv6_route and returns a list
+ of routes for IPv6 packets.
+ @param ifbuff should be a buffer big enough to hold info for max_routes
+ routes.
+
+ Here is some info about the format of /proc/net/if_inet6, written by
+ Peter Bieringer and taken from:
+ http://tldp.org/HOWTO/Linux+IPv6-HOWTO/proc-net.html :
+
+ # cat /proc/net/ipv6_route
+ 00000000000000000000000000000000 00 00000000000000000000000000000000 00
+ +------------------------------+ ++ +------------------------------+ ++
+ | | | |
+ 1 2 3 4
+
+ ¬ 00000000000000000000000000000000 ffffffff 00000001 00000001 00200200 lo
+ ¬ +------------------------------+ +------+ +------+ +------+ +------+ ++
+ ¬ | | | | | |
+ ¬ 5 6 7 8 9 10
+
+ 1. IPv6 destination network displayed in 32 hexadecimal chars without colons as separator
+ 2. IPv6 destination prefix length in hexadecimal
+ 3. IPv6 source network displayed in 32 hexadecimal chars without colons as separator
+ 4. IPv6 source prefix length in hexadecimal
+ 5. IPv6 next hop displayed in 32 hexadecimal chars without colons as separator
+ 6. Metric in hexadecimal
+ 7. Reference counter
+ 8. Use counter
+ 9. Flags
+10. Device name
+
+ @warning This function is NOT portable. It will only work on Linux systems
+ and may not work in chroot-ed environments because it needs to be able
+ to access /proc/net/ipv6_route.
+ */
+int getroutes_inet6_linux(route6_t *rtbuf, int max_routes){
+ FILE *route6file=NULL;
+ size_t i=0, j=0;
+ int readlines=0;
+ int parsed_routes=0;
+ bool badchars=false;
+ bool hasifname=false;
+ char buffer[2048];
+ char twobytes[3];
+ memset(buffer, 0, sizeof(buffer));
+
+ if(rtbuf==NULL || max_routes<=0)
+ nping_fatal(QT_3,"getroutes_inet6_linux() NULL values supplied");
+
+ /* TODO: Do we fatal() or should we just error and return OP_FAILURE? */
+ if ( !file_is_readable(PATH_PROC_IPV6ROUTE) )
+ nping_fatal(QT_3, "Couldn't get IPv6 route information. File %s does not exist or you don't have read permissions.", PATH_PROC_IPV6ROUTE);
+ if( (route6file=fopen(PATH_PROC_IPV6ROUTE, "r"))==NULL )
+ nping_fatal(QT_3, "Failed to open %s.", PATH_PROC_IPV6ROUTE);
+
+ while( fgets(buffer,sizeof(buffer), route6file) ){
+
+ if(parsed_routes>=max_routes)
+ break;
+
+ nping_print(DBG_4, "Read %s:%d: %s\n",PATH_PROC_IPV6ROUTE, ++readlines, buffer);
+
+ /* Check the line has the expected format ********************************/
+ /* Some versions of the kernel include colons in the IPv6 address, some
+ * others don't. So what we do is to remove the colons so we can process
+ * the line no matter the format of the IPv6 addresses.
+ *
+ * TODO: Can interfaces with format eth0:1 appear on /proc/net/ipv6_route?
+ * If they can, then we need to change the code to skip the last : */
+ removecolon(buffer);
+
+ /* 1. Check it has the correct length. */
+ size_t min_len=0;
+ min_len += 3*32; /* Three IPv6 addresses in hex */
+ min_len += 2*2; /* Two 8bit hex values (prefix lengths) */
+ min_len += 4*8; /* Four 32-bit hex values */
+ min_len += 1; /* I guess one char is the min for a device len */
+ min_len += 9; /* 9 spaces */
+ if( strlen(buffer) < min_len ){
+ continue;
+ }
+ /* 2. Check the first 140 characters only contain hex digits or spaces */
+ for(i=0; i<140; i++){
+ if( !isxdigit(buffer[i]) && buffer[i]!=' '){
+ badchars=true;
+ break;
+ }
+ }
+ if(badchars){
+ badchars=false;
+ continue;
+ }
+ /* 2. Check spaces are in the appropriate place */
+ if( buffer[32]!=' ' || buffer[71]!=' ' || buffer[122]!=' ' ||
+ buffer[35]!=' ' || buffer[104]!=' ' || buffer[131]!=' ' ||
+ buffer[68]!=' ' || buffer[113]!=' ' || buffer[140]!=' ' ){
+ continue;
+ }
+
+ /* 4. Check we actually have an interface name afterwards */
+ for(i=140; i<strlen(buffer); i++){
+ if( isalpha(buffer[i]) )
+ hasifname=true;
+ }
+ if(!hasifname){
+ hasifname=false;
+ continue;
+ }
+
+ /* If we get here means the read line has the expected format so we
+ * read the information and store it in a interface_info structure *
+ */
+
+ /* Store destination network address */
+ u8 dst_addr[16];
+ for(i=0, j=0; j<16 && i<32; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ dst_addr[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+ /* Store destination network prefix */
+ u8 dst_prefix;
+ twobytes[0]=buffer[33]; twobytes[1]=buffer[34]; twobytes[2]='\0';
+ dst_prefix=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store source network address */
+ u8 src_addr[16];
+ for(i=36, j=0; j<16 && i<68; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ src_addr[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+ /* Store source network prefix */
+ u8 src_prefix;
+ twobytes[0]=buffer[69]; twobytes[1]=buffer[70]; twobytes[2]='\0';
+ src_prefix=(u8)strtol(twobytes, NULL, 16);
+
+ /* Store next hop address */
+ u8 nh_addr[16];
+ for(i=72, j=0; j<16 && i<104; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ nh_addr[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store metric */
+ u8 metric[4];
+ for(i=105, j=0; j<4 && i<113; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ metric[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store reference counter */
+ u8 ref_count[4];
+ for(i=114, j=0; j<4 && i<122; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ ref_count[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store use counter */
+ u8 use_count[4];
+ for(i=123, j=0; j<4 && i<131; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ use_count[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store flags */
+ u8 flags[4];
+ for(i=132, j=0; j<4 && i<140; i+=2){
+ twobytes[0]=buffer[i]; twobytes[1]=buffer[i+1]; twobytes[2]='\0';
+ flags[j++]=(u8)strtol(twobytes, NULL, 16);
+ }
+
+ /* Store interface name */
+ char devname[DEVNAMELEN];
+ memset(devname, 0, DEVNAMELEN);
+ for(i=140, j=0; i<strlen(buffer) && j<DEVNAMELEN-1; i++){
+ if( buffer[i]==' ' || buffer[i]=='\n')
+ continue;
+ else
+ devname[j++]=buffer[i];
+ }
+ devname[j]='\0';
+
+ /* Once we have all the info, copy it to user supplied buffer */
+ memset(&rtbuf[parsed_routes], 0, sizeof(route6_t));
+ memcpy(rtbuf[parsed_routes].dst_net.s6_addr, dst_addr, 16);
+ rtbuf[parsed_routes].dst_prefix=dst_prefix;
+ memcpy(rtbuf[parsed_routes].src_net.s6_addr, src_addr, 16);
+ rtbuf[parsed_routes].src_prefix=src_prefix;
+ memcpy(rtbuf[parsed_routes].next_hop.s6_addr, nh_addr, 16);
+
+ /* TODO: Check the endianness stuff here is implemented right.
+ * The thing is that the part of the linux kernel that prints the info
+ * to /proc/net/ipv6_rout is the following:
+ * [From /net/ipv6/route.c ]
+ * 2427 seq_printf(m, " %08x %08x %08x %08x %8s\n",
+ * 2428 rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
+ * 2429 rt->u.dst.__use, rt->rt6i_flags,
+ * 2430 rt->rt6i_dev ? rt->rt6i_dev->name : "");
+ *
+ * So as they are actually printing 32bit values with %08x, they are
+ * getting printed out in network byte order (big endian) so we call
+ * ntohl() for each of them so we actually convert them to the right
+ * representation in the current machine. With 8-bit values we have no
+ * problem because they are converted to binary using strtol() and it
+ * handles endianness by itself. Am I doing anything wrong here?
+ * */
+ memcpy(&rtbuf[parsed_routes].metric, metric, 4);
+ rtbuf[parsed_routes].metric=ntohl(rtbuf[parsed_routes].metric);
+ memcpy(&rtbuf[parsed_routes].ref_count, ref_count, 4);
+ rtbuf[parsed_routes].ref_count=ntohl(rtbuf[parsed_routes].ref_count);
+ memcpy(&rtbuf[parsed_routes].use_count, use_count, 4);
+ rtbuf[parsed_routes].use_count=ntohl(rtbuf[parsed_routes].use_count);
+ memcpy(&rtbuf[parsed_routes].flags, flags, 4);
+ rtbuf[parsed_routes].flags=ntohl(rtbuf[parsed_routes].flags);
+ memcpy(rtbuf[parsed_routes].devname, devname, DEVNAMELEN);
+
+/* Debugging code: This should print the exact same lines that
+ * /proc/net/if_inet6 contains. (well, unless that kernel includes colons
+ * in the ipv6 address)
+ *
+ for(i=0; i<16; i++)
+ printf("%02x", rtbuf[parsed_routes].dst_net.s6_addr[i]);
+
+ printf(" %02x ", rtbuf[parsed_routes].dst_prefix);
+
+ for(i=0; i<16; i++)
+ printf("%02x", rtbuf[parsed_routes].src_net.s6_addr[i]);
+
+ printf(" %02x ", rtbuf[parsed_routes].src_prefix);
+
+ for(i=0; i<16; i++)
+ printf("%02x", rtbuf[parsed_routes].next_hop.s6_addr[i]);
+
+ printf(" %08x", rtbuf[parsed_routes].metric);
+ printf(" %08x", rtbuf[parsed_routes].ref_count);
+ printf(" %08x", rtbuf[parsed_routes].use_count);
+ printf(" %08x", rtbuf[parsed_routes].flags);
+ printf(" %8s\n", rtbuf[parsed_routes].devname);
+*/
+ parsed_routes++;
+
+ } /* End of loop */
+
+ /* Cleanup */
+ if(route6file)
+ fclose(route6file);
+ return parsed_routes;
+} /* End of getroutes_inet6_linux() */
+
+
+/** This function takes a sockaddr_storage pointer that MUST contain a valid
+ * IPv6 address (a sockaddr_in6 struct with sin6_family set to AF_INET6),
+ * and returns the best route entry for the supplied destination.
+ * The route entries are read from /proc/net/ipv6_route through function
+ * getroutes_inet6_linux().
+ * @warning This function is NOT portable. It will only work on Linux systems
+ * and may not work in chroot-ed environments because it needs to be able
+ * to access /proc/net/ipv6_route.
+ * @warning It returns NULL in case of error. Check for it or you'll segfault.
+ * @warning returned pointer points to a static buffer that subsequent calls
+ * will overwrite. */
+route6_t *route_dst_ipv6_linux(const struct sockaddr_storage *const dst){
+ struct sockaddr_in6 *dstsin6=NULL; /* Cast for supplied sockaddr_storage var */
+ route6_t routes6[64]; /* Array of IPv6 routes */
+ int total_routes6=0; /* Number of returned routes */
+ static route6_t theone; /* Stores the best route we find */
+ route6_t *def_gw=NULL; /* Stores default gateway */
+ int best_match=0; /* Max number of bits that we've matched */
+ int curr_match=0; /* Matching bits in current route */
+ u8 zero_addr[16]; /* Just to compare route to addr "::" */
+ memset(zero_addr, 0, 16);
+ dstsin6=(struct sockaddr_in6 *)dst;
+
+ if(dst==NULL) return NULL;
+ if(dstsin6->sin6_family!=AF_INET6) return NULL;
+
+ /* Let's parse /proc/net/ipv6_route and get a list of routes */
+ if ( (total_routes6=getroutes_inet6_linux(routes6, 64)) <= 0 )
+ return NULL;
+
+ /* Now we go over the whole route list and select the match that has the
+ * largest prefix length */
+
+ for(int i=0; i<total_routes6; i++){
+ /* Check how many bits they have in common */
+ curr_match=bitcmp(dstsin6->sin6_addr.s6_addr, routes6[i].dst_net.s6_addr, 16);
+
+ /* Select only the best match (always taking into account that
+ * our dst address needs to match at least dst_prefix bits. */
+ if( curr_match > best_match && curr_match>=routes6[i].dst_prefix){
+ best_match=curr_match;
+ memcpy(&theone, &routes6[i], sizeof(route6_t));
+ }
+ /* There was no match, but we check if the route is actually "::"
+ * (like 0.0.0.0 in IPv4). If it is, we store it, just in case we
+ * end up without a better route. */
+ else if ( !memcmp( routes6[i].dst_net.s6_addr, zero_addr, 16) ){
+ if(def_gw==NULL){
+ def_gw=&routes6[i];
+ }
+ else if( !strncmp("lo", def_gw->devname, 2) ){
+ /* If the route we have is through the loopback interface,
+ * overwrite it, we prefer to choose any other device as
+ * the default gateway. We just compare the first two
+ * letters cause in Linux the interface is called "lo" but
+ * on BSD is usually called lo0. */
+ def_gw=&routes6[i];
+ }
+ }
+ }
+ if( best_match==0 ){
+ if(def_gw!=NULL)
+ memcpy(&theone, def_gw, sizeof(route6_t));
+ else return NULL;
+ }
+ return &theone;
+} /* End of route_dst_ipv6() */
diff --git a/nping/utils_net.h b/nping/utils_net.h
new file mode 100644
index 0000000..1232ae3
--- /dev/null
+++ b/nping/utils_net.h
@@ -0,0 +1,155 @@
+
+/***************************************************************************
+ * utils_net.cc -- Miscellaneous network-related functions that perform *
+ * various tasks. *
+ * *
+ ***********************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 "NpingTarget.h"
+
+#ifndef UTILS_NET_H
+#define UTILS_NET_H 1
+
+#ifndef NETINET_IN_SYSTM_H /* This guarding is needed for at least some versions of OpenBSD */
+#include <netinet/in_systm.h> /* defines n_long needed for netinet/ip.h */
+#define NETINET_IN_SYSTM_H
+#endif
+#ifndef NETINET_IP_H /* This guarding is needed for at least some versions of OpenBSD */
+#include <netinet/ip.h>
+#define NETINET_IP_H
+#endif
+
+int atoIP(const char *hostname, struct in_addr *dst);
+int atoIP(const char *hostname, struct sockaddr_storage *ss, int family);
+char *IPtoa(u32 i);
+char *IPtoa(struct sockaddr_storage *ss);
+char *IPtoa(struct in_addr addr);
+char *IPtoa(struct in6_addr addr);
+char *IPtoa(struct sockaddr_storage ss);
+char *IPtoa(struct sockaddr_storage *ss, int family);
+char *IPtoa(u8 *ipv6addr);
+u16 sockaddr2port(struct sockaddr_storage *ss);
+u16 sockaddr2port(struct sockaddr_storage ss);
+u16 sockaddr2port(struct sockaddr_in *s4);
+u16 sockaddr2port(struct sockaddr_in6 *s6);
+int setsockaddrfamily(struct sockaddr_storage *ss, int family);
+int setsockaddrany(struct sockaddr_storage *ss);
+bool isICMPType(u8 type);
+bool isICMPCode(u8 code);
+bool isICMPCode(u8 code, u8 type);
+int getPacketStrInfo(const char *proto, const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen, struct sockaddr_storage *ss_src, struct sockaddr_storage *ss_dst);
+int getPacketStrInfo(const char *proto, const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen);
+int getNetworkInterfaceName(u32 destination, char *dev);
+int getNetworkInterfaceName(struct sockaddr_storage *dst, char *dev);
+int nping_getpts_simple(const char *origexpr, u16 **list, int *count);
+int resolveCached(char *host, struct sockaddr_storage *ss, size_t *sslen,int pf) ;
+struct hostent *gethostbynameCached(char *host);
+struct hostent *hostentcpy(struct hostent *src);
+int hostentfree(struct hostent *src);
+int parseMAC(const char *txt, u8 *targetbuff);
+char *MACtoa(u8 *mac);
+const char *arppackethdrinfo(const u8 *packet, u32 len, int detail );
+int arppackethdrinfo(const u8 *packet, u32 len, u8 *dstbuff, u32 dstlen);
+int tcppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen, int detail, struct sockaddr_storage *src, struct sockaddr_storage *dst);
+int udppackethdrinfo(const u8 *packet, size_t len, u8 *dstbuff, size_t dstlen, int detail, struct sockaddr_storage *src, struct sockaddr_storage *dst);
+const char *getRandomTextPayload();
+int send_packet(NpingTarget *target, int rawfd, u8 *pkt, size_t pktLen);
+int print_dnet_interface(const struct intf_entry *entry, void *arg) ;
+int print_interfaces_dnet();
+struct sockaddr_storage *getSrcSockAddrFromIPPacket(u8 *pkt, size_t pktLen);
+u8 *getUDPheaderLocation(u8 *pkt, size_t pktLen);
+u8 *getTCPheaderLocation(u8 *pkt, size_t pktLen);
+u8 getProtoFromIPPacket(u8 *pkt, size_t pktLen);
+u16 *getSrcPortFromIPPacket(u8 *pkt, size_t pktLen);
+u16 *getDstPortFromIPPacket(u8 *pkt, size_t pktLen);
+u16 *getDstPortFromTCPHeader(u8 *pkt, size_t pktLen);
+u16 *getDstPortFromUDPHeader(u8 *pkt, size_t pktLen);
+int obtainRawSocket();
+
+#define DEVNAMELEN 16
+#define PATH_PROC_IFINET6 "/proc/net/if_inet6"
+typedef struct ipv6_interface{
+ char devname[DEVNAMELEN]; /* Interface name */
+ struct sockaddr_storage ss; /* Address as a sockaddr_storage var */
+ u8 addr[16]; /* Address as a 128bit array */
+ u16 netmask_bits; /* Prefix length */
+ u8 dev_no; /* Netlink device number */
+ u8 scope; /* Scope */
+ u8 flags; /* Interface flags */
+ u8 mac[6]; /* MAC addr. (I wish we could get it)*/
+}if6_t;
+
+int getinterfaces_inet6_linux(if6_t *ifbuf, int max_ifaces);
+
+#define PATH_PROC_IPV6ROUTE "/proc/net/ipv6_route"
+
+typedef struct sys_route6 {
+ struct in6_addr dst_net; /* Destination Network */
+ u8 dst_prefix; /* Destination Prefix Length */
+ struct in6_addr src_net; /* Source Network */
+ u8 src_prefix; /* Source Prefix Length */
+ struct in6_addr next_hop; /* Gateway - 0 if none */
+ u32 metric; /* Metric */
+ u32 ref_count; /* Reference Counter */
+ u32 use_count; /* Use Counter */
+ u32 flags; /* Flags */
+ char devname[DEVNAMELEN]; /* Device name */
+}route6_t;
+
+int getroutes_inet6_linux(route6_t *rtbuf, int max_routes);
+route6_t *route_dst_ipv6_linux(const struct sockaddr_storage *const dst);
+
+#endif /* UTILS_NET_H */
diff --git a/nping/winfix.cc b/nping/winfix.cc
new file mode 100644
index 0000000..258c210
--- /dev/null
+++ b/nping/winfix.cc
@@ -0,0 +1,264 @@
+
+/***************************************************************************
+ * winfix.cc -- A few trivial windows-compatibility-related functions that *
+ * are specific to Nping. Most of this has been moved into nbase so it can *
+ * be shared. *
+ * *
+ ***********************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/
+ *
+ ***************************************************************************/
+
+/* $Id: */
+
+#include "winfix.h"
+#include "nping.h"
+//#include "tcpip.h"
+#include "NpingOps.h"
+#include "output.h"
+#include <Packet32.h>
+#include <shellapi.h>
+
+#ifdef _MSC_VER
+# include <delayimp.h>
+#endif
+
+extern NpingOps o;
+
+/* internal functions */
+static void win_cleanup(void);
+
+/* The code that has no preconditions to being called, so it can be
+ executed before even Nping options parsing (so o.getDebugging() and the
+ like don't need to be used. Its main function is to do
+ WSAStartup() as some of the option parsing code does DNS
+ resolution */
+void win_pre_init() {
+ WORD werd;
+ WSADATA data;
+
+ werd = MAKEWORD( 2, 2 );
+ if( (WSAStartup(werd, &data)) !=0 )
+ fatal("failed to start winsock.\n");
+}
+
+/* Check if the NPCAP service is running on Windows, and try to start it if it's
+ not. Return true if it was running or we were able to start it, false
+ otherwise. */
+static bool start_service(const char *svcname) {
+ SC_HANDLE scm, npf;
+ SERVICE_STATUS service;
+ bool npf_running;
+ int ret;
+ char startsvc[32];
+
+ scm = NULL;
+ npf = NULL;
+
+ scm = OpenSCManager(NULL, NULL, 0);
+ if (scm == NULL) {
+ error("Error in OpenSCManager");
+ goto quit_error;
+ }
+ npf = OpenService(scm, svcname, SC_MANAGER_CONNECT | SERVICE_QUERY_STATUS);
+ if (npf == NULL) {
+ /* No need to warn at this point: we'll check later
+ error("Error in OpenService");
+ */
+ goto quit_error;
+ }
+ if (!QueryServiceStatus(npf, &service)) {
+ error("Error in QueryServiceStatus");
+ goto quit_error;
+ }
+ npf_running = (service.dwCurrentState & SERVICE_RUNNING) != 0;
+ CloseServiceHandle(scm);
+ CloseServiceHandle(npf);
+
+ if (npf_running) {
+ if (o.getDebugging() > DBG_1)
+ printf("%s service is already running.\n", svcname);
+ return true;
+ }
+
+ /* Service is not running. Try to start it. */
+
+ if (o.getDebugging() > DBG_1)
+ printf("%s service is already running.\n", svcname);
+
+ Snprintf(startsvc, 32, "start %s", svcname);
+ ret = (int) ShellExecute(0, "runas", "net.exe", startsvc, 0, SW_HIDE);
+ if (ret <= 32) {
+ error("Unable to start %s service: ShellExecute returned %d.\n\
+Resorting to unprivileged (non-administrator) mode.", svcname, ret);
+ return false;
+ }
+
+ return true;
+
+quit_error:
+ if (scm != NULL)
+ CloseServiceHandle(scm);
+ if (npf != NULL)
+ CloseServiceHandle(npf);
+
+ return false;
+}
+
+/* Restrict where we're willing to load DLLs from to prevent DLL hijacking. */
+static void init_dll_path()
+{
+ BOOL (WINAPI *SetDllDirectory)(LPCTSTR);
+
+ SetDllDirectory = (BOOL (WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
+ if (SetDllDirectory == NULL) {
+ char nmapdir[MAX_PATH];
+
+ /* SetDllDirectory is not available before XP SP1. Instead, set
+ the current directory to the home of the executable (instead
+ of where a malicious DLL may be). */
+ if (GetModuleFileName(NULL, nmapdir, sizeof(nmapdir)) == 0 ||
+ GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ pfatal("Error in GetModuleFileName");
+ }
+ if (SetCurrentDirectory(nmapdir))
+ pfatal("Error in SetCurrentDirectory");
+ } else {
+ if (SetDllDirectory("") == 0)
+ pfatal("Error in SetDllDirectory(\"\")");
+ }
+}
+
+/* If we find the Npcap driver, allow Nping to load Npcap DLLs from the "\System32\Npcap" directory. */
+static void init_npcap_dll_path()
+{
+ BOOL(WINAPI *SetDllDirectory)(LPCTSTR);
+ char sysdir_name[512];
+ int len;
+
+ SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
+ if (SetDllDirectory == NULL) {
+ pfatal("Error in SetDllDirectory");
+ }
+ else {
+ len = GetSystemDirectory(sysdir_name, 480); // be safe
+ if (!len)
+ pfatal("Error in GetSystemDirectory (%d)", GetLastError());
+ strcat(sysdir_name, "\\Npcap");
+ if (SetDllDirectory(sysdir_name) == 0)
+ pfatal("Error in SetDllDirectory(\"System32\\Npcap\")");
+ }
+}
+
+/* Requires that win_pre_init() has already been called, also that
+ options processing has been done so that o.debugging is
+ available */
+void win_init()
+{
+ init_dll_path();
+
+ // Try to initialize Npcap
+#ifdef _MSC_VER
+ __try
+#endif
+ {
+ const char *pcap_ver = NULL;
+
+ if(o.getDebugging() >= DBG_2) printf("Trying to initialize Windows pcap engine\n");
+
+ /* o.getIsRoot() will be false at this point if the user asked for
+ --unprivileged. In that case don't bother them with a
+ potential UAC dialog when starting NPF. */
+ if (o.isRoot()) {
+ if (!start_service("npcap")) {
+ if(o.getDebugging() >= DBG_0) {
+ error("Unable to start the npcap service");
+ }
+ o.setHavePcap(false);
+ }
+ }
+
+ init_npcap_dll_path();
+
+ pcap_ver = PacketGetVersion();
+ if (o.getDebugging() >= DBG_1)
+ printf("Packet.dll present, library version %s\n", pcap_ver);
+
+#ifdef _MSC_VER
+ if(FAILED(__HrLoadAllImportsForDll("wpcap.dll")))
+ {
+ error("WARNING: Failed to load wpcap.dll. Nmap may not function.\n");
+ o.setHavePcap(false);
+ }
+#endif
+ if(o.getDebugging() >= DBG_1)
+ printf("wpcap.dll present, library version: %s\n", pcap_lib_version());
+
+ }
+#ifdef _MSC_VER
+ __except (1) {
+ error("WARNING: Could not import all necessary Npcap functions. You may need to upgrade to the latest version from https://npcap.com. Resorting to connect() mode -- Nmap may not function completely");
+ o.setHavePcap(false);
+ }
+#endif
+
+ if (!o.havePcap())
+ o.setIsRoot(0);
+ atexit(win_cleanup);
+}
+
+
+static void win_cleanup(void)
+{
+ WSACleanup();
+}
diff --git a/nping/winfix.h b/nping/winfix.h
new file mode 100644
index 0000000..c53b0cc
--- /dev/null
+++ b/nping/winfix.h
@@ -0,0 +1,35 @@
+#ifndef WINFIX_H
+#define WINFIX_H
+
+#include <winsock2.h>
+#include <windows.h>
+#include <iphlpapi.h>
+
+#ifndef EXTERNC
+# ifdef __cplusplus
+# define EXTERNC extern "C"
+# else
+# define EXTERNC extern
+# endif
+#endif
+
+// windows-specific options
+
+/* (exported) functions */
+/* The code that has no preconditions to being called, so it can be
+ executed before even Nmap options parsing (so o.debugging and the
+ like don't need to be used. Its main function is to do
+ WSAStartup() as some of the option parsing code does DNS
+ resolution */
+EXTERNC void win_pre_init();
+
+/* Requires that win_pre_init() has already been called, also that
+ options processing has been done so that o.debugging is
+ available */
+EXTERNC void win_init();
+EXTERNC void win_barf(const char *msg);
+#endif
+
+
+
+