"Fossies" - the Fresh Open Source Software Archive

Member "scanssh-2.1/scanssh.c" (21 Nov 2004, 31480 Bytes) of package /linux/privat/old/scanssh-2.1.tar.gz:


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 "scanssh.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * ScanSSH - simple SSH version scanner
    3  *
    4  * Copyright 2000-2004 (c) Niels Provos <provos@citi.umich.edu>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/types.h>
   31 
   32 #ifdef HAVE_CONFIG_H
   33 #include "config.h"
   34 #endif
   35 
   36 #include <sys/socket.h>
   37 #include <sys/wait.h>
   38 #include <sys/time.h>
   39 #include <sys/resource.h>
   40 #include <sys/queue.h>
   41 #include <sys/tree.h>
   42 
   43 #include <netinet/in.h>
   44 #include <arpa/inet.h>
   45 
   46 #include <stdio.h>
   47 #include <stdlib.h>
   48 #include <string.h>
   49 #include <signal.h>
   50 #include <errno.h>
   51 #include <err.h>
   52 #include <fcntl.h>
   53 #include <netdb.h>
   54 #include <pcap.h>
   55 #include <unistd.h>
   56 #include <md5.h>
   57 #include <stdarg.h>
   58 #include <assert.h>
   59 
   60 #include <event.h>
   61 #include <dnet.h>
   62 
   63 #include "scanssh.h"
   64 #include "exclude.h"
   65 #include "xmalloc.h"
   66 #include "interface.h"
   67 
   68 #ifndef howmany
   69 #define howmany(x,y)    (((x) + ((y) - 1)) / (y))
   70 #endif
   71 
   72 #ifdef DEBUG
   73 int debug = 0;
   74 #define DFPRINTF(x) if (debug) fprintf x
   75 #define DNFPRINTF(y, x) if (debug >= y) fprintf x
   76 #else
   77 #define DFPRINTF(x)
   78 #define DNFPRINTF(y, x)
   79 #endif
   80 
   81 struct address_node {
   82     TAILQ_ENTRY (address_node) an_next;
   83 
   84     struct addr an_start;
   85     struct addr an_end;
   86     int an_bits;
   87 };
   88 
   89 struct generate {
   90     TAILQ_ENTRY (generate) gen_next;
   91 
   92     TAILQ_HEAD (an_list, address_node) gen_anqueue;
   93 
   94     int gen_flags;
   95 
   96     uint32_t gen_seed;      /* Seed for PRNG */
   97 
   98     uint32_t gen_bits;
   99     uint32_t gen_start;
  100     uint32_t gen_iterate;
  101     uint32_t gen_end;
  102     uint32_t gen_current;
  103     uint32_t gen_n;     /* successful generations */
  104     uint32_t gen_max;
  105 
  106 
  107     struct port *gen_ports;
  108     int gen_nports;
  109 };
  110 
  111 int populate(struct argument **, int *);
  112 int next_address(struct generate *, struct addr *);
  113 
  114 /* Globals */
  115 struct interface *ss_inter;
  116 rand_t *ss_rand;
  117 ip_t   *ss_ip;
  118 
  119 /* SOCKS servers via which we can scan */
  120 struct socksq socks_host;
  121 
  122 struct scanner **ss_scanners = NULL;
  123 int ss_nscanners = 0;
  124 
  125 struct argument *args;      /* global list of addresses */
  126 int entries;            /* number of remaining addresses */
  127 
  128 int ssh_sendident;      /* should we send ident to ssh server? */
  129 
  130 struct port *ss_ports = NULL;   /* global list of ports to be scanned */
  131 int ss_nports = 0;
  132 
  133 int ss_nhosts = 0;      /* Number of addresses generated */
  134 
  135 pcap_t *pd;
  136 int rndexclude = 1;
  137 struct timeval syn_start;
  138 int syn_rate = 100;
  139 int syn_nsent = 0;
  140 
  141 int max_scanqueue_size = MAXSCANQUEUESZ;
  142 
  143 struct address_slot slots[MAXSLOTS];
  144 
  145 #define MAX_PROCESSES   30
  146 
  147 int commands[MAX_PROCESSES];
  148 int results[MAX_PROCESSES];
  149 
  150 TAILQ_HEAD (gen_list, generate) genqueue;
  151 struct queue_list readyqueue;
  152 
  153 /* Structure for probes */
  154 static SPLAY_HEAD(syntree, argument) synqueue;
  155 
  156 int
  157 argumentcompare(struct argument *a, struct argument *b)
  158 {
  159     return (addr_cmp(&a->addr, &b->addr));
  160 }
  161 
  162 SPLAY_PROTOTYPE(syntree, argument, a_node, argumentcompare);
  163 SPLAY_GENERATE(syntree, argument, a_node, argumentcompare);
  164 
  165 #define synlist_empty()     (synqueuesz == 0)
  166 
  167 int synqueuesz;
  168 
  169 struct address_slot *
  170 slot_get(void)
  171 {
  172     int i;
  173     struct address_slot *slot;
  174 
  175     for (i = 0; i < MAXSLOTS; i++)
  176         if (slots[i].slot_base == NULL)
  177             break;
  178 
  179     if (i >= MAXSLOTS)
  180         return (NULL);
  181     
  182     slot = &slots[i];
  183 
  184     if (slot->slot_base == NULL) {
  185         slot->slot_size = EXPANDEDARGS;
  186         slot->slot_base = xmalloc(EXPANDEDARGS * sizeof(struct argument));
  187         memset(slot->slot_base, 0,
  188                slot->slot_size * sizeof(struct argument));
  189     }
  190 
  191     return (slot);
  192 }
  193 
  194 /* We need to call this to free up our memory */
  195 
  196 void
  197 slot_free(struct address_slot *slot)
  198 {
  199     slot->slot_ref--;
  200     if (slot->slot_ref)
  201         return;
  202 
  203     slot->slot_size = 0;
  204     free(slot->slot_base);
  205     slot->slot_base = NULL;
  206 }
  207 
  208 void
  209 argument_free(struct argument *arg)
  210 {
  211     if (arg->a_ports != NULL && arg->a_hasports) {
  212         int i;
  213 
  214         for (i = 0; i < arg->a_nports; i++) {
  215             struct port_scan *ps = arg->a_ports[i].scan;
  216             if (ps != NULL) {
  217                 event_del(&ps->ev);
  218                 free(ps);
  219             }
  220         }
  221         free(arg->a_ports);
  222         arg->a_ports = NULL;
  223     }
  224 
  225     if (arg->a_res != NULL) {
  226         free(arg->a_res);
  227         arg->a_res = NULL;
  228     }
  229 
  230     slot_free(arg->a_slot);
  231 }
  232 
  233 void
  234 synlist_init(void)
  235 {
  236     SPLAY_INIT(&synqueue);
  237     synqueuesz = 0;
  238 }
  239 
  240 /* Inserts an address into the syn tree and schedules a retransmit */
  241 
  242 int
  243 synlist_insert(struct argument *arg)
  244 {
  245     struct timeval tv;
  246 
  247     timerclear(&tv);
  248     tv.tv_sec = (arg->a_retry/2 + 1) * SYNWAIT;
  249     tv.tv_usec = rand_uint32(ss_rand) % 1000000L;
  250 
  251     evtimer_add(&arg->ev, &tv);
  252 
  253     /* Insert the node into our tree */
  254     assert(SPLAY_FIND(syntree, &synqueue, arg) == NULL);
  255     SPLAY_INSERT(syntree, &synqueue, arg);
  256 
  257     synqueuesz++;
  258 
  259     return (0);
  260 }
  261 
  262 void
  263 synlist_remove(struct argument *arg)
  264 {
  265     SPLAY_REMOVE(syntree, &synqueue, arg);
  266     evtimer_del(&arg->ev);
  267     synqueuesz--;
  268 }
  269 
  270 int
  271 synlist_probe(struct argument *arg, uint16_t port)
  272 {
  273         return (synprobe_send(&ss_inter->if_ent.intf_addr,
  274             &arg->addr, port, &arg->a_seqnr));
  275 }
  276 
  277 int
  278 synprobe_send(struct addr *src, struct addr *dst,
  279     uint16_t port, uint32_t *seqnr)
  280 {
  281     static uint8_t pkt[1500];
  282     struct tcp_hdr *tcp;
  283     uint iplen;
  284     int res;
  285 
  286     DFPRINTF((stderr, "Sending probe to %s:%d\n", addr_ntoa(dst), port));
  287 
  288     tcp = (struct tcp_hdr *)(pkt + IP_HDR_LEN);
  289     tcp_pack_hdr(tcp, rand_uint16(ss_rand), port, 
  290         *seqnr, 0, 
  291         TH_SYN, 0x8000, 0);
  292 
  293     iplen = IP_HDR_LEN + (tcp->th_off << 2);
  294 
  295     /* Src and Dst are reversed both for ip and tcp */
  296     ip_pack_hdr(pkt, 0, iplen,
  297         rand_uint16(ss_rand),
  298         IP_DF, 64,
  299         IP_PROTO_TCP, src->addr_ip, dst->addr_ip);
  300 
  301     ip_checksum(pkt, iplen);
  302     
  303     if ((res = ip_send(ss_ip, pkt, iplen)) != iplen) {
  304         warn("%s: ip_send(%d): %s", __func__, res, addr_ntoa(dst));
  305         return (-1);
  306     }
  307 
  308     return (0);
  309 }
  310 
  311 void
  312 sigchld_handler(int sig)
  313 {
  314         int save_errno = errno;
  315     int status;
  316     wait(&status);
  317         signal(SIGCHLD, sigchld_handler);
  318         errno = save_errno;
  319 }
  320 
  321 void
  322 printres(struct argument *exp, uint16_t port, char *result)
  323 {
  324     fprintf(stdout, "%s:%d %s\n",
  325         addr_ntoa(&exp->addr), port, result);
  326     fflush(stdout);
  327 }
  328 
  329 void
  330 postres(struct argument *arg, const char *fmt, ...)
  331 {
  332     static char buffer[1024];
  333     va_list ap;
  334 
  335     va_start(ap, fmt);
  336     vsnprintf(buffer, sizeof(buffer), fmt, ap);
  337     va_end(ap);
  338 
  339     if (arg->a_res != NULL)
  340         free(arg->a_res);
  341     if ((arg->a_res = strdup(buffer)) == NULL)
  342         err(1, "%s: strdup", __func__);
  343 }
  344 
  345 /*
  346  * Called when a syn probe times out and we might have to repeat it
  347  */
  348 
  349 void
  350 ss_timeout(int fd, short what, void *parameter)
  351 {
  352     struct argument *arg = parameter;
  353     struct timeval tv;
  354 
  355     if (arg->a_retry < SYNRETRIES) {
  356         arg->a_retry++;
  357         /*
  358          * If this probe fails we are not reducing the retry counter,
  359          * as some of the failures might repeat always, like a host
  360          * on the local network not being reachable or some unrouteable
  361          * address space.
  362          */
  363         if (synlist_probe(arg, arg->a_ports[0].port) == 0)
  364             syn_nsent++;
  365     } else {
  366         printres(arg, arg->a_ports[0].port, "<timeout>");
  367         synlist_remove(arg);
  368         argument_free(arg);
  369         return;
  370     }
  371 
  372     timerclear(&tv);
  373     tv.tv_sec = (arg->a_retry/2 + 1) * SYNWAIT;
  374     tv.tv_usec = rand_uint32(ss_rand) % 1000000L;
  375     
  376     evtimer_add(&arg->ev, &tv);
  377 }
  378 
  379 void
  380 ss_recv_cb(uint8_t *ag, const struct pcap_pkthdr *pkthdr, const uint8_t *pkt)
  381 {
  382     struct interface *inter = (struct interface *)ag;
  383     struct ip_hdr *ip;
  384     struct tcp_hdr *tcp = NULL;
  385     struct addr addr;
  386     struct argument *arg, tmp;
  387     ushort iplen, iphlen;
  388 
  389     /* Everything below assumes that the packet is IPv4 */
  390     if (pkthdr->caplen < inter->if_dloff + IP_HDR_LEN)
  391         return;
  392 
  393     pkt += inter->if_dloff;
  394     ip = (struct ip_hdr *)pkt;
  395 
  396     iplen = ntohs(ip->ip_len);
  397     if (pkthdr->caplen - inter->if_dloff < iplen)
  398         return;
  399 
  400     iphlen = ip->ip_hl << 2;
  401     if (iphlen > iplen)
  402         return;
  403     if (iphlen < sizeof(struct ip_hdr))
  404         return;
  405 
  406     addr_pack(&addr, ADDR_TYPE_IP, IP_ADDR_BITS, &ip->ip_src, IP_ADDR_LEN);
  407 
  408     if (iplen < iphlen + TCP_HDR_LEN)
  409         return;
  410 
  411     tcp = (struct tcp_hdr *)(pkt + iphlen);
  412 
  413     /* See if we get results from our syn probe */
  414     tmp.addr = addr;
  415     if ((arg = SPLAY_FIND(syntree, &synqueue, &tmp)) != NULL) {
  416         struct port *port;
  417         /* Check if the result is coming from the right port */
  418         port = ports_find(arg, ntohs(tcp->th_sport));
  419         if (port == NULL)
  420             return;
  421 
  422         if (!arg->a_hasports)
  423             ports_setup(arg, arg->a_ports, arg->a_nports);
  424 
  425         if (tcp->th_flags & TH_RST) {
  426             printres(arg, port->port, "<refused>");
  427             ports_remove(arg, port->port);
  428             if (arg->a_nports == 0) {
  429                 synlist_remove(arg);
  430                 argument_free(arg);
  431                 return;
  432             }
  433         } else {
  434             ports_markchecked(arg, port);
  435         }
  436 
  437         if (ports_isalive(arg) == 1) {
  438             synlist_remove(arg);
  439             scanhost_ready(arg);
  440         }
  441     }
  442 }
  443 
  444 void
  445 scanssh_init(void)
  446 {
  447     TAILQ_INIT(&readyqueue);
  448     synlist_init();
  449 }
  450 
  451 void
  452 usage(char *name)
  453 {
  454     fprintf(stderr, 
  455         "%s: [-VIERhp] [-s scanners] [-n ports] [-e excludefile] [-i if] [-b alias] <IP address|network>...\n\n"
  456         "\t-V          print version number of scanssh,\n"
  457         "\t-I          do not send identification string,\n"
  458         "\t-E          exit if exclude file is missing,\n"
  459         "\t-R          do not honor exclude file for random addresses,\n"
  460         "\t-p          proxy detection mode; set scanners and ports,\n"
  461         "\t-n <port>   the port number to scan.\n"
  462         "\t-e <file>   exclude the IP addresses and networks in <file>,\n"
  463         "\t-b <alias>  specifies the IP alias to connect from,\n"
  464         "\t-i <if>     specifies the local interface,\n"
  465         "\t-h          this message.\n"
  466         "\t-s <modes>  uses the following modules for scanning:\n",
  467         name);
  468     scanner_print("\t\t");
  469 }
  470 
  471 void
  472 generate_free(struct generate *gen)
  473 {
  474     struct address_node *node;
  475 
  476     /* Remove generator and attached addr nodes */
  477     for (node = TAILQ_FIRST(&gen->gen_anqueue);
  478          node;
  479          node = TAILQ_FIRST(&gen->gen_anqueue)) {
  480         TAILQ_REMOVE(&gen->gen_anqueue, node, an_next);
  481         xfree(node);
  482     }
  483 
  484     TAILQ_REMOVE(&genqueue, gen, gen_next);
  485     xfree(gen);
  486 }
  487 
  488 /*
  489  * Given an IP prefix and mask create all addresses contained
  490  * excluding any addresses specified in the exclude queues.
  491  */
  492 
  493 int
  494 populate(struct argument **pargs, int *nargs)
  495 {
  496     struct generate *gen;
  497     struct addr addr;
  498     struct address_slot *slot = NULL;
  499     struct argument *args;
  500     int count;
  501 
  502     uint32_t i = 0;
  503 
  504     if (!TAILQ_FIRST(&genqueue))
  505         return (-1);
  506 
  507     if ((slot = slot_get()) == NULL)
  508         return (-1);
  509 
  510     args = slot->slot_base;
  511     count = slot->slot_size;
  512 
  513     while (TAILQ_FIRST(&genqueue) && count) {
  514         struct port *ports;
  515         int nports;
  516 
  517         gen = TAILQ_FIRST(&genqueue);
  518         ports = gen->gen_ports;
  519         nports = gen->gen_nports;
  520 
  521         
  522         /* Initalize generator */
  523         if (!gen->gen_current) {
  524             if (gen->gen_flags & FLAGS_USERANDOM)
  525                 rndsboxinit(gen->gen_seed);
  526 
  527             gen->gen_current = gen->gen_start;
  528         }
  529 
  530         while (count) {
  531             if (next_address(gen, &addr) == -1) {
  532                 generate_free(gen);
  533                 break;
  534             }
  535 
  536             DFPRINTF((stderr, "New address: %s\n",
  537                      addr_ntoa(&addr)));
  538 
  539             /* Set up a new address for scanning */
  540             memset(&args[i], 0, sizeof(struct argument));
  541             args[i].addr = addr;
  542             args[i].a_slot = slot;
  543             args[i].a_scanner = ss_scanners[0];
  544             args[i].a_scanneroff = 0;
  545             args[i].a_seqnr = rand_uint32(ss_rand);
  546 
  547             /*
  548              * If we have a local port range from the generator
  549              * use that.  Otherwise, use the ports that have
  550              * been supplied globally.
  551              */
  552             if (ports != NULL) {
  553                 args[i].a_ports = ports;
  554                 args[i].a_nports = nports;
  555             } else {
  556                 args[i].a_ports = ss_ports;
  557                 args[i].a_nports = ss_nports;
  558             }
  559 
  560             evtimer_set(&args[i].ev, ss_timeout, &args[i]);
  561 
  562             slot->slot_ref++;
  563             ss_nhosts++;
  564 
  565             count--;
  566             i++;
  567         }
  568     }
  569 
  570     *pargs = args;
  571     *nargs = i;
  572 
  573     return (0);
  574 }
  575 
  576 int
  577 address_from_offset(struct address_node *an, uint32_t offset,
  578     struct addr *addr)
  579 {
  580     ip_addr_t start, end;
  581     for (; an; an = TAILQ_NEXT(an, an_next)) {
  582         *addr = an->an_start;
  583         start = ntohl(an->an_start.addr_ip);
  584         end = ntohl(an->an_end.addr_ip);
  585         if (start + offset <= end)
  586             break;
  587         offset -= end - start + 1;
  588     }
  589 
  590     if (an == NULL)
  591         return (-1);
  592 
  593     addr->addr_ip = htonl(start + offset);
  594 
  595     return (0);
  596 }
  597 
  598 /*
  599  * get the next address, keep state.
  600  */
  601 
  602 int
  603 next_address(struct generate *gen, struct addr *addr)
  604 {
  605     struct addr ipv4addr, tmp;
  606     uint32_t offset;
  607     int done = 0, random;
  608 
  609     /* Check if generator has been exhausted */
  610     if (gen->gen_n >= gen->gen_max)
  611         return (-1);
  612 
  613     random = gen->gen_flags & FLAGS_USERANDOM;
  614 
  615     do {
  616         /* Get offset into address range */
  617         if (random)
  618             offset = rndgetaddr(gen->gen_bits,
  619                 gen->gen_current);
  620         else
  621             offset = gen->gen_current;
  622         
  623         gen->gen_current += gen->gen_iterate;
  624         
  625         if (address_from_offset(TAILQ_FIRST(&gen->gen_anqueue),
  626             offset, &ipv4addr) == -1)
  627             continue;
  628         
  629         if (!random || rndexclude) {
  630             tmp = exclude(ipv4addr, &excludequeue);
  631             if (addr_cmp(&ipv4addr, &tmp)) {
  632                 if (random) {
  633                     if (gen->gen_flags & FLAGS_SUBTRACTEXCLUDE)
  634                         gen->gen_max--;
  635 
  636                     continue;
  637                 }
  638 
  639                 /* In linear mode, we can skip these */
  640                 offset = gen->gen_current;
  641                 offset += ntohl(tmp.addr_ip) - ntohl(ipv4addr.addr_ip);
  642                 if (offset < gen->gen_current) {
  643                     gen->gen_current = gen->gen_end;
  644                     break;
  645                 }
  646                 gen->gen_current = offset;
  647                 
  648                 if (gen->gen_iterate == 1)
  649                     continue;
  650 
  651                 /* Adjust for splits */
  652                 offset /= gen->gen_iterate;
  653                 offset *= gen->gen_iterate;
  654 
  655                 offset += gen->gen_start;
  656 
  657                 if (offset < gen->gen_current)
  658                     offset += gen->gen_iterate;
  659                 if (offset < gen->gen_current) {
  660                     gen->gen_current = gen->gen_end;
  661                     break;
  662                 }
  663 
  664                 gen->gen_current = offset;
  665                 continue;
  666             }
  667         }
  668         
  669         if (random) {
  670             tmp = exclude(ipv4addr, &rndexclqueue);
  671             if (addr_cmp(&ipv4addr, &tmp)) {
  672                 if (gen->gen_flags & FLAGS_SUBTRACTEXCLUDE)
  673                     gen->gen_max--;
  674                 continue;
  675             }
  676         }
  677         
  678         /* We have an address */
  679         done = 1;
  680     } while ((gen->gen_current < gen->gen_end) && 
  681         (gen->gen_n < gen->gen_max) && !done);
  682 
  683     if (!done)
  684         return (-1);
  685 
  686     gen->gen_n += gen->gen_iterate;
  687 
  688     *addr = ipv4addr;
  689 
  690     return (0);
  691 }
  692 
  693 struct address_node *
  694 address_node_get(char *line)
  695 {
  696     struct address_node *an;
  697 
  698     /* Allocate an address node */
  699     an = xmalloc(sizeof(struct address_node));
  700     memset(an, 0, sizeof(struct address_node));
  701     if (addr_pton(line, &an->an_start) == -1) {
  702         fprintf(stderr, "Can not parse %s\n", line);
  703         goto error;
  704     }
  705     /* Working around libdnet bug */
  706     if (strcmp(line, "0.0.0.0/0") == 0)
  707         an->an_start.addr_bits = 0;
  708 
  709     an->an_bits = an->an_start.addr_bits;
  710 
  711     addr_bcast(&an->an_start, &an->an_end);
  712     an->an_start.addr_bits = IP_ADDR_BITS;
  713     an->an_end.addr_bits = IP_ADDR_BITS;
  714 
  715     return (an);
  716 
  717  error:
  718     free(an);
  719     return (NULL);
  720 }
  721 
  722 /*
  723  * Creates a generator from a command line
  724  * [split(x/n)/][random(x,s)/][(]<address/mask> .... [)]
  725  */
  726 
  727 int
  728 generate_split(struct generate *gen, char **pline)
  729 {
  730     char *line, *end;
  731 
  732     line = *pline;
  733 
  734     if ((end = strstr(line, ")/")) == NULL ||
  735         strchr(line, '/') < end) {
  736         fprintf(stderr, "Split not terminated correctly: %s\n", line);
  737         return (-1);
  738     }
  739 
  740     line =  strsep(pline, "/");
  741 
  742     /* Generate a random scan entry */
  743     if (sscanf(line, "split(%d,%d)/",
  744            &gen->gen_start, &gen->gen_iterate) != 2)
  745         return (-1);
  746         
  747     if (!gen->gen_start || gen->gen_start > gen->gen_iterate) {
  748         fprintf(stderr, "Invalid start/iterate pair: %d/%d\n",
  749             gen->gen_start, gen->gen_iterate);
  750         return (-1);
  751     }
  752 
  753     /* Internally, we start counting at 0 */
  754     gen->gen_start--;
  755 
  756     return (0);
  757 }
  758 
  759 /*
  760  * Creates a generator from a command line
  761  * [split(x/n)/][random(x,s)/][(]<address/mask> .... [)]
  762  */
  763 
  764 int
  765 generate_random(struct generate *gen, char **pline)
  766 {
  767     int i;
  768     char seed[31], *line, *end;
  769 
  770     line = *pline;
  771 
  772     if ((end = strstr(line, ")/")) == NULL ||
  773         strchr(line, '/') < end) {
  774         fprintf(stderr, "Random not terminated correctly: %s\n", line);
  775         return (-1);
  776     }
  777 
  778     line = strsep(pline, "/");
  779 
  780     /* Generate a random scan entry */
  781     seed[0] = '\0';
  782     if (sscanf(line, "random(%d,%30s)/", &gen->gen_max, seed) < 1)
  783         return (-1);
  784         
  785     /* Generate seed from string */
  786     if (strlen(seed)) {
  787         MD5_CTX ctx;
  788         uint8_t digest[16];
  789         uint32_t *tmp = (uint32_t *)digest;
  790 
  791         MD5Init(&ctx);
  792         MD5Update(&ctx, seed, strlen(seed));
  793         MD5Final(digest, &ctx);
  794 
  795         gen->gen_seed = 0;
  796         for (i = 0; i < 4; i ++)
  797             gen->gen_seed ^= *tmp++;
  798                 
  799     } else
  800         gen->gen_seed = rand_uint32(ss_rand);
  801 
  802     gen->gen_flags |= FLAGS_USERANDOM;
  803 
  804     /* If the random numbers exhaust all possible addresses,
  805      * we need to subtract those addresses from the count
  806      * that can not be generated because they were excluded
  807      */
  808     if (!gen->gen_max)
  809         gen->gen_flags |= FLAGS_SUBTRACTEXCLUDE;
  810 
  811     return (0);
  812 }
  813 
  814 int
  815 generate(char *line)
  816 {
  817     struct generate *gen;
  818     struct address_node *an;
  819     uint32_t count, tmp;
  820     char *p;
  821     int bits, i, done;
  822 
  823     gen = xmalloc(sizeof(struct generate));
  824     memset(gen, 0, sizeof(struct generate));
  825     TAILQ_INIT(&gen->gen_anqueue);
  826 
  827     /* Insert in generator queue, on failure generate_free removes it */
  828     TAILQ_INSERT_TAIL(&genqueue, gen, gen_next);
  829 
  830     /* Check for port ranges */
  831     p = strsep(&line, ":");
  832     if (line != NULL) {
  833         if (ports_parse(line,
  834             &gen->gen_ports, &gen->gen_nports) == -1) {
  835             fprintf(stderr, "Bad port range: %s\n", line);
  836             goto fail;
  837         }
  838     }
  839     line = p;
  840 
  841     done = 0;
  842     while (!done) {
  843         done = 1;
  844         if (strncmp(line, "random(", 7) == 0) {
  845             if (gen->gen_flags & FLAGS_USERANDOM) {
  846                 fprintf(stderr,
  847                     "Random already specified: %s\n",
  848                     line);
  849                 goto fail;
  850             }
  851             if (generate_random(gen, &line) == -1)
  852                 goto fail;
  853 
  854             done = 0;
  855         } else if (strncmp(line, "split(", 6) == 0) {
  856             if (gen->gen_iterate) {
  857                 fprintf(stderr,
  858                     "Split already specified: %s\n",
  859                     line);
  860                 goto fail;
  861             }
  862             if (generate_split(gen, &line) == -1)
  863                 goto fail;
  864 
  865             done = 0;
  866         }
  867     }
  868 
  869     /* If no special split is specified, always iterated by 1 */
  870     if (!gen->gen_iterate)
  871         gen->gen_iterate = 1;
  872 
  873     if (line[0] == '(') {
  874         char *end;
  875         
  876         line++;
  877         if ((end = strchr(line, ')')) == NULL) {
  878             fprintf(stderr, "Missing ')' in line: %s\n", line);
  879             goto fail;
  880         }
  881         *end = '\0';
  882         
  883     }
  884 
  885     while (line && (p = strsep(&line, " "))) {
  886         if ((an = address_node_get(p)) == NULL)
  887             goto fail;
  888 
  889         TAILQ_INSERT_TAIL(&gen->gen_anqueue, an, an_next);
  890     }
  891 
  892     /* Try to find out the effective bit range */
  893     count = 0;
  894     for (an = TAILQ_FIRST(&gen->gen_anqueue); an;
  895          an = TAILQ_NEXT(an, an_next)) {
  896         bits = an->an_bits;
  897         if (bits == 0) {
  898             count = -1;
  899             break;
  900         }
  901 
  902         if (count + (1 << (32 - bits)) < count) {
  903             count = -1;
  904             break;
  905         }
  906 
  907         count += 1 << (32 - bits);
  908     }
  909 
  910     /* Try to convert count into a network mask */
  911     bits = 0;
  912     tmp = count;
  913     for (i = -1; tmp; tmp >>= 1, i++) {
  914         if (tmp & 1)
  915             bits++;
  916     }
  917 
  918     /* a count of 01100, results in bits = 29, but it should be 28 */
  919     gen->gen_bits = 32 - i;
  920     if (bits > 1)
  921         gen->gen_bits--;
  922     bits = gen->gen_bits;
  923 
  924     if (gen->gen_flags & FLAGS_USERANDOM) {
  925         if (bits == 0)
  926             gen->gen_end = -1;
  927         else 
  928             gen->gen_end = 1 << (32 - bits);
  929     } else
  930         gen->gen_end = count;
  931 
  932     if (gen->gen_max == 0)
  933         gen->gen_max = count;
  934 
  935     return (0);
  936  fail:
  937     if (gen)
  938         generate_free(gen);
  939 
  940     return (-1);
  941 }
  942 
  943 int
  944 probe_haswork(void)
  945 {
  946     return (TAILQ_FIRST(&genqueue) || entries || !synlist_empty());
  947 }
  948 
  949 void
  950 probe_send(int fd, short what, void *parameter)
  951 {
  952     struct event *ev = parameter;
  953     struct timeval tv;
  954     int ntotal, nprobes, nsent;
  955     extern int scan_nhosts;
  956 
  957     /* Schedule the next probe */
  958     if (probe_haswork()) {
  959         timerclear(&tv);
  960         tv.tv_usec = 1000000L / syn_rate;
  961         evtimer_add(ev, &tv);
  962     } else if (TAILQ_FIRST(&readyqueue) == NULL && !scan_nhosts) {
  963         struct timeval tv;
  964 
  965         /* Terminate the event loop */
  966         timerclear(&tv);
  967         tv.tv_sec = 2;
  968         event_loopexit(&tv);
  969     }
  970 
  971     gettimeofday(&tv, NULL);
  972     timersub(&tv, &syn_start, &tv);
  973 
  974     ntotal = tv.tv_sec * syn_rate + (tv.tv_usec * syn_rate) / 1000000L;
  975     nprobes = ntotal - syn_nsent;
  976 
  977     nsent = 0;
  978     while ((TAILQ_FIRST(&genqueue) || entries) && nsent < nprobes) {
  979         /* Create new entries, if we need them */
  980         if (!entries && TAILQ_FIRST(&genqueue)) {
  981             if (populate(&args, &entries) == -1) {
  982                 /* 
  983                  * We fail if we have used up our memory.
  984                  * We also need to consume our number of
  985                  * sent packets.
  986                  */
  987                 syn_nsent = ntotal;
  988                 entries = 0;
  989                 break;
  990             }
  991             continue;
  992         }
  993 
  994         entries--;
  995         args[entries].a_retry = 0;
  996 
  997         if (TAILQ_FIRST(&socks_host) == NULL) {
  998             synlist_insert(&args[entries]);
  999 
 1000             /* 
 1001              * On failure, synlist_insert already scheduled
 1002              * a retransmit.
 1003              */
 1004             synlist_probe(&args[entries],
 1005                 args[entries].a_ports[0].port);
 1006         } else {
 1007             struct argument *arg = &args[entries];
 1008             if (!arg->a_hasports)
 1009                 ports_setup(arg, arg->a_ports, arg->a_nports);
 1010             scanhost_ready(arg);
 1011         }
 1012 
 1013         nsent++;
 1014         syn_nsent++;
 1015     }
 1016 }
 1017 
 1018 int
 1019 parse_socks_host(char *optarg)
 1020 {
 1021     char *host;
 1022     while ((host = strsep(&optarg, ",")) != NULL) {
 1023         /*
 1024          * Parse the address of a SOCKS proxy that we are
 1025          * using for all connections.
 1026          */
 1027         struct socks_host *single_host;
 1028 
 1029         char *address = strsep(&host, ":");
 1030         if (host == NULL || *host == '\0')
 1031             return (-1);
 1032 
 1033         single_host = calloc(1, sizeof(struct socks_host));
 1034         if (single_host == NULL)
 1035             err(1, "calloc");
 1036         if (addr_pton(address, &single_host->host) == -1)
 1037             return (-1);
 1038 
 1039         if ((single_host->port = atoi(host)) == 0)
 1040             return (-1);
 1041 
 1042         TAILQ_INSERT_TAIL(&socks_host, single_host, next);
 1043     }
 1044 
 1045     return (0);
 1046 }
 1047 
 1048 int
 1049 main(int argc, char **argv)
 1050 {
 1051     struct event ev_send;
 1052     char *name, *dev = NULL, *scanner = "ssh";
 1053     char *default_ports = "22";
 1054     int ch;
 1055     struct timeval tv, tv_start, tv_end;
 1056     struct rlimit rl;
 1057     int failonexclude = 0;
 1058     int milliseconds;
 1059 
 1060     ssh_sendident = 1;
 1061 
 1062     TAILQ_INIT(&socks_host);
 1063 
 1064     name = argv[0];
 1065     while ((ch = getopt(argc, argv, "VIhdpm:u:s:i:e:n:r:ER")) != -1)
 1066         switch(ch) {
 1067         case 'V':
 1068             fprintf(stderr, "ScanSSH %s\n", VERSION);
 1069             exit(0);
 1070 #ifdef DEBUG
 1071         case 'd':
 1072             debug++;
 1073             break;
 1074 #endif
 1075         case 'I':
 1076             ssh_sendident = 0;
 1077             break;
 1078         case 'p':
 1079             scanner = "http-proxy,http-connect,socks5,socks4,telnet-proxy,ssh";
 1080             default_ports = "23,22,80,81,808,1080,1298,3128,6588,4480,8080,8081,8000,8100,9050";
 1081             break;
 1082         case 'm':
 1083             max_scanqueue_size = atoi(optarg);
 1084             if (max_scanqueue_size == 0) {
 1085                 usage(name);
 1086                 exit(1);
 1087             }
 1088             break;
 1089         case 'u': 
 1090             if (parse_socks_host(optarg) == -1) {
 1091                 usage(name);
 1092                 exit(1);
 1093             }
 1094             break;
 1095         case 's':
 1096             scanner = optarg;
 1097             break;
 1098         case 'i':
 1099             dev = optarg;
 1100             break;
 1101         case 'n':
 1102             if (ports_parse(optarg, &ss_ports, &ss_nports) == -1) {
 1103                 usage(name);
 1104                 exit(1);
 1105             }
 1106             break;
 1107         case 'e':
 1108             excludefile = optarg;
 1109             /* FALLTHROUGH */
 1110         case 'E':
 1111             failonexclude = 1;
 1112             break;
 1113         case 'R':
 1114             rndexclude=0;
 1115             break;
 1116         case 'r':
 1117             syn_rate = atoi(optarg);
 1118             if (syn_rate == 0) {
 1119                 fprintf(stderr, "Bad syn probe rate: %s\n",
 1120                     optarg);
 1121                 usage(name);
 1122                 exit(1);
 1123             }
 1124             break;
 1125         case 'h':
 1126         default:
 1127             usage(name);
 1128             exit(1);
 1129         }
 1130 
 1131     argc -= optind;
 1132     argv += optind;
 1133 
 1134     if (scanner_parse(scanner) == -1)
 1135         errx(1, "bad scanner: %s", scanner);
 1136 
 1137     if ((ss_rand = rand_open()) == NULL)
 1138         err(1, "rand_open");
 1139 
 1140     if ((ss_ip = ip_open()) == NULL)
 1141         err(1, "ip_open");
 1142 
 1143     scanssh_init();
 1144     
 1145     event_init();
 1146 
 1147     interface_initialize();
 1148 
 1149     /* Initialize the specified interfaces */
 1150     interface_init(dev, 0, NULL,
 1151         "(tcp[13] & 18 = 18 or tcp[13] & 4 = 4)");
 1152 
 1153     /* Raising file descriptor limits */
 1154     rl.rlim_max = RLIM_INFINITY;
 1155     rl.rlim_cur = RLIM_INFINITY;
 1156     if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
 1157         /* Linux does not seem to like this */
 1158         if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
 1159             err(1, "getrlimit: NOFILE");
 1160         rl.rlim_cur = rl.rlim_max;
 1161         if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
 1162             err(1, "setrlimit: NOFILE");
 1163     }
 1164 
 1165     /* Raising the memory limits */
 1166     rl.rlim_max = RLIM_INFINITY;
 1167     rl.rlim_cur = MAXSLOTS * EXPANDEDARGS * sizeof(struct argument) * 2;
 1168     if (setrlimit(RLIMIT_DATA, &rl) == -1) {
 1169         /* Linux does not seem to like this */
 1170         if (getrlimit(RLIMIT_DATA, &rl) == -1)
 1171             err(1, "getrlimit: DATA");
 1172         rl.rlim_cur = rl.rlim_max;
 1173         if (setrlimit(RLIMIT_DATA, &rl) == -1)
 1174             err(1, "setrlimit: DATA");
 1175     }
 1176     
 1177        
 1178     /* revoke privs */
 1179 #ifdef HAVE_SETEUID
 1180         seteuid(getuid());
 1181 #endif /* HAVE_SETEUID */
 1182         setuid(getuid());
 1183 
 1184     /* Set up our port ranges */
 1185     if (ss_nports == 0) {
 1186         if (ports_parse(default_ports, &ss_ports, &ss_nports) == -1)
 1187             errx(1, "Error setting up port list");
 1188     }
 1189 
 1190     if (setupexcludes() == -1 && failonexclude) {
 1191         warn("fopen: %s", excludefile);
 1192         exit(1);
 1193     }
 1194 
 1195     memset(slots, 0, sizeof(slots));
 1196 
 1197     TAILQ_INIT(&genqueue);
 1198 
 1199     while (argc) {
 1200         if (generate(argv[0]) == -1)
 1201             warnx("generate failed on %s", argv[0]);
 1202 
 1203         argv++;
 1204         argc--;
 1205     }
 1206 
 1207     if (!TAILQ_FIRST(&genqueue))
 1208         errx(1, "nothing to scan");
 1209 
 1210     gettimeofday(&syn_start, NULL);
 1211 
 1212     evtimer_set(&ev_send, probe_send, &ev_send);
 1213     timerclear(&tv);
 1214     tv.tv_usec = 1000000L / syn_rate;
 1215     evtimer_add(&ev_send, &tv);
 1216 
 1217     gettimeofday(&tv_start, NULL);
 1218 
 1219     event_dispatch();
 1220 
 1221     /* Measure our effective host scan rate */
 1222 
 1223     gettimeofday(&tv_end, NULL);
 1224 
 1225     timersub(&tv_end, &tv_start, &tv_end);
 1226 
 1227     milliseconds = tv_end.tv_sec * 1000 + tv_end.tv_usec % 1000;
 1228 
 1229     fprintf(stderr, "Effective host scan rate: %.2f hosts/s\n",
 1230         (float)ss_nhosts / (float) milliseconds * 1000.0);
 1231 
 1232     return (1);
 1233 }
 1234 
 1235 void
 1236 ports_timeout(int fd, short what, void *parameter)
 1237 {
 1238     struct port_scan *ps = parameter;
 1239     struct argument *arg = ps->arg;
 1240     struct timeval tv;
 1241 
 1242     if (ps->count < SYNRETRIES) {
 1243         ps->count++;
 1244         /*
 1245          * If this probe fails we are not reducing the retry counter,
 1246          * as some of the failures might repeat always, like a host
 1247          * on the local network not being reachable or some unrouteable
 1248          * address space,
 1249          */
 1250         if (synlist_probe(arg, ps->port) == -1)
 1251             goto reschedule;
 1252 
 1253         syn_nsent++;
 1254     } else {
 1255         printres(arg, ps->port, "<timeout>");
 1256         ports_remove(arg, ps->port);
 1257         if (arg->a_nports == 0) {
 1258             synlist_remove(arg);
 1259             argument_free(arg);
 1260             return;
 1261         }
 1262         return;
 1263     }
 1264 
 1265  reschedule:
 1266     timerclear(&tv);
 1267     tv.tv_sec += (arg->a_retry/2 + 1) * SYNWAIT;
 1268     tv.tv_usec = rand_uint32(ss_rand) % 1000000L;
 1269     
 1270     evtimer_add(&arg->ev, &tv);
 1271 }
 1272 
 1273 /* Mark a port as checked - meaning that we can connect to it */
 1274 
 1275 void
 1276 ports_markchecked(struct argument *arg, struct port *port)
 1277 {
 1278     struct port_scan *ps = port->scan;
 1279 
 1280     DNFPRINTF(2, (stderr, "%s: %s:%d marked alive\n",
 1281               __func__, addr_ntoa(&arg->addr), port->port));
 1282 
 1283     if (ps == NULL) {
 1284         /* Populates scan structures */
 1285         ports_isalive(arg);
 1286 
 1287         /* This argument has a new memory area now */
 1288         port = ports_find(arg, port->port);
 1289         ps = port->scan;
 1290     }
 1291 
 1292     event_del(&ps->ev);
 1293     ps->flags |= PORT_CHECKED;
 1294 }
 1295 
 1296 /* Checks if all ports for this host have been checked to be alive */
 1297 
 1298 int
 1299 ports_isalive(struct argument *arg)
 1300 {
 1301     struct port_scan *ps;
 1302     int i;
 1303 
 1304     /* We already populated the structures */
 1305     if (arg->a_ports[0].scan != NULL) {
 1306         for (i = 0; i < arg->a_nports; i++)
 1307             if (!(arg->a_ports[i].scan->flags & PORT_CHECKED))
 1308                 return (0);
 1309         for (i = 0; i < arg->a_nports; i++) {
 1310             ps = arg->a_ports[i].scan;
 1311             event_del(&ps->ev);
 1312             free(ps);
 1313             arg->a_ports[i].scan = NULL;
 1314         }
 1315         return (1);
 1316     }
 1317 
 1318     /* This host was newly detected as alive */
 1319     for (i = 0; i < arg->a_nports; i++) {
 1320         struct timeval tv;
 1321 
 1322         if ((ps = calloc(1, sizeof(struct port_scan))) == NULL)
 1323             err(1, "%s: calloc");
 1324         arg->a_ports[i].scan = ps;
 1325 
 1326         ps->arg = arg;
 1327         ps->port = arg->a_ports[i].port;
 1328         evtimer_set(&ps->ev, ports_timeout, ps);
 1329 
 1330         timerclear(&tv);
 1331         tv.tv_usec = rand_uint32(ss_rand) % 1000000L;
 1332         
 1333         evtimer_add(&ps->ev, &tv);
 1334     }
 1335 
 1336     return (0);
 1337 }
 1338 
 1339 /* Copy the ports list to the argument and use it for scanning */
 1340 
 1341 int
 1342 ports_setup(struct argument *arg, struct port *ports, int nports)
 1343 {
 1344     arg->a_hasports = 1;
 1345     arg->a_nports = nports;
 1346     if ((arg->a_ports = calloc(nports, sizeof(struct port))) == NULL)
 1347         err(1, "%s: calloc", __func__);
 1348 
 1349     memcpy(arg->a_ports, ports, nports * sizeof(struct port));
 1350 
 1351     return (0);
 1352 }
 1353 
 1354 struct port *
 1355 ports_find(struct argument *arg, uint16_t port)
 1356 {
 1357     int i;
 1358 
 1359     for (i = 0; i < arg->a_nports; i++)
 1360         if (arg->a_ports[i].port == port)
 1361             return (&arg->a_ports[i]);
 1362 
 1363     return (NULL);
 1364 }
 1365 
 1366 /* Remove one port from the list and reduce the number of available ports */
 1367 
 1368 int
 1369 ports_remove(struct argument *arg, uint16_t port)
 1370 {
 1371     int i;
 1372 
 1373     for (i = 0; i < arg->a_nports; i++) {
 1374         if (arg->a_ports[i].port == port) {
 1375             /* Deallocate the scan structure if necessary */
 1376             if (arg->a_ports[i].scan != NULL) {
 1377                 event_del(&arg->a_ports[i].scan->ev);
 1378                 free(arg->a_ports[i].scan);
 1379             }
 1380             arg->a_nports--;
 1381             if (i < arg->a_nports) {
 1382                 arg->a_ports[i] = arg->a_ports[arg->a_nports];
 1383             } else if (arg->a_nports == 0) {
 1384                 free (arg->a_ports);
 1385                 arg->a_ports = NULL;
 1386             }
 1387             return (0);
 1388         }
 1389     }
 1390 
 1391     return (-1);
 1392 }
 1393 
 1394 /* Parse the list of ports and put them into an array */
 1395 
 1396 int
 1397 ports_parse(char *argument, struct port **pports, int *pnports)
 1398 {
 1399     char buf[1024], *line = buf;
 1400     char *p, *e;
 1401     int size, count, val;
 1402     struct port *ports = *pports;
 1403     struct port port;
 1404 
 1405     strlcpy(buf, argument, sizeof(buf));
 1406 
 1407     memset(&port, 0, sizeof(port));
 1408 
 1409     count = 0;
 1410     size = 0;
 1411     while ((p = strsep(&line, ",")) != NULL) {
 1412         val = strtoul(p, &e, 10);
 1413         if (p[0] == '\0' || *e != '\0')
 1414             return (-1);
 1415         if (val <= 0 || val > 65535)
 1416             return (-1);
 1417 
 1418         if (count >= size) {
 1419             struct port *tmpports;
 1420             if (size == 0)
 1421                 size = 10;
 1422             else
 1423                 size <<= 1;
 1424 
 1425             tmpports = realloc(ports, size*sizeof(struct port));
 1426             if (tmpports == NULL)
 1427                 err(1, "realloc");
 1428             ports = tmpports;
 1429             memset(&ports[count], 0,
 1430                 (size - count) * sizeof(struct port));
 1431         }
 1432 
 1433         port.port = val;
 1434         ports[count++] = port;
 1435     }
 1436 
 1437     if (count == 0)
 1438         return (-1);
 1439 
 1440     *pports = ports;
 1441     *pnports = count;
 1442     return (0);
 1443 }
 1444 
 1445 /* Parse the list of scanners and put them into an array */
 1446 
 1447 int
 1448 scanner_parse(char *argument)
 1449 {
 1450     char buf[1024], *line = buf;
 1451     char *p;
 1452     int size, count;
 1453     struct scanner *scanner;
 1454 
 1455     strlcpy(buf, argument, sizeof(buf));
 1456 
 1457     count = 0;
 1458     size = 0;
 1459     while ((p = strsep(&line, ",")) != NULL) {
 1460         if ((scanner = scanner_find(p)) == NULL)
 1461             return (-1);
 1462 
 1463         if (count >= size) {
 1464             struct scanner **tmpscanners;
 1465             if (size == 0)
 1466                 size = 10;
 1467             else
 1468                 size <<= 1;
 1469 
 1470             tmpscanners = realloc(ss_scanners,
 1471                 size * sizeof(struct scanner *));
 1472             if (tmpscanners == NULL)
 1473                 err(1, "realloc");
 1474             ss_scanners = tmpscanners;
 1475             memset(&ss_scanners[count], 0,
 1476                 (size - count) * sizeof(struct scanner *));
 1477         }
 1478         ss_scanners[count++] = scanner;
 1479     }
 1480 
 1481     if (count == 0)
 1482         return (-1);
 1483 
 1484     ss_nscanners = count;
 1485     return (0);
 1486 }