"Fossies" - the Fresh Open Source Software Archive

Member "nmap-7.91/scan_lists.cc" (9 Oct 2020, 22272 Bytes) of package /linux/misc/nmap-7.91.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "scan_lists.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.90_vs_7.91.

    1 /***************************************************************************
    2  * scan_lists.cc -- Structures and functions for lists of ports to scan    *
    3  * and scan types                                                          *
    4  ***********************IMPORTANT NMAP LICENSE TERMS************************
    5  *                                                                         *
    6  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
    7  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
    8  *                                                                         *
    9  * This program is distributed under the terms of the Nmap Public Source   *
   10  * License (NPSL). The exact license text applying to a particular Nmap    *
   11  * release or source code control revision is contained in the LICENSE     *
   12  * file distributed with that version of Nmap or source code control       *
   13  * revision. More Nmap copyright/legal information is available from       *
   14  * https://nmap.org/book/man-legal.html, and further information on the    *
   15  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
   16  * summarizes some key points from the Nmap license, but is no substitute  *
   17  * for the actual license text.                                            *
   18  *                                                                         *
   19  * Nmap is generally free for end users to download and use themselves,    *
   20  * including commercial use. It is available from https://nmap.org.        *
   21  *                                                                         *
   22  * The Nmap license generally prohibits companies from using and           *
   23  * redistributing Nmap in commercial products, but we sell a special Nmap  *
   24  * OEM Edition with a more permissive license and special features for     *
   25  * this purpose. See https://nmap.org/oem                                  *
   26  *                                                                         *
   27  * If you have received a written Nmap license agreement or contract       *
   28  * stating terms other than these (such as an Nmap OEM license), you may   *
   29  * choose to use and redistribute Nmap under those terms instead.          *
   30  *                                                                         *
   31  * The official Nmap Windows builds include the Npcap software             *
   32  * (https://npcap.org) for packet capture and transmission. It is under    *
   33  * separate license terms which forbid redistribution without special      *
   34  * permission. So the official Nmap Windows builds may not be              *
   35  * redistributed without special permission (such as an Nmap OEM           *
   36  * license).                                                               *
   37  *                                                                         *
   38  * Source is provided to this software because we believe users have a     *
   39  * right to know exactly what a program is going to do before they run it. *
   40  * This also allows you to audit the software for security holes.          *
   41  *                                                                         *
   42  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
   43  * and add new features.  You are highly encouraged to submit your         *
   44  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
   45  * for possible incorporation into the main distribution. Unless you       *
   46  * specify otherwise, it is understood that you are offering us very       *
   47  * broad rights to use your submissions as described in the Nmap Public    *
   48  * Source License Contributor Agreement. This is important because we      *
   49  * fund the project by selling licenses with various terms, and also       *
   50  * because the inability to relicense code has caused devastating          *
   51  * problems for other Free Software projects (such as KDE and NASM).       *
   52  *                                                                         *
   53  * The free version of Nmap is distributed in the hope that it will be     *
   54  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
   55  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
   56  * indemnification and commercial support are all available through the    *
   57  * Npcap OEM program--see https://nmap.org/oem.                            *
   58  *                                                                         *
   59  ***************************************************************************/
   60 
   61 /* Convert a string like "-100,n*tp,200-1024,3000-4000,[60000-]" into an array
   62  * of port numbers. Note that one trailing comma is OK -- this is actually
   63  * useful for machine generated lists
   64  *
   65  * Fyodor - Wrote original
   66  * William McVey - Added T:, U:, P: directives
   67  * Doug Hoyte - Added [], name lookups, and wildcard expansion
   68  *
   69  * getpts() handles []
   70  * Any port ranges included inside square brackets will have all
   71  * their ports looked up in nmap-services or nmap-protocols
   72  * and will only be included if they are found.
   73  * Returns a scan_list* with all the ports that should be scanned.
   74  *
   75  * getpts() handles service/protocol name lookups and wildcard expansion.
   76  * The service name can be specified instead of the port number.
   77  * For example, "ssh" can be used instead of "22". You can use wildcards
   78  * like "*" and "?". See the function wildtest() for the exact details.
   79  * For example,
   80  *
   81  * nmap -p http* host
   82  *
   83  * Will scan http (80), http-mgmt (280), http-proxy (8080), https (443), etc.
   84  *
   85  * Matching is case INsensitive but the first character in a match MUST
   86  * be lowercase so it doesn't conflict with the T:, U:, and P: directives.
   87  *
   88  * getpts() is unable to match service names that start with a digit
   89  * like 3com-tsmux (106/udp). Use a pattern like "?com-*" instead.
   90  *
   91  * BE CAREFUL ABOUT SHELL EXPANSIONS!!!
   92  * If you are trying to match the services nmsp (537/tcp) and nms (1429/tcp)
   93  * and you execute the command
   94  *
   95  * ./nmap -p nm* host
   96  *
   97  * You will see
   98  *
   99  * Found no matches for the service mask 'nmap' and your specified protocols
  100  * QUITTING!
  101  *
  102  * This is because nm* was expanded to the name of the binary file nmap in
  103  * the current directory by your shell. When unsure, quote your port strings
  104  * to be safe:
  105  *
  106  * ./nmap -p 'nm*' host
  107  *
  108  * getpts() is smart enough to keep the T: U: and P: directives nested
  109  * and working in a logical manner. For instance,
  110  *
  111  * nmap -sTU -p [U:1025-],1-1024 host
  112  *
  113  * Will scan UDP ports 1025 and up that are found in the service file
  114  * and all TCP/UDP ports below <= 1024. Notice that the U doesn't affect
  115  * the outer part of the port expression. It's "closed".
  116  */
  117 
  118 #include "scan_lists.h"
  119 #include "nmap_error.h"
  120 #include "NmapOps.h"
  121 #include "protocols.h"
  122 #include "services.h"
  123 #include <nbase.h>
  124 
  125 extern NmapOps o;  /* option structure */
  126 
  127 static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_type,
  128                        int *portwarning, bool change_range_type = true);
  129 
  130 void getpts(const char *origexpr, struct scan_lists *ports) {
  131   u8 *porttbl;
  132   int range_type = 0;
  133   int portwarning = 0;
  134   int i, tcpi, udpi, sctpi, proti;
  135 
  136   if (o.TCPScan())
  137     range_type |= SCAN_TCP_PORT;
  138   if (o.UDPScan())
  139     range_type |= SCAN_UDP_PORT;
  140   if (o.SCTPScan())
  141     range_type |= SCAN_SCTP_PORT;
  142   if (o.ipprotscan)
  143     range_type |= SCAN_PROTOCOLS;
  144   if (o.noportscan && o.exclude_portlist) { // We want to exclude from ping scans in this case but we take port list normally and then removepts() handles it
  145     range_type |= SCAN_TCP_PORT;
  146     range_type |= SCAN_UDP_PORT;
  147     range_type |= SCAN_SCTP_PORT;
  148   }
  149 
  150   porttbl = (u8 *) safe_zalloc(65536);
  151 
  152   getpts_aux(origexpr,      // Pass on the expression
  153              0,             // Don't start off nested
  154              porttbl,       // Our allocated port table
  155              range_type,    // Defaults to TCP/UDP/SCTP/Protos
  156              &portwarning); // No, we haven't warned them about dup ports yet
  157 
  158   ports->tcp_count = 0;
  159   ports->udp_count = 0;
  160   ports->sctp_count = 0;
  161   ports->prot_count = 0;
  162   for (i = 0; i <= 65535; i++) {
  163     if (porttbl[i] & SCAN_TCP_PORT)
  164       ports->tcp_count++;
  165     if (porttbl[i] & SCAN_UDP_PORT)
  166       ports->udp_count++;
  167     if (porttbl[i] & SCAN_SCTP_PORT)
  168       ports->sctp_count++;
  169     if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
  170       ports->prot_count++;
  171   }
  172 
  173   if (range_type != 0 && 0 == (ports->tcp_count + ports->udp_count + ports->sctp_count + ports->prot_count))
  174     fatal("No ports specified -- If you really don't want to scan any ports use ping scan...");
  175 
  176   if (ports->tcp_count) {
  177     ports->tcp_ports = (unsigned short *)safe_zalloc(ports->tcp_count * sizeof(unsigned short));
  178   }
  179   if (ports->udp_count) {
  180     ports->udp_ports = (unsigned short *)safe_zalloc(ports->udp_count * sizeof(unsigned short));
  181   }
  182   if (ports->sctp_count) {
  183     ports->sctp_ports = (unsigned short *)safe_zalloc(ports->sctp_count * sizeof(unsigned short));
  184   }
  185   if (ports->prot_count) {
  186     ports->prots = (unsigned short *)safe_zalloc(ports->prot_count * sizeof(unsigned short));
  187   }
  188 
  189   for (i = tcpi = udpi = sctpi = proti = 0; i <= 65535; i++) {
  190     if (porttbl[i] & SCAN_TCP_PORT)
  191       ports->tcp_ports[tcpi++] = i;
  192     if (porttbl[i] & SCAN_UDP_PORT)
  193       ports->udp_ports[udpi++] = i;
  194     if (porttbl[i] & SCAN_SCTP_PORT)
  195       ports->sctp_ports[sctpi++] = i;
  196     if (porttbl[i] & SCAN_PROTOCOLS && i < 256)
  197       ports->prots[proti++] = i;
  198   }
  199 
  200   free(porttbl);
  201 }
  202 
  203 /* This function is like getpts except it only allocates space for and stores
  204   values into one unsigned short array, instead of an entire scan_lists struct
  205   For that reason, T:, U:, S: and P: restrictions are not allowed and only one
  206   bit in range_type may be set. */
  207 void getpts_simple(const char *origexpr, int range_type,
  208                    unsigned short **list, int *count) {
  209   u8 *porttbl;
  210   int portwarning = 0;
  211   int i, j;
  212 
  213   /* Make sure that only one bit in range_type is set (or that range_type is 0,
  214      which is useless but not incorrect). */
  215   assert((range_type & (range_type - 1)) == 0);
  216 
  217   porttbl = (u8 *) safe_zalloc(65536);
  218 
  219   /* Get the ports but do not allow changing the type with T:, U:, or P:. */
  220   getpts_aux(origexpr, 0, porttbl, range_type, &portwarning, false);
  221 
  222   /* Count how many are set. */
  223   *count = 0;
  224   for (i = 0; i <= 65535; i++) {
  225     if (porttbl[i] & range_type)
  226       (*count)++;
  227   }
  228 
  229   if (*count == 0) {
  230     free(porttbl);
  231     return;
  232   }
  233 
  234   *list = (unsigned short *) safe_zalloc(*count * sizeof(unsigned short));
  235 
  236   /* Fill in the list. */
  237   for (i = 0, j = 0; i <= 65535; i++) {
  238     if (porttbl[i] & range_type)
  239       (*list)[j++] = i;
  240   }
  241 
  242   free(porttbl);
  243 }
  244 
  245 /* removepts() takes a port specification and removes any matching ports
  246   from the given scan_lists struct. */
  247 
  248 static int remaining_ports(unsigned short int *ports, int count, unsigned short int *exclude_ports, int exclude_count, const char *type = "");
  249 
  250 void removepts(const char *expr, struct scan_lists * ports) {
  251   static struct scan_lists exclude_ports;
  252 
  253   if (!expr)
  254     return;
  255 
  256   getpts(expr, &exclude_ports);
  257 
  258   #define SUBTRACT_PORTS(type,excludetype) \
  259     ports->type##_count = remaining_ports(ports->type##_ports, \
  260                                           ports->type##_count, \
  261                                           exclude_ports.excludetype##_ports, \
  262                                           exclude_ports.excludetype##_count, \
  263                                           #type)
  264 
  265   SUBTRACT_PORTS(tcp, tcp);
  266   SUBTRACT_PORTS(udp, udp);
  267   SUBTRACT_PORTS(sctp, sctp);
  268   SUBTRACT_PORTS(syn_ping, tcp);
  269   SUBTRACT_PORTS(ack_ping, tcp);
  270   SUBTRACT_PORTS(udp_ping, udp);
  271   SUBTRACT_PORTS(sctp_ping, sctp);
  272 
  273   #define prot_ports prots
  274   SUBTRACT_PORTS(prot, prot);
  275   SUBTRACT_PORTS(proto_ping, prot);
  276   #undef prot_ports
  277 
  278   #undef SUBTRACT_PORTS
  279 
  280   free_scan_lists(&exclude_ports);
  281 }
  282 
  283 /* This function returns the number of ports that remain after the excluded ports
  284   are removed from the ports. It places these ports at the start of the ports array. */
  285 static int remaining_ports(unsigned short int *ports, int count, unsigned short int *exclude_ports, int exclude_count, const char *type) {
  286   static bool has_been_excluded[65536];
  287   int i, j;
  288 
  289   if (count == 0 || exclude_count == 0)
  290     return count;
  291 
  292   if (o.debugging > 1)
  293     log_write(LOG_STDOUT, "Removed %s ports: ", type);
  294 
  295   for (i = 0; i < 65536; i++)
  296     has_been_excluded[i] = false;
  297   for (i = 0; i < exclude_count; i++)
  298     has_been_excluded[exclude_ports[i]] = true;
  299   for (i = 0, j = 0; i < count; i++)
  300     if (!has_been_excluded[ports[i]])
  301       ports[j++] = ports[i];
  302     else if (o.debugging > 1)
  303       log_write(LOG_STDOUT, "%d ", ports[i]);
  304 
  305   if (o.debugging > 1) {
  306     if (count-j) {
  307       log_write(LOG_STDOUT, "\n");
  308     } else {
  309       log_write(LOG_STDOUT, "None\n");
  310     }
  311   }
  312   if (o.debugging && count-j) {
  313     log_write(LOG_STDOUT, "Removed %d %s ports that would have been considered for scanning otherwise.\n", count-j, type);
  314   }
  315 
  316   return j;
  317 }
  318 
  319 /* getpts() and getpts_simple() (see above) are wrappers for this function */
  320 
  321 static void getpts_aux(const char *origexpr, int nested, u8 *porttbl, int range_type, int *portwarning, bool change_range_type) {
  322   long rangestart = -2343242, rangeend = -9324423;
  323   const char *current_range;
  324   char *endptr;
  325   char servmask[128];  // A protocol name can be up to 127 chars + nul byte
  326   int i;
  327 
  328   /* An example of proper syntax to use in error messages. */
  329   const char *syntax_example;
  330   if (change_range_type)
  331     syntax_example = "-100,200-1024,T:3000-4000,U:60000-";
  332   else
  333     syntax_example = "-100,200-1024,3000-4000,60000-";
  334 
  335   current_range = origexpr;
  336   do {
  337     while (isspace((int) (unsigned char) *current_range))
  338       current_range++; /* I don't know why I should allow spaces here, but I will */
  339 
  340     if (change_range_type && *(current_range+1) == ':') {
  341       switch (*current_range) {
  342         case 'T':
  343           range_type = SCAN_TCP_PORT;
  344           break;
  345         case 'U':
  346           range_type = SCAN_UDP_PORT;
  347           break;
  348         case 'S':
  349           range_type = SCAN_SCTP_PORT;
  350           break;
  351         case 'P':
  352           range_type = SCAN_PROTOCOLS;
  353           break;
  354         default:
  355           fatal("Error parsing port list: Unknown protocol specifier '%c'.", *current_range);
  356           break;
  357       }
  358       current_range += 2;
  359       continue;
  360     }
  361 
  362     if (*current_range == '[') {
  363       if (nested)
  364         fatal("Can't nest [] brackets in port/protocol specification");
  365 
  366       getpts_aux(++current_range, 1, porttbl, range_type, portwarning);
  367 
  368       // Skip past the ']'. This is OK because we can't nest []s
  369       while (*current_range != ']' && *current_range != '\0')
  370         current_range++;
  371       if (*current_range == ']')
  372         current_range++;
  373 
  374       // Skip over a following ',' so we're ready to keep parsing
  375       if (*current_range == ',')
  376         current_range++;
  377 
  378       continue;
  379     } else if (*current_range == ']') {
  380       if (!nested)
  381         fatal("Unexpected ] character in port/protocol specification");
  382 
  383       return;
  384     } else if (*current_range == '-') {
  385       if (range_type & SCAN_PROTOCOLS)
  386         rangestart = 0;
  387       else
  388         rangestart = 1;
  389     } else if (isdigit((int) (unsigned char) *current_range)) {
  390       rangestart = strtol(current_range, &endptr, 10);
  391       if (range_type & SCAN_PROTOCOLS) {
  392         if (rangestart < 0 || rangestart > 255)
  393           fatal("Protocols specified must be between 0 and 255 inclusive");
  394       } else {
  395         if (rangestart < 0 || rangestart > 65535)
  396           fatal("Ports specified must be between 0 and 65535 inclusive");
  397       }
  398       current_range = endptr;
  399       while (isspace((int) (unsigned char) *current_range)) current_range++;
  400     } else if (islower((int) (unsigned char) *current_range) || *current_range == '*' || *current_range == '?') {
  401       i = 0;
  402 
  403       while (*current_range && !isspace((int) (unsigned char) *current_range) && *current_range != ',' && *current_range != ']') {
  404         servmask[i++] = *(current_range++);
  405         if (i >= ((int)sizeof(servmask) - 1))
  406           fatal("A service mask in the port/protocol specification is either malformed or too long");
  407       }
  408 
  409       if (*current_range && *current_range != ']') current_range++; // We want the '] character to be picked up on the next pass
  410       servmask[i] = '\0'; // Finish the string
  411 
  412       i = addportsfromservmask(servmask, porttbl, range_type);
  413       if (range_type & SCAN_PROTOCOLS)
  414         i += addprotocolsfromservmask(servmask, porttbl);
  415 
  416       if (i == 0)
  417         fatal("Found no matches for the service mask '%s' and your specified protocols", servmask);
  418 
  419       continue;
  420 
  421     } else {
  422       fatal("Error #485: Your port specifications are illegal.  Example of proper form: \"%s\"", syntax_example);
  423     }
  424     /* Now I have a rangestart, time to go after rangeend */
  425     if (!*current_range || *current_range == ',' || *current_range == ']') {
  426       /* Single port specification */
  427       rangeend = rangestart;
  428     } else if (*current_range == '-') {
  429       current_range++;
  430       if (!*current_range || *current_range == ',' || *current_range == ']') {
  431         /* Ended with a -, meaning up until the last possible port */
  432         if (range_type & SCAN_PROTOCOLS)
  433           rangeend = 255;
  434         else
  435           rangeend = 65535;
  436       } else if (isdigit((int) (unsigned char) *current_range)) {
  437         rangeend = strtol(current_range, &endptr, 10);
  438         if (range_type & SCAN_PROTOCOLS) {
  439           if (rangeend < 0 || rangeend > 255)
  440             fatal("Protocols specified must be between 0 and 255 inclusive");
  441         } else {
  442           if (rangeend < 0 || rangeend > 65535)
  443             fatal("Ports specified must be between 0 and 65535 inclusive");
  444         }
  445         current_range = endptr;
  446       } else {
  447         fatal("Error #486: Your port specifications are illegal.  Example of proper form: \"%s\"", syntax_example);
  448       }
  449       if (rangeend < rangestart) {
  450         fatal("Your %s range %ld-%ld is backwards. Did you mean %ld-%ld?",
  451               (range_type & SCAN_PROTOCOLS) ? "protocol" : "port",
  452               rangestart, rangeend, rangeend, rangestart);
  453       }
  454     } else {
  455       fatal("Error #487: Your port specifications are illegal.  Example of proper form: \"%s\"", syntax_example);
  456     }
  457 
  458     /* Now I have a rangestart and a rangeend, so I can add these ports */
  459     while (rangestart <= rangeend) {
  460       if (porttbl[rangestart] & range_type) {
  461         if (!(*portwarning)) {
  462           error("WARNING: Duplicate port number(s) specified.  Are you alert enough to be using Nmap?  Have some coffee or Jolt(tm).");
  463           (*portwarning)++;
  464         }
  465       } else {
  466         if (nested) {
  467           if ((range_type & SCAN_TCP_PORT) &&
  468               nmap_getservbyport(rangestart, "tcp")) {
  469             porttbl[rangestart] |= SCAN_TCP_PORT;
  470           }
  471           if ((range_type & SCAN_UDP_PORT) &&
  472               nmap_getservbyport(rangestart, "udp")) {
  473             porttbl[rangestart] |= SCAN_UDP_PORT;
  474           }
  475           if ((range_type & SCAN_SCTP_PORT) &&
  476               nmap_getservbyport(rangestart, "sctp")) {
  477             porttbl[rangestart] |= SCAN_SCTP_PORT;
  478           }
  479           if ((range_type & SCAN_PROTOCOLS) &&
  480               nmap_getprotbynum(rangestart)) {
  481             porttbl[rangestart] |= SCAN_PROTOCOLS;
  482           }
  483         } else {
  484           porttbl[rangestart] |= range_type;
  485         }
  486       }
  487       rangestart++;
  488     }
  489 
  490     /* Find the next range */
  491     while (isspace((int) (unsigned char) *current_range)) current_range++;
  492 
  493     if (*current_range == ']') {
  494       if (!nested)
  495         fatal("Unexpected ] character in port/protocol specification");
  496       return;
  497     }
  498 
  499     if (*current_range && *current_range != ',') {
  500       fatal("Error #488: Your port specifications are illegal.  Example of proper form: \"%s\"", syntax_example);
  501     }
  502     if (*current_range == ',')
  503       current_range++;
  504   } while (current_range && *current_range);
  505 
  506 }
  507 
  508 void free_scan_lists(struct scan_lists *ports) {
  509   if (ports->tcp_ports)
  510     free(ports->tcp_ports);
  511   if (ports->udp_ports)
  512     free(ports->udp_ports);
  513   if (ports->sctp_ports)
  514     free(ports->sctp_ports);
  515   if (ports->prots)
  516     free(ports->prots);
  517   if (ports->syn_ping_ports)
  518     free(ports->syn_ping_ports);
  519   if (ports->ack_ping_ports)
  520     free(ports->ack_ping_ports);
  521   if (ports->udp_ping_ports)
  522     free(ports->udp_ping_ports);
  523   if (ports->proto_ping_ports)
  524     free(ports->proto_ping_ports);
  525 }
  526 
  527 
  528 
  529 /* Just a routine for obtaining a string for printing based on the scantype */
  530 const char *scantype2str(stype scantype) {
  531 
  532   switch (scantype) {
  533   case STYPE_UNKNOWN:
  534     return "Unknown Scan Type";
  535     break;
  536   case HOST_DISCOVERY:
  537     return "Host Discovery";
  538     break;
  539   case ACK_SCAN:
  540     return "ACK Scan";
  541     break;
  542   case SYN_SCAN:
  543     return "SYN Stealth Scan";
  544     break;
  545   case FIN_SCAN:
  546     return "FIN Scan";
  547     break;
  548   case XMAS_SCAN:
  549     return "XMAS Scan";
  550     break;
  551   case UDP_SCAN:
  552     return "UDP Scan";
  553     break;
  554   case CONNECT_SCAN:
  555     return "Connect Scan";
  556     break;
  557   case NULL_SCAN:
  558     return "NULL Scan";
  559     break;
  560   case WINDOW_SCAN:
  561     return "Window Scan";
  562     break;
  563   case SCTP_INIT_SCAN:
  564     return "SCTP INIT Scan";
  565     break;
  566   case SCTP_COOKIE_ECHO_SCAN:
  567     return "SCTP COOKIE-ECHO Scan";
  568     break;
  569   case MAIMON_SCAN:
  570     return "Maimon Scan";
  571     break;
  572   case IPPROT_SCAN:
  573     return "IPProto Scan";
  574     break;
  575   case PING_SCAN:
  576     return "Ping Scan";
  577     break;
  578   case PING_SCAN_ARP:
  579     return "ARP Ping Scan";
  580     break;
  581   case PING_SCAN_ND:
  582     return "ND Ping Scan";
  583     break;
  584   case IDLE_SCAN:
  585     return "Idle Scan";
  586     break;
  587   case BOUNCE_SCAN:
  588     return "Bounce Scan";
  589     break;
  590   case SERVICE_SCAN:
  591     return "Service Scan";
  592     break;
  593   case OS_SCAN:
  594     return "OS Scan";
  595     break;
  596   case SCRIPT_PRE_SCAN:
  597     return "Script Pre-Scan";
  598     break;
  599   case SCRIPT_SCAN:
  600     return "Script Scan";
  601     break;
  602   case SCRIPT_POST_SCAN:
  603     return "Script Post-Scan";
  604     break;
  605   case TRACEROUTE:
  606     return "Traceroute" ;
  607     break;
  608   default:
  609     assert(0);
  610     break;
  611   }
  612 
  613   return NULL; /* Unreached */
  614 
  615 }
  616