mirror of
https://github.com/nmap/nmap.git
synced 2025-12-15 04:09:01 +00:00
This is a refactoring of target parsing that stores different types of target specifications as different classes. The eventual intention is to allow easy iteration over each specification for the purpose of IPv6 multicast host discovery.
1895 lines
83 KiB
C++
1895 lines
83 KiB
C++
|
|
/***************************************************************************
|
|
* 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-2012 Insecure.Com LLC. Nmap is *
|
|
* also a registered trademark of Insecure.Com LLC. This program is free *
|
|
* software; you may redistribute and/or modify it under the terms of the *
|
|
* GNU General Public License as published by the Free Software *
|
|
* Foundation; Version 2 with the clarifications and exceptions described *
|
|
* below. This guarantees your right to use, modify, and redistribute *
|
|
* this software under certain conditions. If you wish to embed Nmap *
|
|
* technology into proprietary software, we sell alternative licenses *
|
|
* (contact sales@insecure.com). Dozens of software vendors already *
|
|
* license Nmap technology such as host discovery, port scanning, OS *
|
|
* detection, version detection, and the Nmap Scripting Engine. *
|
|
* *
|
|
* Note that the GPL places important restrictions on "derived works", yet *
|
|
* it does not provide a detailed definition of that term. To avoid *
|
|
* misunderstandings, we interpret that term as broadly as copyright law *
|
|
* allows. For example, we consider an application to constitute a *
|
|
* "derivative work" for the purpose of this license if it does any of the *
|
|
* following: *
|
|
* o Integrates source code from Nmap *
|
|
* o Reads or includes Nmap copyrighted data files, such as *
|
|
* nmap-os-db or nmap-service-probes. *
|
|
* o Executes Nmap and parses the results (as opposed to typical shell or *
|
|
* execution-menu apps, which simply display raw Nmap output and so are *
|
|
* not derivative works.) *
|
|
* o Integrates/includes/aggregates Nmap into a proprietary executable *
|
|
* installer, such as those produced by InstallShield. *
|
|
* o Links to a library or executes a program that does any of the above *
|
|
* *
|
|
* The term "Nmap" should be taken to also include any portions or derived *
|
|
* works of Nmap, as well as other software we distribute under this *
|
|
* license such as Zenmap, Ncat, and Nping. This list is not exclusive, *
|
|
* but is meant to clarify our interpretation of derived works with some *
|
|
* common examples. Our interpretation applies only to Nmap--we don't *
|
|
* speak for other people's GPL works. *
|
|
* *
|
|
* If you have any questions about the GPL licensing restrictions on using *
|
|
* Nmap in non-GPL works, we would be happy to help. As mentioned above, *
|
|
* we also offer alternative license to integrate Nmap into proprietary *
|
|
* applications and appliances. These contracts have been sold to dozens *
|
|
* of software vendors, and generally include a perpetual license as well *
|
|
* as providing for priority support and updates. They also fund the *
|
|
* continued development of Nmap. Please email sales@insecure.com for *
|
|
* further information. *
|
|
* *
|
|
* As a special exception to the GPL terms, Insecure.Com LLC grants *
|
|
* permission to link the code of this program with any version of the *
|
|
* OpenSSL library which is distributed under a license identical to that *
|
|
* listed in the included docs/licenses/OpenSSL.txt file, and distribute *
|
|
* linked combinations including the two. You must obey the GNU GPL in all *
|
|
* respects for all of the code used other than OpenSSL. If you modify *
|
|
* this file, you may extend this exception to your version of the file, *
|
|
* but you are not obligated to do so. *
|
|
* *
|
|
* If you received these files with a written license agreement or *
|
|
* contract stating terms other than the terms above, then that *
|
|
* alternative license agreement takes precedence over these comments. *
|
|
* *
|
|
* 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 (none *
|
|
* have been found so far). *
|
|
* *
|
|
* Source code also allows you to port Nmap to new platforms, fix bugs, *
|
|
* and add new features. You are highly encouraged to send your changes *
|
|
* to the dev@nmap.org mailing list for possible incorporation into the *
|
|
* main distribution. By sending these changes to Fyodor or one of the *
|
|
* Insecure.Org development mailing lists, or checking them into the Nmap *
|
|
* source code repository, it is understood (unless you specify otherwise) *
|
|
* that you are offering the Nmap Project (Insecure.Com LLC) the *
|
|
* unlimited, non-exclusive right to reuse, modify, and relicense the *
|
|
* code. Nmap will always be available Open Source, but this is important *
|
|
* because the inability to relicense code has caused devastating problems *
|
|
* for other Free Software projects (such as KDE and NASM). We also *
|
|
* occasionally relicense the code to third parties as discussed above. *
|
|
* If you wish to specify special license conditions of your *
|
|
* contributions, just say so when you send them. *
|
|
* *
|
|
* 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 Nmap *
|
|
* license file for more details (it's in a COPYING file included with *
|
|
* Nmap, and also available from https://svn.nmap.org/nmap/COPYING *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#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];
|
|
|
|
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},
|
|
{"mss", required_argument, 0, 0},
|
|
{"ws", required_argument, 0, 0},
|
|
{"ts", required_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 */
|
|
/* All these are for the ARP Operation Code */
|
|
{"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},
|
|
/* These are for the 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},
|
|
{"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-file", 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},
|
|
{"host-timeout", 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 */
|
|
//optind = 1; /* so it can be called multiple times */
|
|
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 (optcmp(long_options[option_index].name, "tcp-connect") == 0) {
|
|
if( o.issetMode() && o.getMode()!=TCP_CONNECT)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "tcp") == 0) {
|
|
if( o.issetMode() && o.getMode()!=TCP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "udp") == 0) {
|
|
if( o.issetMode() && o.getMode()!=UDP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "icmp") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ICMP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "arp") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ARP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "traceroute") == 0 ||
|
|
optcmp(long_options[option_index].name, "tr") == 0) {
|
|
o.enableTraceroute();
|
|
|
|
/* Now shortcuts that we support but that are not actual modes */
|
|
} else if (optcmp(long_options[option_index].name, "arp-request") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ARP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "arp-reply") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ARP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "rarp-request") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ARP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "rarp-reply") == 0) {
|
|
if( o.issetMode() && o.getMode()!=ARP)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "destination-unreachable") == 0 ||
|
|
optcmp(long_options[option_index].name, "dest-unr") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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( optcmp(long_options[option_index].name, "echo-request") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "timestamp") == 0 ||
|
|
optcmp(long_options[option_index].name, "timestamp-request") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "information") == 0 ||
|
|
optcmp(long_options[option_index].name, "information-request") == 0 ) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "netmask") == 0 ||
|
|
optcmp(long_options[option_index].name, "netmask-request") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "seq") == 0) {
|
|
if ( parse_u32(optarg, &aux32) != OP_SUCCESS )
|
|
outFatal(QT_3, "Invalid TCP Sequence number. Value must be 0<=N<2^32.");
|
|
else
|
|
o.setTCPSequence( aux32 );
|
|
/* TCP Flags */
|
|
} else if (optcmp(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){
|
|
outFatal(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 )
|
|
outFatal(QT_3, "Invalid format in --flag. Make sure you specify a comma-separed list that contains 3-charater 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';
|
|
outFatal(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]) )
|
|
outFatal(QT_3, "Invalid TCP flag supplied (%c). If you want to specify flags using a number you must add prefix \"0x\"", optarg[f]);
|
|
else
|
|
outFatal(QT_3, "Invalid TCP flag supplied: %c", optarg[f]);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* TCP Acknowledgement number */
|
|
} else if (optcmp(long_options[option_index].name, "ack") == 0) {
|
|
if ( parse_u32(optarg, &aux32) != OP_SUCCESS )
|
|
outFatal(QT_3, "Invalid TCP ACK number. Value must be 0<=N<2^32.");
|
|
else
|
|
o.setTCPAck( aux32 );
|
|
/* TCP Window size */
|
|
} else if (optcmp(long_options[option_index].name, "win") == 0) {
|
|
if ( parse_u16(optarg, &aux16) != OP_SUCCESS )
|
|
outFatal(QT_3, "Invalid TCP Window size. Value must be 0<=N<65535.");
|
|
else
|
|
o.setTCPWindow( aux16 );
|
|
/* Set a bad TCP checksum */
|
|
} else if (optcmp(long_options[option_index].name, "badsum") == 0) {
|
|
o.enableBadsum();
|
|
/* TCP maximum segment size option TODO: Implement this */
|
|
} else if (optcmp(long_options[option_index].name, "mss") == 0) {
|
|
/* TCP window scale option TODO: Implement this */
|
|
} else if (optcmp(long_options[option_index].name, "ws") == 0) {
|
|
/* TCP timestamp option TODO: Implement this */
|
|
} else if (optcmp(long_options[option_index].name, "ts") == 0) {
|
|
|
|
|
|
/* ICMP OPTIONS **************************************************************/
|
|
/* ICMP Type */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-type") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Type. Value must be 0<=N<=255.");
|
|
/* Warn if ICMP Type is not RFC-compliant */
|
|
if( !isICMPType(aux8) )
|
|
outError(QT_1, "Warning: Specified ICMP type (%d) is not RFC compliant.", aux8);
|
|
/* ICMP Code */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-code") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Code. Value must be 0<=N<=255.");
|
|
/* ICMP Identification field */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-id") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Identifier. Value must be 0<=N<2^16.");
|
|
/* ICMP Sequence number */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-seq") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Sequence number. Value must be 0<=N<2^16.");
|
|
/* ICMP Redirect Address */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-redirect-addr") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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)
|
|
outFatal(QT_3, "Could not resolve specified ICMP Redirect Address.");
|
|
else
|
|
o.setICMPRedirectAddress( aux_ip4 );
|
|
}
|
|
/* ICMP Parameter problem pointer */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-param-pointer") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Parameter problem pointer. Value must be 0<=N<=255..");
|
|
/* ICMP Router Advertisement lifetime */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-advert-lifetime") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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
|
|
outFatal(QT_3, "Invalid ICMP Router advertisement lifetime. Value must be 0<=N<2^16..");
|
|
/* ICMP Router Advertisement entry */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-advert-entry") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "icmp-orig-time") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "icmp-recv-time") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 trasnmit timestamp */
|
|
} else if (optcmp(long_options[option_index].name, "icmp-trans-time") == 0) {
|
|
if ( o.issetMode() && o.getMode() != ICMP )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "arp-type") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-type") == 0 ||
|
|
optcmp(long_options[option_index].name, "arp-code") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-code") == 0 ||
|
|
optcmp(long_options[option_index].name, "arp-operation") == 0 ||
|
|
optcmp(long_options[option_index].name, "arp-op") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-operation") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-op") == 0 ){
|
|
if ( o.issetMode() && o.getMode() != ARP ){
|
|
outFatal(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 ){
|
|
outFatal(QT_3, "Invalid ARP type/operation code");
|
|
}else{
|
|
o.setARPOpCode(aux16);
|
|
}
|
|
/* ARP Sender MAC Address */
|
|
} else if (optcmp(long_options[option_index].name, "arp-sender-mac") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-sender-mac") == 0 ){
|
|
if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){
|
|
outFatal(QT_3, "Invalid ARP Sender MAC address.");
|
|
}else{
|
|
o.setARPSenderHwAddr(auxmac);
|
|
}
|
|
/* ARP Sender IP Address */
|
|
} else if (optcmp(long_options[option_index].name, "arp-sender-ip") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-sender-ip") == 0 ){
|
|
if ( atoIP(optarg, &aux_ip4)!=OP_SUCCESS ){
|
|
outFatal(QT_3, "Invalid ARP Sender IP address.");
|
|
}else{
|
|
o.setARPSenderProtoAddr(aux_ip4);
|
|
}
|
|
/* ARP Target MAC Address */
|
|
} else if (optcmp(long_options[option_index].name, "arp-target-mac") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-target-mac") == 0 ){
|
|
if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){
|
|
outFatal(QT_3, "Invalid ARP Target MAC address.");
|
|
}else{
|
|
o.setARPTargetHwAddr(auxmac);
|
|
}
|
|
/* ARP Target IP Address */
|
|
} else if (optcmp(long_options[option_index].name, "arp-target-ip") == 0 ||
|
|
optcmp(long_options[option_index].name, "rarp-target-ip") == 0 ){
|
|
if ( atoIP(optarg, &aux_ip4)!=OP_SUCCESS ){
|
|
outFatal(QT_3, "Invalid ARP Target IP address.");
|
|
}else{
|
|
o.setARPTargetProtoAddr(aux_ip4);
|
|
}
|
|
|
|
|
|
/* ETHERNET OPTIONS **********************************************************/
|
|
/* Destination MAC address */
|
|
} else if (optcmp(long_options[option_index].name, "dest-mac") == 0 ){
|
|
if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){
|
|
outFatal(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 (optcmp(long_options[option_index].name, "source-mac") == 0 ||
|
|
optcmp(long_options[option_index].name, "spoof-mac") == 0 ){
|
|
if ( parseMAC(optarg, auxmac) != OP_SUCCESS ){
|
|
outFatal(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 (optcmp(long_options[option_index].name, "ethertype") == 0 ||
|
|
optcmp(long_options[option_index].name, "ethtype") == 0 ||
|
|
optcmp(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{
|
|
outFatal(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 (optcmp(long_options[option_index].name, "dest-ip") == 0 ){
|
|
o.targets.addSpec( strdup(optarg) );
|
|
/* IP Type of service*/
|
|
} else if (optcmp(long_options[option_index].name, "tos") == 0 ){
|
|
if ( parse_u8(optarg, &aux8) == OP_SUCCESS ){
|
|
o.setTOS(aux8);
|
|
}else{
|
|
outFatal(QT_3,"TOS option must be a number between 0 and 255 (inclusive)");
|
|
}
|
|
/* IP Identification field */
|
|
} else if (optcmp(long_options[option_index].name, "id") == 0 ){
|
|
if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){
|
|
o.setIdentification(aux16);
|
|
}else{
|
|
outFatal(QT_3,"Identification must be a number between 0 and 65535 (inclusive)");
|
|
}
|
|
/* Don't fragment bit */
|
|
} else if (optcmp(long_options[option_index].name, "df") == 0 ){
|
|
o.setDF();
|
|
/* More fragments bit */
|
|
} else if (optcmp(long_options[option_index].name, "mf") == 0 ){
|
|
o.setMF();
|
|
/* Time to live (hop-limit in IPv6) */
|
|
} else if (optcmp(long_options[option_index].name, "ttl") == 0 ||
|
|
optcmp(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{
|
|
outFatal(QT_3,"%s option must be a number between 0 and 255 (inclusive)",
|
|
optcmp(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 (optcmp(long_options[option_index].name, "badsum-ip") == 0 ){
|
|
o.enableBadsumIP();
|
|
/* IP Options */
|
|
} else if (optcmp(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 )
|
|
outFatal(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 (optcmp(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{
|
|
outFatal(QT_3,"MTU must be >0 and multiple of 8");
|
|
}
|
|
|
|
|
|
/* IPv6 OPTIONS **************************************************************/
|
|
/* IPv6 Traffic class */
|
|
} else if (optcmp(long_options[option_index].name, "traffic-class") == 0 ||
|
|
optcmp(long_options[option_index].name, "tc") == 0 ){
|
|
if ( parse_u8(optarg, &aux8) == OP_SUCCESS )
|
|
o.setTrafficClass(aux8);
|
|
else
|
|
outFatal(QT_3,"IPv6 Traffic Class must be a number between 0 and 255 (inclusive)");
|
|
/* IPv6 Flow label */
|
|
} else if (optcmp(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 )
|
|
outFatal(QT_3, "IPv6 Flow Label cannot be greater than 1048575 ");
|
|
else
|
|
o.setFlowLabel(aux32);
|
|
}else{
|
|
outFatal(QT_3,"IPv6 Flow Label must be a number between 0 and 1048575");
|
|
}
|
|
|
|
|
|
/* PACKET PAYLOAD OPTIONS ***************************************************/
|
|
/* Hexadecimal payload specification */
|
|
} else if (optcmp(long_options[option_index].name, "data") == 0 ){
|
|
u8 *tempbuff=NULL;
|
|
size_t len=0;
|
|
if( (tempbuff=parseBufferSpec(optarg, &len))==NULL)
|
|
outFatal(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);
|
|
}
|
|
/* Read payload from a file */
|
|
} else if (optcmp(long_options[option_index].name, "data-file") == 0 ){
|
|
if ( o.issetPayloadFilename() ) {
|
|
outFatal(QT_3,"Only one payload input filename allowed");
|
|
}else {
|
|
int tmp = file_is_readable(optarg);
|
|
if ( tmp == 1 )
|
|
o.setPayloadFilename(optarg);
|
|
else if ( tmp==2)
|
|
outFatal(QT_3,"Specified payload file is a directory, not a file.");
|
|
else
|
|
outFatal(QT_3,"Specified payload file does not exist or couldn't be opened for reading.");
|
|
}
|
|
/* Random payload */
|
|
} else if (optcmp(long_options[option_index].name, "data-length") == 0 ){
|
|
if( o.issetPayloadType() != false )
|
|
outFatal(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 ){
|
|
outFatal(QT_3,"Invalid payload length specification");
|
|
}
|
|
if ( aux32 > MAX_PAYLOAD_ALLOWED )
|
|
outFatal(QT_3,"data-length must be a value between 0 and %d.", MAX_PAYLOAD_ALLOWED);
|
|
if ( aux32 > MAX_RECOMMENDED_PAYLOAD )
|
|
outPrint(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 )
|
|
outFatal(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 (optcmp(long_options[option_index].name, "data-string") == 0 ){
|
|
o.setPayloadType(PL_STRING);
|
|
int plen=strlen(optarg);
|
|
if ( plen>MAX_PAYLOAD_ALLOWED )
|
|
outFatal(QT_3,"data-string must be between 0 and %d characters.", MAX_PAYLOAD_ALLOWED);
|
|
if ( plen > MAX_RECOMMENDED_PAYLOAD )
|
|
outPrint(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 (optcmp(long_options[option_index].name, "echo-client")==0 ||
|
|
optcmp(long_options[option_index].name, "ec")==0 ){
|
|
o.setRoleClient();
|
|
o.setEchoPassphrase(optarg);
|
|
} else if (optcmp(long_options[option_index].name, "echo-server")==0 ||
|
|
optcmp(long_options[option_index].name, "es")==0 ){
|
|
o.setRoleServer();
|
|
o.setEchoPassphrase(optarg);
|
|
} else if (optcmp(long_options[option_index].name, "echo-port")==0 ||
|
|
optcmp(long_options[option_index].name, "ep")==0 ){
|
|
if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){
|
|
if(aux16==0)
|
|
outFatal(QT_3, "Invalid echo port. Port can't be zero.");
|
|
else
|
|
o.setEchoPort( aux16 );
|
|
}else{
|
|
outFatal(QT_3, "Invalid echo port. Value must be 0<N<2^16.");
|
|
}
|
|
} else if (optcmp(long_options[option_index].name, "once")==0 ){
|
|
o.setOnce(true);
|
|
} else if (optcmp(long_options[option_index].name, "no-crypto")==0 ||
|
|
optcmp(long_options[option_index].name, "nc")==0 ){
|
|
o.doCrypto(false);
|
|
} else if (optcmp(long_options[option_index].name, "safe-payloads")==0 ){
|
|
o.echoPayload(false);
|
|
} else if (optcmp(long_options[option_index].name, "include-payloads")==0 ){
|
|
o.echoPayload(true);
|
|
|
|
|
|
/* TIMING AND PERFORMANCE OPTIONS ********************************************/
|
|
/* Inter-packet delay */
|
|
} else if (optcmp(long_options[option_index].name, "delay") == 0 ){
|
|
if ( (l= tval2msecs(optarg)) == -1)
|
|
outFatal(QT_3,"Invalid delay supplied. Delay must be a valid, positive integer or floating point number.");
|
|
else if(l<0)
|
|
outFatal(QT_3,"Invalid delay supplied. Delays can never be negative.");
|
|
if (l >= 10 * 1000 && tval_unit(optarg) == NULL)
|
|
outFatal(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 (optcmp(long_options[option_index].name, "rate") == 0 ){
|
|
if (parse_u32(optarg, &aux32)==OP_SUCCESS){
|
|
if(aux32==0){
|
|
outFatal(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{
|
|
outFatal(QT_3,"Invalid rate supplied. Rate must be a valid, positive integer");
|
|
}
|
|
/* Host timeout */
|
|
} else if (optcmp(long_options[option_index].name, "host-timeout") == 0 ){
|
|
l = tval2msecs(optarg);
|
|
if (l >= 10000 * 1000 && tval_unit(optarg) == NULL)
|
|
outFatal(QT_3,"Since April 2010, the default unit for --host-timeout is seconds, so your time of \"%s\" is %.1f hours. Use \"%sms\" for %g milliseconds.", optarg, l / 1000.0 / 60 / 60, optarg, l / 1000.0);
|
|
o.setHostTimeout(l);
|
|
|
|
|
|
/* MISC OPTIONS **************************************************************/
|
|
} else if (optcmp(long_options[option_index].name, "privileged") == 0 ){
|
|
o.setIsRoot();
|
|
} else if (optcmp(long_options[option_index].name, "unprivileged") == 0 ){
|
|
o.setIsRoot(0);
|
|
} else if (optcmp(long_options[option_index].name, "send-eth") == 0 ){
|
|
o.setSendPreference(PACKET_SEND_ETH_STRONG);
|
|
} else if (optcmp(long_options[option_index].name, "send-ip") == 0 ){
|
|
o.setSendPreference(PACKET_SEND_IP_STRONG);
|
|
} else if (optcmp(long_options[option_index].name, "bpf-filter") == 0 || optcmp(long_options[option_index].name, "filter") == 0){
|
|
o.setBPFFilterSpec( optarg );
|
|
if( o.issetDisablePacketCapture() && o.disablePacketCapture()==true )
|
|
outError(QT_2, "Warning: There is no point on specifying a BPF filter if you disable packet capture. BPF filter will be ignored.");
|
|
} else if (optcmp(long_options[option_index].name, "nsock-engine") == 0){
|
|
if (nsock_set_default_engine(optarg) < 0)
|
|
outFatal(QT_3, "Unknown or non-available engine: %s", optarg);
|
|
/* Output Options */
|
|
} else if (optcmp(long_options[option_index].name, "quiet") == 0 ){
|
|
o.setVerbosity(-4);
|
|
o.setDebugging(0);
|
|
}else if (optcmp(long_options[option_index].name, "debug") == 0 ){
|
|
o.setVerbosity(4);
|
|
o.setDebugging(9);
|
|
}
|
|
|
|
/* Copy and paste these to add more options. */
|
|
//}else if (optcmp(long_options[option_index].name, "") == 0 ){
|
|
//} else if (optcmp(long_options[option_index].name, "") == 0 ){
|
|
|
|
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 ){
|
|
outError(QT_3,"WARNING: -f is irrelevant if an MTU has been previously specified");
|
|
}
|
|
else{
|
|
outPrint(DBG_1, "Setting default MTU=%d", DEFAULT_MTU_FOR_FRAGMENTATION);
|
|
o.setMTU( DEFAULT_MTU_FOR_FRAGMENTATION );
|
|
}
|
|
break;
|
|
|
|
case 'g': /* Source port */
|
|
if( o.issetSourcePort() ){
|
|
outFatal(QT_3,"Cannot specify source port twice.");
|
|
}else if ( parse_u16(optarg, &aux16) == OP_SUCCESS ){
|
|
o.setSourcePort(aux16);
|
|
if(aux16==0)
|
|
outError(QT_1, "WARNING: a source port of zero may not work on all systems.");
|
|
}else{
|
|
outFatal(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 ){
|
|
outFatal(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){
|
|
outFatal(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)
|
|
outFatal(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{
|
|
outFatal(QT_3,"Packet count must be an integer greater than 0.");
|
|
}
|
|
break; /* case 'c': */
|
|
|
|
case 'e': /* Network interface */
|
|
if(strlen(optarg)==0)
|
|
outFatal(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() )
|
|
outError(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)
|
|
outFatal(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')
|
|
outFatal(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)
|
|
outFatal(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')
|
|
outFatal(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)
|
|
outFatal(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')
|
|
outFatal(QT_3,"Invalid argument to -q: \"%s\".", optarg);
|
|
}
|
|
}else{
|
|
o.decreaseVerbosity();
|
|
}
|
|
break; /* case 'q': */
|
|
|
|
} /* End of switch */
|
|
|
|
} /* End of getopt while */
|
|
|
|
|
|
/* 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);
|
|
/* TODO: change printf for output(). Check why we're getting error
|
|
* ArgParser.cc:(.text+0x72): undefined reference to `output'*/
|
|
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.0-255.1-254\n"
|
|
//" -iL <inputfilename>: Read targets from list of hosts or networks\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"
|
|
//" --mss <size> : Set maximum segment size.\n"
|
|
//" --ws <n> : Set window scale.\n"
|
|
//" --sack [To be defined] : Selective ACK.\n"
|
|
//" --ts <echo,reply> : Set timestamp (echo and reply fields).\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"
|
|
//" TODO: Add options for all fields required by those ICMP msg types.\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"
|
|
// Supported but undocumented:"" --spoof-ip: Set source IP address. (consistent with --spoof-mac format)\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"
|
|
" --ttl <hops> : Set time to live [0-255].\n"
|
|
" --badsum-ip : Use a random invalid checksum. \n"
|
|
" --ip-options <S|R [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"
|
|
//" -f : Fragment packets.\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"
|
|
// Supported but undocumented:" --spoof-mac : Set source MAC address (provides same flag as nmap).\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-file <filename> : Include payload from specified file.\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"
|
|
//" --host-timeout <time> : Give up on target after this long.\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") )
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: too short");
|
|
/* Im going to limit this to 255 chars. */
|
|
if( len > 255 )
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: too long");
|
|
|
|
/* Let's find the comma */
|
|
aux=strstr(str, ",");
|
|
|
|
if(aux==NULL )
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, missing comma delimiter");
|
|
if(aux==str)
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, comma cannot be placed at start");
|
|
if(aux>=str+len-1 )
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: Bad syntax, comma cannot be placed at the end");
|
|
|
|
/* Looks like at least the syntax is corect */
|
|
memcpy(first, str, aux-str);
|
|
memcpy(last, aux+1, len-(aux-str) );
|
|
|
|
if( atoIP(first, &auxIP) == OP_FAILURE )
|
|
outFatal(QT_3, "Invalid Router Advertising Entry specification: Unable to resolve %s", first);
|
|
if( isNumber_u32( last ) == false )
|
|
outFatal(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 ommited.
|
|
* 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 ommited.
|
|
* 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() */
|
|
|
|
|
|
|
|
/* Sames 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)
|
|
outFatal(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 )
|
|
outFatal(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 )
|
|
outFatal(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 )
|
|
outFatal(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 )
|
|
outFatal(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)
|
|
outFatal(QT_3,"Invalid time supplied");
|
|
else
|
|
*dst=diff;
|
|
}
|
|
|
|
return OP_SUCCESS;
|
|
} /* End of parseICMPTimestamp() */
|