[BACK]Return to netcat.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / nc

Annotation of src/usr.bin/nc/netcat.c, Revision 1.10

1.1       deraadt     1: /* Netcat 1.10 RELEASE 960320
1.7       deraadt     2:  *
                      3:  *   A damn useful little "backend" utility begun 950915 or thereabouts,
                      4:  *   as *Hobbit*'s first real stab at some sockets programming.  Something that
                      5:  *   should have and indeed may have existed ten years ago, but never became a
                      6:  *   standard Unix utility.  IMHO, "nc" could take its place right next to cat,
                      7:  *   cp, rm, mv, dd, ls, and all those other cryptic and Unix-like things.
                      8:  *
                      9:  *   Read the README for the whole story, doc, applications, etc.
                     10:  *
                     11:  *   Layout:
                     12:  *     conditional includes:
                     13:  *     includes:
                     14:  *     handy defines:
                     15:  *     globals:
                     16:  *     malloced globals:
                     17:  *     cmd-flag globals:
                     18:  *     support routines:
                     19:  *     readwrite select loop:
                     20:  *     main:
                     21:  *
                     22:  *  bluesky:
                     23:  *     parse ranges of IP address as well as ports, perhaps
                     24:  *     RAW mode!
                     25:  *     backend progs to grab a pty and look like a real telnetd?!
                     26:  *     backend progs to do various encryption modes??!?!
1.1       deraadt    27: */
                     28:
                     29: #include "generic.h"           /* same as with L5, skey, etc */
                     30:
                     31: /* conditional includes -- a very messy section which you may have to dink
                     32:    for your own architecture [and please send diffs...]: */
                     33: /* #undef _POSIX_SOURCE                /* might need this for something? */
                     34: #define HAVE_BIND              /* ASSUMPTION -- seems to work everywhere! */
                     35:
1.7       deraadt    36: #include <sys/types.h>
                     37: #include <sys/time.h>
                     38: #include <sys/select.h>
                     39: #include <sys/socket.h>
                     40: #include <netinet/in.h>
                     41: #include <netinet/in_systm.h>
                     42: #include <netinet/ip.h>
                     43: #include <arpa/inet.h>
                     44: #include <netdb.h>             /* hostent, gethostby*, getservby* */
                     45: #include <stdio.h>
                     46: #include <string.h>
                     47: #include <errno.h>
                     48: #include <setjmp.h>
                     49: #include <signal.h>
                     50: #include <fcntl.h>
1.1       deraadt    51: #include <stdlib.h>
1.5       art        52: #include <unistd.h>
1.1       deraadt    53:
                     54: #ifdef HAVE_RANDOM             /* aficionados of ?rand48() should realize */
                     55: #define SRAND srandom          /* that this doesn't need *strong* random */
                     56: #define RAND random            /* numbers just to mix up port numbers!! */
                     57: #else
                     58: #define SRAND srand
                     59: #define RAND rand
1.6       deraadt    60: #endif                         /* HAVE_RANDOM */
1.1       deraadt    61:
                     62: #define SLEAZE_PORT 31337      /* for UDP-scan RTT trick, change if ya want */
                     63: #define BIGSIZ 8192            /* big buffers */
                     64:
1.7       deraadt    65: struct host_info {
1.6       deraadt    66:        char    name[MAXHOSTNAMELEN];   /* dns name */
                     67:        char    addrs[8][24];   /* ascii-format IP addresses */
                     68:        struct in_addr iaddrs[8];       /* real addresses: in_addr.s_addr:
                     69:                                         * ulong */
1.1       deraadt    70: };
                     71:
1.7       deraadt    72: struct port_info {
1.6       deraadt    73:        char    name[64];       /* name in /etc/services */
                     74:        char    anum[8];        /* ascii-format number */
1.7       deraadt    75:        u_short  num;           /* real host-order number */
1.1       deraadt    76: };
                     77:
                     78: /* globals: */
                     79: jmp_buf jbuf;                  /* timer crud */
1.6       deraadt    80: int     jval = 0;              /* timer crud */
                     81: int     netfd = -1;
                     82: int     ofd = 0;               /* hexdump output fd */
1.7       deraadt    83:
1.1       deraadt    84: extern int h_errno;
                     85: /* stolen almost wholesale from bsd herror.c */
1.6       deraadt    86: static char *h_errs[] = {
                     87:        "Error 0",              /* but we *don't* use this */
                     88:        "Unknown host",         /* 1 HOST_NOT_FOUND */
                     89:        "Host name lookup failure",     /* 2 TRY_AGAIN */
                     90:        "Unknown server error", /* 3 NO_RECOVERY */
                     91:        "No address associated with name",      /* 4 NO_ADDRESS */
1.1       deraadt    92: };
1.7       deraadt    93:
1.6       deraadt    94: int     gatesidx = 0;          /* LSRR hop count */
                     95: int     gatesptr = 4;          /* initial LSRR pointer, settable */
1.7       deraadt    96: u_short  Single = 1;           /* zero if scanning */
1.1       deraadt    97: unsigned int insaved = 0;      /* stdin-buffer size for multi-mode */
                     98: unsigned int wrote_out = 0;    /* total stdout bytes */
                     99: unsigned int wrote_net = 0;    /* total net bytes */
                    100: static char wrote_txt[] = " sent %d, rcvd %d";
                    101: static char hexnibs[20] = "0123456789abcdef  ";
                    102:
                    103: /* will malloc up the following globals: */
1.7       deraadt   104: struct timeval timer1, timer2;
                    105: struct sockaddr_in    *lclend = NULL;          /* sockaddr_in structs */
                    106: struct sockaddr_in    *remend = NULL;
                    107: struct host_info  **gates = NULL;              /* LSRR hop hostpoop */
1.6       deraadt   108: char   *optbuf = NULL;         /* LSRR or sockopts */
                    109: char   *bigbuf_in;             /* data buffers */
                    110: char   *bigbuf_net;
1.7       deraadt   111: fd_set fds1, fds2;
                    112: struct port_info   *portpoop = NULL;   /* for getportpoop / getservby* */
1.6       deraadt   113: unsigned char *stage = NULL;   /* hexdump line buffer */
1.1       deraadt   114:
                    115: /* global cmd flags: */
1.7       deraadt   116: u_short  o_alla = 0;
1.1       deraadt   117: unsigned int o_interval = 0;
1.7       deraadt   118: u_short  o_listen = 0;
                    119: u_short  o_nflag = 0;
                    120: u_short  o_wfile = 0;
                    121: u_short  o_random = 0;
                    122: u_short  o_udpmode = 0;
                    123: u_short  o_verbose = 0;
1.1       deraadt   124: unsigned int o_wait = 0;
1.7       deraadt   125: u_short  o_zero = 0;
1.1       deraadt   126: /* o_tn in optional section */
                    127:
                    128: /* Debug macro: squirt whatever message and sleep a bit so we can see it go
                    129:    by.  need to call like Debug ((stuff)) [with no ; ] so macro args match!
                    130:    Beware: writes to stdOUT... */
                    131: #ifdef DEBUG
                    132: #define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
                    133: #else
1.6       deraadt   134: #define Debug(x)               /* nil... */
1.1       deraadt   135: #endif
                    136:
                    137:
                    138: /* support routines -- the bulk of this thing.  Placed in such an order that
                    139:    we don't have to forward-declare anything: */
                    140:
                    141: /* holler :
                    142:    fake varargs -- need to do this way because we wind up calling through
                    143:    more levels of indirection than vanilla varargs can handle, and not all
                    144:    machines have vfprintf/vsyslog/whatever!  6 params oughta be enough. */
1.6       deraadt   145: void
                    146: holler(str, p1, p2, p3, p4, p5, p6)
                    147:        char   *str;
                    148:        char   *p1, *p2, *p3, *p4, *p5, *p6;
1.1       deraadt   149: {
1.6       deraadt   150:        if (o_verbose) {
                    151:                fprintf(stderr, str, p1, p2, p3, p4, p5, p6);
1.1       deraadt   152: #ifdef HAVE_BIND
1.6       deraadt   153:                if (h_errno) {  /* if host-lookup variety of error ... */
                    154:                        if (h_errno > 4)        /* oh no you don't, either */
                    155:                                fprintf(stderr, "preposterous h_errno: %d", h_errno);
                    156:                        else
1.8       deraadt   157:                                fprintf(stderr, "%s", h_errs[h_errno]);
1.6       deraadt   158:                        h_errno = 0;    /* and reset for next call */
                    159:                }
1.1       deraadt   160: #endif
1.6       deraadt   161:                if (errno) {    /* this gives funny-looking messages, but */
                    162:                        perror(" ");    /* it's more portable than
                    163:                                         * sys_errlist[]... */
                    164:                } else          /* xxx: do something better?  */
                    165:                        fprintf(stderr, "\n");
                    166:                fflush(stderr);
                    167:        }
1.7       deraadt   168: }
1.1       deraadt   169:
                    170: /* bail :
                    171:    error-exit handler, callable from anywhere */
1.6       deraadt   172: void
                    173: bail(str, p1, p2, p3, p4, p5, p6)
                    174:        char   *str;
                    175:        char   *p1, *p2, *p3, *p4, *p5, *p6;
                    176: {
                    177:        o_verbose = 1;
                    178:        holler(str, p1, p2, p3, p4, p5, p6);
                    179:        close(netfd);
                    180:        exit(1);
1.7       deraadt   181: }
1.1       deraadt   182:
                    183: /* catch :
                    184:    no-brainer interrupt handler */
1.6       deraadt   185: void
                    186: catch()
1.1       deraadt   187: {
1.6       deraadt   188:        errno = 0;
                    189:        if (o_verbose > 1)      /* normally we don't care */
                    190:                bail(wrote_txt, wrote_net, wrote_out);
                    191:        bail(" punt!");
1.1       deraadt   192: }
                    193:
                    194: /* timeout and other signal handling cruft */
1.6       deraadt   195: void
                    196: tmtravel()
1.1       deraadt   197: {
1.6       deraadt   198:        signal(SIGALRM, SIG_IGN);
                    199:        alarm(0);
                    200:        if (jval == 0)
                    201:                bail("spurious timer interrupt!");
                    202:        longjmp(jbuf, jval);
1.1       deraadt   203: }
                    204:
                    205: /* arm :
                    206:    set the timer.  Zero secs arg means unarm */
1.6       deraadt   207: void
                    208: arm(num, secs)
                    209:        unsigned int num;
                    210:        unsigned int secs;
                    211: {
                    212:        if (secs == 0) {        /* reset */
                    213:                signal(SIGALRM, SIG_IGN);
                    214:                alarm(0);
                    215:                jval = 0;
                    216:        } else {                /* set */
                    217:                signal(SIGALRM, tmtravel);
                    218:                alarm(secs);
                    219:                jval = num;
                    220:        }                       /* if secs */
1.7       deraadt   221: }
1.1       deraadt   222:
                    223: /* findline :
                    224:    find the next newline in a buffer; return inclusive size of that "line",
                    225:    or the entire buffer size, so the caller knows how much to then write().
                    226:    Not distinguishing \n vs \r\n for the nonce; it just works as is... */
1.6       deraadt   227: unsigned int
                    228: findline(buf, siz)
                    229:        char   *buf;
                    230:        unsigned int siz;
                    231: {
                    232:        register char *p;
                    233:        register int x;
                    234:        if (!buf)               /* various sanity checks... */
                    235:                return (0);
                    236:        if (siz > BIGSIZ)
                    237:                return (0);
                    238:        x = siz;
                    239:        for (p = buf; x > 0; x--) {
                    240:                if (*p == '\n') {
                    241:                        x = (int) (p - buf);
                    242:                        x++;    /* 'sokay if it points just past the end! */
                    243:                        Debug(("findline returning %d", x))
                    244:                            return (x);
                    245:                }
                    246:                p++;
                    247:        }                       /* for */
                    248:        Debug(("findline returning whole thing: %d", siz))
                    249:            return (siz);
1.7       deraadt   250: }
1.1       deraadt   251:
                    252: /* comparehosts :
1.7       deraadt   253:    cross-check the host_info we have so far against new gethostby*() info,
1.1       deraadt   254:    and holler about mismatches.  Perhaps gratuitous, but it can't hurt to
                    255:    point out when someone's DNS is fukt.  Returns 1 if mismatch, in case
                    256:    someone else wants to do something about it. */
1.6       deraadt   257: int
                    258: comparehosts(poop, hp)
1.7       deraadt   259:        struct host_info   *poop;
1.6       deraadt   260:        struct hostent *hp;
                    261: {
                    262:        errno = 0;
                    263:        h_errno = 0;
                    264:        if (strcasecmp(poop->name, hp->h_name) != 0) {  /* normal */
                    265:                holler("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
                    266:                return (1);
                    267:        }
                    268:        return (0);
1.1       deraadt   269: /* ... do we need to do anything over and above that?? */
1.7       deraadt   270: }
1.1       deraadt   271:
                    272: /* gethostpoop :
1.7       deraadt   273:    resolve a host 8 ways from sunday; return a new host_info struct with its
1.1       deraadt   274:    info.  The argument can be a name or [ascii] IP address; it will try its
                    275:    damndest to deal with it.  "numeric" governs whether we do any DNS at all,
                    276:    and we also check o_verbose for what's appropriate work to do. */
1.7       deraadt   277: struct host_info   *
1.6       deraadt   278: gethostpoop(name, numeric)
                    279:        char   *name;
1.7       deraadt   280:        u_short  numeric;
1.6       deraadt   281: {
                    282:        struct hostent *hostent;
                    283:        struct in_addr iaddr;
1.7       deraadt   284:        register struct host_info *poop = NULL;
1.6       deraadt   285:        register int x;
1.1       deraadt   286:
                    287: /* I really want to strangle the twit who dreamed up all these sockaddr and
                    288:    hostent abstractions, and then forced them all to be incompatible with
                    289:    each other so you *HAVE* to do all this ridiculous casting back and forth.
                    290:    If that wasn't bad enough, all the doc insists on referring to local ports
                    291:    and addresses as "names", which makes NO sense down at the bare metal.
                    292:
                    293:    What an absolutely horrid paradigm, and to think of all the people who
                    294:    have been wasting significant amounts of time fighting with this stupid
                    295:    deliberate obfuscation over the last 10 years... then again, I like
                    296:    languages wherein a pointer is a pointer, what you put there is your own
                    297:    business, the compiler stays out of your face, and sheep are nervous.
                    298:    Maybe that's why my C code reads like assembler half the time... */
                    299:
                    300: /* If we want to see all the DNS stuff, do the following hair --
1.4       deraadt   301:    if inet_aton, do reverse and forward with any warnings; otherwise try
1.1       deraadt   302:    to do forward and reverse with any warnings.  In other words, as long
                    303:    as we're here, do a complete DNS check on these clowns.  Yes, it slows
                    304:    things down a bit for a first run, but once it's cached, who cares? */
                    305:
1.6       deraadt   306:        errno = 0;
                    307:        h_errno = 0;
                    308:        if (name)
1.7       deraadt   309:                poop = (struct host_info *) calloc(1, sizeof(struct host_info));
1.6       deraadt   310:        if (!poop)
                    311:                bail("gethostpoop fuxored");
1.7       deraadt   312:        strlcpy(poop->name, "(UNKNOWN)", sizeof(poop->name));
                    313:        if (inet_aton(name, &iaddr) == 0) {
1.6       deraadt   314:
                    315:                if (numeric)
                    316:                        bail("Can't parse %s as an IP address", name);
                    317:                hostent = gethostbyname(name);
                    318:                if (!hostent)
1.1       deraadt   319: /* failure to look up a name is fatal, since we can't do anything with it */
1.6       deraadt   320:                        bail("%s: forward host lookup failed: ", name);
1.7       deraadt   321:                strlcpy(poop->name, hostent->h_name, MAXHOSTNAMELEN);
1.6       deraadt   322:                for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
1.7       deraadt   323:                        memcpy(&poop->iaddrs[x], hostent->h_addr_list[x],
                    324:                            sizeof(struct in_addr));
                    325:                        strlcpy(poop->addrs[x], inet_ntoa(poop->iaddrs[x]),
                    326:                            sizeof(poop->addrs[0]));
                    327:                }
1.6       deraadt   328:                if (!o_verbose) /* if we didn't want to see the */
                    329:                        return (poop);  /* inverse stuff, we're done. */
1.1       deraadt   330: /* do inverse lookups in separate loop based on our collected forward addrs,
                    331:    since gethostby* tends to crap into the same buffer over and over */
1.6       deraadt   332:                for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) {
                    333:                        hostent = gethostbyaddr((char *) &poop->iaddrs[x],
1.7       deraadt   334:                            sizeof(struct in_addr), AF_INET);
1.6       deraadt   335:                        if ((!hostent) || (!hostent->h_name))
                    336:                                holler("Warning: inverse host lookup failed for %s: ",
                    337:                                    poop->addrs[x]);
                    338:                        else
                    339:                                (void) comparehosts(poop, hostent);
                    340:                }               /* for x -> addrs, part B */
                    341:
                    342:        } else {                /* not INADDR_NONE: numeric addresses... */
1.7       deraadt   343:                memcpy(poop->iaddrs, &iaddr, sizeof(struct in_addr));
                    344:                strlcpy(poop->addrs[0], inet_ntoa(iaddr), sizeof(poop->addrs));
1.6       deraadt   345:                if (numeric)    /* if numeric-only, we're done */
                    346:                        return (poop);
                    347:                if (!o_verbose) /* likewise if we don't want */
                    348:                        return (poop);  /* the full DNS hair */
1.7       deraadt   349:                hostent = gethostbyaddr((char *) &iaddr, sizeof(struct in_addr), AF_INET);
1.1       deraadt   350: /* numeric or not, failure to look up a PTR is *not* considered fatal */
1.6       deraadt   351:                if (!hostent)
                    352:                        holler("%s: inverse host lookup failed: ", name);
                    353:                else {
1.7       deraadt   354:                        strlcpy(poop->name, hostent->h_name, MAXHOSTNAMELEN);
1.6       deraadt   355:                        hostent = gethostbyname(poop->name);
                    356:                        if ((!hostent) || (!hostent->h_addr_list[0]))
                    357:                                holler("Warning: forward host lookup failed for %s: ",
                    358:                                    poop->name);
                    359:                        else
                    360:                                (void) comparehosts(poop, hostent);
                    361:                }               /* if hostent */
                    362:        }                       /* INADDR_NONE Great Split */
1.1       deraadt   363:
1.7       deraadt   364: /* whatever-all went down previously, we should now have a host_info struct
1.1       deraadt   365:    with at least one IP address in it. */
1.6       deraadt   366:        h_errno = 0;
                    367:        return (poop);
1.7       deraadt   368: }
1.1       deraadt   369:
                    370: /* getportpoop :
                    371:    Same general idea as gethostpoop -- look up a port in /etc/services, fill
1.7       deraadt   372:    in global port_info, but return the actual port *number*.  Pass ONE of:
1.1       deraadt   373:        pstring to resolve stuff like "23" or "exec";
                    374:        pnum to reverse-resolve something that's already a number.
                    375:    If o_nflag is on, fill in what we can but skip the getservby??? stuff.
                    376:    Might as well have consistent behavior here, and it *is* faster. */
1.7       deraadt   377: u_short
1.6       deraadt   378: getportpoop(pstring, pnum)
                    379:        char   *pstring;
                    380:        unsigned int pnum;
                    381: {
                    382:        struct servent *servent;
                    383:        register int x;
                    384:        register int y;
1.7       deraadt   385:        char   *whichp = "tcp";
1.6       deraadt   386:        if (o_udpmode)
1.7       deraadt   387:                whichp = "udp";
1.6       deraadt   388:        portpoop->name[0] = '?';/* fast preload */
                    389:        portpoop->name[1] = '\0';
1.1       deraadt   390:
                    391: /* case 1: reverse-lookup of a number; placed first since this case is much
                    392:    more frequent if we're scanning */
1.6       deraadt   393:        if (pnum) {
                    394:                if (pstring)    /* one or the other, pleeze */
                    395:                        return (0);
                    396:                x = pnum;
                    397:                if (o_nflag)    /* go faster, skip getservbyblah */
                    398:                        goto gp_finish;
                    399:                y = htons(x);   /* gotta do this -- see Fig.1 below */
                    400:                servent = getservbyport(y, whichp);
                    401:                if (servent) {
                    402:                        y = ntohs(servent->s_port);
                    403:                        if (x != y)     /* "never happen" */
                    404:                                holler("Warning: port-bynum mismatch, %d != %d", x, y);
1.7       deraadt   405:                        strlcpy(portpoop->name, servent->s_name,
                    406:                            sizeof(portpoop->name));
                    407:                }
1.6       deraadt   408:                goto gp_finish;
                    409:        }                       /* if pnum */
                    410:        /* case 2: resolve a string, but we still give preference to numbers
                    411:         * instead of trying to resolve conflicts.  None of the entries in *my*
                    412:         * extensive /etc/services begins with a digit, so this should "always
                    413:         * work" unless you're at 3com and have some company-internal services
                    414:         * defined... */
                    415:        if (pstring) {
                    416:                if (pnum)       /* one or the other, pleeze */
                    417:                        return (0);
                    418:                x = atoi(pstring);
                    419:                if (x)
                    420:                        return (getportpoop(NULL, x));  /* recurse for
                    421:                                                         * numeric-string-arg */
                    422:                if (o_nflag)    /* can't use names! */
                    423:                        return (0);
                    424:                servent = getservbyname(pstring, whichp);
                    425:                if (servent) {
1.7       deraadt   426:                        strlcpy(portpoop->name, servent->s_name,
                    427:                            sizeof(portpoop->name));
1.6       deraadt   428:                        x = ntohs(servent->s_port);
                    429:                        goto gp_finish;
                    430:                }               /* if servent */
                    431:        }                       /* if pstring */
                    432:        return (0);             /* catches any problems so far */
1.1       deraadt   433:
                    434: /* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
                    435:    Despite this, we still have to treat it as a short when copying it around.
                    436:    Not only that, but we have to convert it *back* into net order for
                    437:    getservbyport to work.  Manpages generally aren't clear on all this, but
                    438:    there are plenty of examples in which it is just quietly done.  More BSD
                    439:    lossage... since everything getserv* ever deals with is local to our own
                    440:    host, why bother with all this network-order/host-order crap at all?!
                    441:    That should be saved for when we want to actually plug the port[s] into
                    442:    some real network calls -- and guess what, we have to *re*-convert at that
                    443:    point as well.  Fuckheads. */
                    444:
                    445: gp_finish:
                    446: /* Fall here whether or not we have a valid servent at this point, with
                    447:    x containing our [host-order and therefore useful, dammit] port number */
1.6       deraadt   448:        sprintf(portpoop->anum, "%d", x);       /* always load any numeric
                    449:                                                 * specs! */
1.7       deraadt   450:        portpoop->num = (x & 0xffff);   /* u_short, remember... */
1.6       deraadt   451:        return (portpoop->num);
1.7       deraadt   452: }
1.1       deraadt   453:
                    454: /* nextport :
                    455:    Come up with the next port to try, be it random or whatever.  "block" is
                    456:    a ptr to randports array, whose bytes [so far] carry these meanings:
                    457:        0       ignore
                    458:        1       to be tested
                    459:        2       tested [which is set as we find them here]
1.7       deraadt   460:    returns a u_short random port, or 0 if all the t-b-t ones are used up. */
                    461: u_short
1.6       deraadt   462: nextport(block)
                    463:        char   *block;
                    464: {
                    465:        register unsigned int x;
                    466:        register unsigned int y;
                    467:
                    468:        y = 70000;              /* high safety count for rnd-tries */
                    469:        while (y > 0) {
                    470:                x = (RAND() & 0xffff);
                    471:                if (block[x] == 1) {    /* try to find a not-done one... */
                    472:                        block[x] = 2;
                    473:                        break;
                    474:                }
                    475:                x = 0;          /* bummer. */
                    476:                y--;
                    477:        }                       /* while y */
                    478:        if (x)
                    479:                return (x);
                    480:
                    481:        y = 65535;              /* no random one, try linear downsearch */
                    482:        while (y > 0) {         /* if they're all used, we *must* be sure! */
                    483:                if (block[y] == 1) {
                    484:                        block[y] = 2;
                    485:                        break;
                    486:                }
                    487:                y--;
                    488:        }                       /* while y */
                    489:        if (y)
                    490:                return (y);     /* at least one left */
1.1       deraadt   491:
1.6       deraadt   492:        return (0);             /* no more left! */
1.7       deraadt   493: }
1.1       deraadt   494:
                    495: /* loadports :
                    496:    set "to be tested" indications in BLOCK, from LO to HI.  Almost too small
                    497:    to be a separate routine, but makes main() a little cleaner... */
1.6       deraadt   498: void
                    499: loadports(block, lo, hi)
                    500:        char   *block;
1.7       deraadt   501:        u_short  lo;
                    502:        u_short  hi;
1.6       deraadt   503: {
1.7       deraadt   504:        u_short  x;
1.6       deraadt   505:
                    506:        if (!block)
                    507:                bail("loadports: no block?!");
                    508:        if ((!lo) || (!hi))
                    509:                bail("loadports: bogus values %d, %d", lo, hi);
                    510:        x = hi;
                    511:        while (lo <= x) {
                    512:                block[x] = 1;
                    513:                x--;
                    514:        }
1.7       deraadt   515: }
                    516:
1.1       deraadt   517: #ifdef GAPING_SECURITY_HOLE
1.6       deraadt   518: char   *pr00gie = NULL;                /* global ptr to -e arg */
1.1       deraadt   519:
                    520: /* doexec :
                    521:    fiddle all the file descriptors around, and hand off to another prog.  Sort
                    522:    of like a one-off "poor man's inetd".  This is the only section of code
                    523:    that would be security-critical, which is why it's ifdefed out by default.
                    524:    Use at your own hairy risk; if you leave shells lying around behind open
                    525:    listening ports you deserve to lose!! */
1.6       deraadt   526: doexec(fd)
                    527:        int     fd;
1.1       deraadt   528: {
1.6       deraadt   529:        register char *p;
1.1       deraadt   530:
1.6       deraadt   531:        dup2(fd, 0);            /* the precise order of fiddlage */
                    532:        close(fd);              /* is apparently crucial; this is */
                    533:        dup2(0, 1);             /* swiped directly out of "inetd". */
                    534:        dup2(0, 2);
                    535:        p = strrchr(pr00gie, '/');      /* shorter argv[0] */
                    536:        if (p)
                    537:                p++;
                    538:        else
                    539:                p = pr00gie;
                    540:        Debug(("gonna exec %s as %s...", pr00gie, p))
                    541:            execl(pr00gie, p, NULL);
                    542:        bail("exec %s failed", pr00gie);        /* this gets sent out.  Hmm... */
1.7       deraadt   543: }
1.6       deraadt   544: #endif                         /* GAPING_SECURITY_HOLE */
1.1       deraadt   545:
                    546: /* doconnect :
                    547:    do all the socket stuff, and return an fd for one of
                    548:        an open outbound TCP connection
                    549:        a UDP stub-socket thingie
                    550:    with appropriate socket options set up if we wanted source-routing, or
                    551:        an unconnected TCP or UDP socket to listen on.
                    552:    Examines various global o_blah flags to figure out what-all to do. */
1.6       deraadt   553: int
                    554: doconnect(rad, rp, lad, lp)
1.7       deraadt   555:        struct in_addr     *rad;
                    556:        u_short  rp;
                    557:        struct in_addr     *lad;
                    558:        u_short  lp;
1.6       deraadt   559: {
                    560:        register int nnetfd;
                    561:        register int rr;
                    562:        int     x, y;
                    563:        errno = 0;
1.1       deraadt   564:
                    565: /* grab a socket; set opts */
                    566: newskt:
1.6       deraadt   567:        if (o_udpmode)
                    568:                nnetfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                    569:        else
                    570:                nnetfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                    571:        if (nnetfd < 0)
                    572:                bail("Can't get socket");
                    573:        if (nnetfd == 0)        /* if stdin was closed this might *be* 0, */
                    574:                goto newskt;    /* so grab another.  See text for why... */
                    575:        x = 1;
                    576:        rr = setsockopt(nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
                    577:        if (rr == -1)
                    578:                holler("nnetfd reuseaddr failed");      /* ??? */
                    579: #ifdef SO_REUSEPORT            /* doesnt exist everywhere... */
                    580:        rr = setsockopt(nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
                    581:        if (rr == -1)
                    582:                holler("nnetfd reuseport failed");      /* ??? */
1.1       deraadt   583: #endif
                    584: #if 0
                    585: /* If you want to screw with RCVBUF/SNDBUF, do it here.  Liudvikas Bukys at
                    586:    Rochester sent this example, which would involve YET MORE options and is
                    587:    just archived here in case you want to mess with it.  o_xxxbuf are global
                    588:    integers set in main() getopt loop, and check for rr == 0 afterward. */
1.6       deraadt   589:        rr = setsockopt(nnetfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
                    590:        rr = setsockopt(nnetfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
1.1       deraadt   591: #endif
1.6       deraadt   592:
                    593:        /* fill in all the right sockaddr crud */
                    594:        lclend->sin_family = AF_INET;
1.1       deraadt   595:
                    596: /* fill in all the right sockaddr crud */
1.6       deraadt   597:        lclend->sin_family = AF_INET;
                    598:        remend->sin_family = AF_INET;
1.1       deraadt   599:
                    600: /* if lad/lp, do appropriate binding */
1.6       deraadt   601:        if (lad)
1.7       deraadt   602:                memcpy(&lclend->sin_addr.s_addr, lad, sizeof(struct in_addr));
1.6       deraadt   603:        if (lp)
                    604:                lclend->sin_port = htons(lp);
                    605:        rr = 0;
                    606:        if (lad || lp) {
                    607:                x = (int) lp;
1.1       deraadt   608: /* try a few times for the local bind, a la ftp-data-port... */
1.6       deraadt   609:                for (y = 4; y > 0; y--) {
1.7       deraadt   610:                        rr = bind(nnetfd, (struct sockaddr *) lclend,
                    611:                            sizeof(struct sockaddr_in));
1.6       deraadt   612:                        if (rr == 0)
                    613:                                break;
                    614:                        if (errno != EADDRINUSE)
                    615:                                break;
                    616:                        else {
                    617:                                holler("retrying local %s:%d", inet_ntoa(lclend->sin_addr), lp);
                    618:                                sleep(2);
                    619:                                errno = 0;      /* clear from sleep */
                    620:                        }       /* if EADDRINUSE */
                    621:                }               /* for y counter */
                    622:        }                       /* if lad or lp */
                    623:        if (rr)
                    624:                bail("Can't grab %s:%d with bind",
                    625:                    inet_ntoa(lclend->sin_addr), lp);
1.1       deraadt   626:
1.6       deraadt   627:        if (o_listen)
                    628:                return (nnetfd);/* thanks, that's all for today */
1.1       deraadt   629:
1.7       deraadt   630:        memcpy(&remend->sin_addr.s_addr, rad, sizeof(struct in_addr));
1.6       deraadt   631:        remend->sin_port = htons(rp);
1.1       deraadt   632:
                    633: /* rough format of LSRR option and explanation of weirdness.
                    634: Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5.
                    635: IHL is multiples of 4, i.e. real len = ip_hl << 2.
                    636:        type 131        1       ; 0x83: copied, option class 0, number 3
                    637:        len             1       ; of *whole* option!
                    638:        pointer         1       ; nxt-hop-addr; 1-relative, not 0-relative
                    639:        addrlist...     var     ; 4 bytes per hop-addr
                    640:        pad-to-32       var     ; ones, i.e. "NOP"
                    641:
                    642: If we want to route A -> B via hops C and D, we must add C, D, *and* B to the
                    643: options list.  Why?  Because when we hand the kernel A -> B with list C, D, B
                    644: the "send shuffle" inside the kernel changes it into A -> C with list D, B and
                    645: the outbound packet gets sent to C.  If B wasn't also in the hops list, the
                    646: final destination would have been lost at this point.
                    647:
                    648: When C gets the packet, it changes it to A -> D with list C', B where C' is
                    649: the interface address that C used to forward the packet.  This "records" the
                    650: route hop from B's point of view, i.e. which address points "toward" B.  This
                    651: is to make B better able to return the packets.  The pointer gets bumped by 4,
                    652: so that D does the right thing instead of trying to forward back to C.
                    653:
                    654: When B finally gets the packet, it sees that the pointer is at the end of the
                    655: LSRR list and is thus "completed".  B will then try to use the packet instead
                    656: of forwarding it, i.e. deliver it up to some application.
                    657:
                    658: Note that by moving the pointer yourself, you could send the traffic directly
                    659: to B but have it return via your preconstructed source-route.  Playing with
                    660: this and watching "tcpdump -v" is the best way to understand what's going on.
                    661:
                    662: Only works for TCP in BSD-flavor kernels.  UDP is a loss; udp_input calls
                    663: stripoptions() early on, and the code to save the srcrt is notdef'ed.
                    664: Linux is also still a loss at 1.3.x it looks like; the lsrr code is { }...
                    665: */
                    666:
                    667: /* if any -g arguments were given, set up source-routing.  We hit this after
                    668:    the gates are all looked up and ready to rock, any -G pointer is set,
                    669:    and gatesidx is now the *number* of hops */
1.6       deraadt   670:        if (gatesidx) {         /* if we wanted any srcrt hops ... */
1.1       deraadt   671: /* don't even bother compiling if we can't do IP options here! */
                    672: #ifdef IP_OPTIONS
1.6       deraadt   673:                if (!optbuf) {  /* and don't already *have* a srcrt set */
                    674:                        char   *opp;    /* then do all this setup hair */
1.7       deraadt   675:                        optbuf = calloc(1, 48);
1.6       deraadt   676:                        opp = optbuf;
                    677:                        *opp++ = IPOPT_LSRR;    /* option */
                    678:                        *opp++ = (char)
1.7       deraadt   679:                            (((gatesidx + 1) * sizeof(struct in_addr)) + 3) & 0xff;     /* length */
1.6       deraadt   680:                        *opp++ = gatesptr;      /* pointer */
1.1       deraadt   681: /* opp now points at first hop addr -- insert the intermediate gateways */
1.6       deraadt   682:                        for (x = 0; x < gatesidx; x++) {
1.7       deraadt   683:                                memcpy(opp, gates[x]->iaddrs, sizeof(struct in_addr));
                    684:                                opp += sizeof(struct in_addr);
1.6       deraadt   685:                        }
1.1       deraadt   686: /* and tack the final destination on the end [needed!] */
1.7       deraadt   687:                        memcpy(opp, rad, sizeof(struct in_addr));
                    688:                        opp += sizeof(struct in_addr);
1.6       deraadt   689:                        *opp = IPOPT_NOP;       /* alignment filler */
                    690:                }               /* if empty optbuf */
                    691:                /* calculate length of whole option mess, which is (3 + [hops]
                    692:                 * + [final] + 1), and apply it [have to do this every time
                    693:                 * through, of course] */
1.7       deraadt   694:                x = ((gatesidx + 1) * sizeof(struct in_addr)) + 4;
1.6       deraadt   695:                rr = setsockopt(nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, x);
                    696:                if (rr == -1)
                    697:                        bail("srcrt setsockopt fuxored");
                    698: #else                          /* IP_OPTIONS */
                    699:                holler("Warning: source routing unavailable on this machine, ignoring");
                    700: #endif                         /* IP_OPTIONS */
                    701:        }                       /* if gatesidx */
                    702:        /* wrap connect inside a timer, and hit it */
                    703:        arm(1, o_wait);
                    704:        if (setjmp(jbuf) == 0) {
1.7       deraadt   705:                rr = connect(nnetfd, (struct sockaddr *) remend, sizeof(struct sockaddr));
1.6       deraadt   706:        } else {                /* setjmp: connect failed... */
                    707:                rr = -1;
                    708:                errno = ETIMEDOUT;      /* fake it */
                    709:        }
                    710:        arm(0, 0);
                    711:        if (rr == 0)
                    712:                return (nnetfd);
                    713:        close(nnetfd);          /* clean up junked socket FD!! */
                    714:        return (-1);
1.7       deraadt   715: }
1.1       deraadt   716:
                    717: /* dolisten :
                    718:    just like doconnect, and in fact calls a hunk of doconnect, but listens for
                    719:    incoming and returns an open connection *from* someplace.  If we were
                    720:    given host/port args, any connections from elsewhere are rejected.  This
                    721:    in conjunction with local-address binding should limit things nicely... */
1.6       deraadt   722: int
                    723: dolisten(rad, rp, lad, lp)
1.7       deraadt   724:        struct in_addr     *rad;
                    725:        u_short  rp;
                    726:        struct in_addr     *lad;
                    727:        u_short  lp;
1.6       deraadt   728: {
                    729:        register int nnetfd;
                    730:        register int rr;
1.7       deraadt   731:        struct host_info   *whozis = NULL;
1.6       deraadt   732:        int     x;
                    733:        char   *cp;
1.7       deraadt   734:        u_short  z;
1.6       deraadt   735:        errno = 0;
1.1       deraadt   736:
                    737: /* Pass everything off to doconnect, who in o_listen mode just gets a socket */
1.6       deraadt   738:        nnetfd = doconnect(rad, rp, lad, lp);
                    739:        if (nnetfd <= 0)
                    740:                return (-1);
                    741:        if (o_udpmode) {        /* apparently UDP can listen ON */
                    742:                if (!lp)        /* "port 0",  but that's not useful */
                    743:                        bail("UDP listen needs -p arg");
                    744:        } else {
                    745:                rr = listen(nnetfd, 1); /* gotta listen() before we can get */
                    746:                if (rr < 0)     /* our local random port.  sheesh. */
                    747:                        bail("local listen fuxored");
                    748:        }
1.1       deraadt   749:
                    750: /* Various things that follow temporarily trash bigbuf_net, which might contain
                    751:    a copy of any recvfrom()ed packet, but we'll read() another copy later. */
                    752:
                    753: /* I can't believe I have to do all this to get my own goddamn bound address
                    754:    and port number.  It should just get filled in during bind() or something.
                    755:    All this is only useful if we didn't say -p for listening, since if we
1.7       deraadt   756:    struct sockaddr_ind -p we *know* what port we're listening on.  At any rate we won't bother
1.1       deraadt   757:    with it all unless we wanted to see it, although listening quietly on a
                    758:    random unknown port is probably not very useful without "netstat". */
1.6       deraadt   759:        if (o_verbose) {
1.7       deraadt   760:                x = sizeof(struct sockaddr);    /* how 'bout getsockNUM instead, pinheads?! */
                    761:                rr = getsockname(nnetfd, (struct sockaddr *) lclend, &x);
1.6       deraadt   762:                if (rr < 0)
                    763:                        holler("local getsockname failed");
                    764:                strcpy(bigbuf_net, "listening on [");   /* buffer reuse... */
                    765:                if (lclend->sin_addr.s_addr)
                    766:                        strcat(bigbuf_net, inet_ntoa(lclend->sin_addr));
                    767:                else
                    768:                        strcat(bigbuf_net, "any");
                    769:                strcat(bigbuf_net, "] %d ...");
                    770:                z = ntohs(lclend->sin_port);
                    771:                holler(bigbuf_net, z);
                    772:        }                       /* verbose -- whew!! */
                    773:        /* UDP is a speeeeecial case -- we have to do I/O *and* get the
                    774:         * calling party's particulars all at once, listen() and accept()
                    775:         * don't apply. At least in the BSD universe, however, recvfrom/PEEK
                    776:         * is enough to tell us something came in, and we can set things up so
                    777:         * straight read/write actually does work after all.  Yow.  YMMV on
                    778:         * strange platforms!  */
                    779:        if (o_udpmode) {
1.7       deraadt   780:                x = sizeof(struct sockaddr);    /* retval for recvfrom */
1.6       deraadt   781:                arm(2, o_wait); /* might as well timeout this, too */
                    782:                if (setjmp(jbuf) == 0) {        /* do timeout for initial
                    783:                                                 * connect */
                    784:                        rr = recvfrom   /* and here we block... */
1.7       deraadt   785:                            (nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (struct sockaddr *) remend, &x);
1.6       deraadt   786:                        Debug(("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))
                    787:                } else
                    788:                        goto dol_tmo;   /* timeout */
                    789:                arm(0, 0);
1.1       deraadt   790: /* I'm not completely clear on how this works -- BSD seems to make UDP
                    791:    just magically work in a connect()ed context, but we'll undoubtedly run
                    792:    into systems this deal doesn't work on.  For now, we apparently have to
                    793:    issue a connect() on our just-tickled socket so we can write() back.
                    794:    Again, why the fuck doesn't it just get filled in and taken care of?!
                    795:    This hack is anything but optimal.  Basically, if you want your listener
                    796:    to also be able to send data back, you need this connect() line, which
                    797:    also has the side effect that now anything from a different source or even a
                    798:    different port on the other end won't show up and will cause ICMP errors.
                    799:    I guess that's what they meant by "connect".
                    800:    Let's try to remember what the "U" is *really* for, eh? */
1.7       deraadt   801:                rr = connect(nnetfd, (struct sockaddr *) remend, sizeof(struct sockaddr));
1.6       deraadt   802:                goto whoisit;
                    803:        }                       /* o_udpmode */
                    804:        /* fall here for TCP */
1.7       deraadt   805:        x = sizeof(struct sockaddr);            /* retval for accept */
1.6       deraadt   806:        arm(2, o_wait);         /* wrap this in a timer, too; 0 = forever */
                    807:        if (setjmp(jbuf) == 0) {
1.7       deraadt   808:                rr = accept(nnetfd, (struct sockaddr *) remend, &x);
1.6       deraadt   809:        } else
                    810:                goto dol_tmo;   /* timeout */
                    811:        arm(0, 0);
                    812:        close(nnetfd);          /* dump the old socket */
                    813:        nnetfd = rr;            /* here's our new one */
1.1       deraadt   814:
                    815: whoisit:
1.6       deraadt   816:        if (rr < 0)
                    817:                goto dol_err;   /* bail out if any errors so far */
1.1       deraadt   818:
                    819: /* If we can, look for any IP options.  Useful for testing the receiving end of
                    820:    such things, and is a good exercise in dealing with it.  We do this before
                    821:    the connect message, to ensure that the connect msg is uniformly the LAST
                    822:    thing to emerge after all the intervening crud.  Doesn't work for UDP on
                    823:    any machines I've tested, but feel free to surprise me. */
                    824: #ifdef IP_OPTIONS
1.6       deraadt   825:        if (!o_verbose)         /* if we wont see it, we dont care */
                    826:                goto dol_noop;
1.7       deraadt   827:        optbuf = calloc(1, 40);
1.6       deraadt   828:        x = 40;
                    829:        rr = getsockopt(nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
                    830:        if (rr < 0)
                    831:                holler("getsockopt failed");
                    832:        Debug(("ipoptions ret len %d", x))
                    833:            if (x) {            /* we've got options, lessee em... */
                    834:                unsigned char *q = (unsigned char *) optbuf;
                    835:                char   *p = bigbuf_net; /* local variables, yuk! */
                    836:                char   *pp = &bigbuf_net[128];  /* get random space farther
                    837:                                                 * out... */
                    838:                memset(bigbuf_net, 0, 256);     /* clear it all first */
                    839:                while (x > 0) {
                    840:                        sprintf(pp, "%2.2x ", *q);      /* clumsy, but works:
                    841:                                                         * turn into hex */
                    842:                        strcat(p, pp);  /* and build the final string */
                    843:                        q++;
                    844:                        p++;
                    845:                        x--;
                    846:                }
                    847:                holler("IP options: %s", bigbuf_net);
                    848:        }                       /* if x, i.e. any options */
1.1       deraadt   849: dol_noop:
1.6       deraadt   850: #endif                         /* IP_OPTIONS */
1.1       deraadt   851:
                    852: /* find out what address the connection was *to* on our end, in case we're
                    853:    doing a listen-on-any on a multihomed machine.  This allows one to
                    854:    offer different services via different alias addresses, such as the
                    855:    "virtual web site" hack. */
1.6       deraadt   856:        memset(bigbuf_net, 0, 64);
                    857:        cp = &bigbuf_net[32];
1.7       deraadt   858:        x = sizeof(struct sockaddr);
                    859:        rr = getsockname(nnetfd, (struct sockaddr *) lclend, &x);
1.6       deraadt   860:        if (rr < 0)
                    861:                holler("post-rcv getsockname failed");
                    862:        strcpy(cp, inet_ntoa(lclend->sin_addr));
1.1       deraadt   863:
                    864: /* now check out who it is.  We don't care about mismatched DNS names here,
                    865:    but any ADDR and PORT we specified had better fucking well match the caller.
                    866:    Converting from addr to inet_ntoa and back again is a bit of a kludge, but
                    867:    gethostpoop wants a string and there's much gnarlier code out there already,
                    868:    so I don't feel bad.
                    869:    The *real* question is why BFD sockets wasn't designed to allow listens for
                    870:    connections *from* specific hosts/ports, instead of requiring the caller to
                    871:    accept the connection and then reject undesireable ones by closing.  In
                    872:    other words, we need a TCP MSG_PEEK. */
1.6       deraadt   873:        z = ntohs(remend->sin_port);
                    874:        strcpy(bigbuf_net, inet_ntoa(remend->sin_addr));
                    875:        whozis = gethostpoop(bigbuf_net, o_nflag);
                    876:        errno = 0;
                    877:        x = 0;                  /* use as a flag... */
                    878:        if (rad)                /* xxx: fix to go down the *list* if we have
                    879:                                 * one? */
1.7       deraadt   880:                if (memcmp(rad, whozis->iaddrs, sizeof(struct sockaddr)))
1.6       deraadt   881:                        x = 1;
                    882:        if (rp)
                    883:                if (z != rp)
                    884:                        x = 1;
                    885:        if (x)                  /* guilty! */
                    886:                bail("invalid connection to [%s] from %s [%s] %d",
                    887:                    cp, whozis->name, whozis->addrs[0], z);
                    888:        holler("connect to [%s] from %s [%s] %d",       /* oh, you're okay.. */
                    889:            cp, whozis->name, whozis->addrs[0], z);
                    890:        return (nnetfd);        /* open! */
1.1       deraadt   891:
                    892: dol_tmo:
1.6       deraadt   893:        errno = ETIMEDOUT;      /* fake it */
1.1       deraadt   894: dol_err:
1.6       deraadt   895:        close(nnetfd);
                    896:        return (-1);
1.7       deraadt   897: }
1.1       deraadt   898:
                    899: /* udptest :
                    900:    fire a couple of packets at a UDP target port, just to see if it's really
                    901:    there.  On BSD kernels, ICMP host/port-unreachable errors get delivered to
                    902:    our socket as ECONNREFUSED write errors.  On SV kernels, we lose; we'll have
                    903:    to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
                    904:    backend.  Guess where one could swipe the appropriate code from...
                    905:
                    906:    Use the time delay between writes if given, otherwise use the "tcp ping"
                    907:    trick for getting the RTT.  [I got that idea from pluvius, and warped it.]
                    908:    Return either the original fd, or clean up and return -1. */
1.6       deraadt   909: udptest(fd, where)
                    910:        int     fd;
1.7       deraadt   911:        struct in_addr     *where;
1.6       deraadt   912: {
                    913:        register int rr;
                    914:
                    915:        rr = write(fd, bigbuf_in, 1);
                    916:        if (rr != 1)
                    917:                holler("udptest first write failed?! errno %d", errno);
                    918:        if (o_wait)
                    919:                sleep(o_wait);
                    920:        else {
1.1       deraadt   921: /* use the tcp-ping trick: try connecting to a normally refused port, which
                    922:    causes us to block for the time that SYN gets there and RST gets back.
                    923:    Not completely reliable, but it *does* mostly work. */
1.6       deraadt   924:                o_udpmode = 0;  /* so doconnect does TCP this time */
1.1       deraadt   925: /* Set a temporary connect timeout, so packet filtration doesnt cause
                    926:    us to hang forever, and hit it */
1.6       deraadt   927:                o_wait = 5;     /* enough that we'll notice?? */
                    928:                rr = doconnect(where, SLEAZE_PORT, 0, 0);
                    929:                if (rr > 0)
                    930:                        close(rr);      /* in case it *did* open */
                    931:                o_wait = 0;     /* reset it */
                    932:                o_udpmode++;    /* we *are* still doing UDP, right? */
                    933:        }                       /* if o_wait */
                    934:        errno = 0;              /* clear from sleep */
                    935:        rr = write(fd, bigbuf_in, 1);
                    936:        if (rr == 1)            /* if write error, no UDP listener */
                    937:                return (fd);
                    938:        close(fd);              /* use it or lose it! */
                    939:        return (-1);
1.7       deraadt   940: }
                    941:
1.1       deraadt   942: /* oprint :
                    943:    Hexdump bytes shoveled either way to a running logfile, in the format:
                    944: D offset       -  - - - --- 16 bytes --- - - -  -     # .... ascii .....
                    945:    where "which" sets the direction indicator, D:
                    946:        0 -- sent to network, or ">"
                    947:        1 -- rcvd and printed to stdout, or "<"
                    948:    and "buf" and "n" are data-block and length.  If the current block generates
                    949:    a partial line, so be it; we *want* that lockstep indication of who sent
                    950:    what when.  Adapted from dgaudet's original example -- but must be ripping
                    951:    *fast*, since we don't want to be too disk-bound... */
1.6       deraadt   952: void
                    953: oprint(which, buf, n)
                    954:        int     which;
                    955:        char   *buf;
                    956:        int     n;
                    957: {
                    958:        int     bc;             /* in buffer count */
                    959:        int     obc;            /* current "global" offset */
                    960:        int     soc;            /* stage write count */
                    961:        register unsigned char *p;      /* main buf ptr; m.b. unsigned here */
                    962:        register unsigned char *op;     /* out hexdump ptr */
                    963:        register unsigned char *a;      /* out asc-dump ptr */
                    964:        register int x;
                    965:        register unsigned int y;
                    966:
                    967:        if (!ofd)
                    968:                bail("oprint called with no open fd?!");
                    969:        if (n == 0)
                    970:                return;
                    971:
                    972:        op = stage;
                    973:        if (which) {
                    974:                *op = '<';
                    975:                obc = wrote_out;/* use the globals! */
                    976:        } else {
                    977:                *op = '>';
                    978:                obc = wrote_net;
                    979:        }
                    980:        op++;                   /* preload "direction" */
                    981:        *op = ' ';
                    982:        p = (unsigned char *) buf;
                    983:        bc = n;
                    984:        stage[59] = '#';        /* preload separator */
                    985:        stage[60] = ' ';
                    986:
                    987:        while (bc) {            /* for chunk-o-data ... */
                    988:                x = 16;
                    989:                soc = 78;       /* len of whole formatted line */
                    990:                if (bc < x) {
                    991:                        soc = soc - 16 + bc;    /* fiddle for however much is
                    992:                                                 * left */
                    993:                        x = (bc * 3) + 11;      /* 2 digits + space per, after
                    994:                                                 * D & offset */
                    995:                        op = &stage[x];
                    996:                        x = 16 - bc;
                    997:                        while (x) {
                    998:                                *op++ = ' ';    /* preload filler spaces */
                    999:                                *op++ = ' ';
                   1000:                                *op++ = ' ';
                   1001:                                x--;
                   1002:                        }
                   1003:                        x = bc; /* re-fix current linecount */
                   1004:                }               /* if bc < x */
                   1005:                bc -= x;        /* fix wrt current line size */
                   1006:                sprintf(&stage[2], "%8.8x ", obc);      /* xxx: still slow? */
                   1007:                obc += x;       /* fix current offset */
                   1008:                op = &stage[11];/* where hex starts */
                   1009:                a = &stage[61]; /* where ascii starts */
                   1010:
                   1011:                while (x) {     /* for line of dump, however long ... */
                   1012:                        y = (int) (*p >> 4);    /* hi half */
                   1013:                        *op = hexnibs[y];
                   1014:                        op++;
                   1015:                        y = (int) (*p & 0x0f);  /* lo half */
                   1016:                        *op = hexnibs[y];
                   1017:                        op++;
                   1018:                        *op = ' ';
                   1019:                        op++;
                   1020:                        if ((*p > 31) && (*p < 127))
                   1021:                                *a = *p;        /* printing */
                   1022:                        else
                   1023:                                *a = '.';       /* nonprinting, loose def */
                   1024:                        a++;
                   1025:                        p++;
                   1026:                        x--;
                   1027:                }               /* while x */
                   1028:                *a = '\n';      /* finish the line */
                   1029:                x = write(ofd, stage, soc);
                   1030:                if (x < 0)
                   1031:                        bail("ofd write err");
                   1032:        }                       /* while bc */
1.7       deraadt  1033: }
                   1034:
1.1       deraadt  1035: #ifdef TELNET
1.7       deraadt  1036: u_short  o_tn = 0;             /* global -t option */
1.1       deraadt  1037:
                   1038: /* atelnet :
                   1039:    Answer anything that looks like telnet negotiation with don't/won't.
                   1040:    This doesn't modify any data buffers, update the global output count,
                   1041:    or show up in a hexdump -- it just shits into the outgoing stream.
                   1042:    Idea and codebase from Mudge@l0pht.com. */
1.6       deraadt  1043: void
                   1044: atelnet(buf, size)
                   1045:        unsigned char *buf;     /* has to be unsigned here! */
                   1046:        unsigned int size;
                   1047: {
                   1048:        static unsigned char obuf[4];   /* tiny thing to build responses into */
                   1049:        register int x;
                   1050:        register unsigned char y;
                   1051:        register unsigned char *p;
                   1052:
                   1053:        y = 0;
                   1054:        p = buf;
                   1055:        x = size;
                   1056:        while (x > 0) {
                   1057:                if (*p != 255)  /* IAC? */
                   1058:                        goto notiac;
                   1059:                obuf[0] = 255;
                   1060:                p++;
                   1061:                x--;
                   1062:                if ((*p == 251) || (*p == 252)) /* WILL or WONT */
                   1063:                        y = 254;/* -> DONT */
                   1064:                if ((*p == 253) || (*p == 254)) /* DO or DONT */
                   1065:                        y = 252;/* -> WONT */
                   1066:                if (y) {
                   1067:                        obuf[1] = y;
                   1068:                        p++;
                   1069:                        x--;
                   1070:                        obuf[2] = *p;   /* copy actual option byte */
                   1071:                        (void) write(netfd, obuf, 3);
1.1       deraadt  1072: /* if one wanted to bump wrote_net or do a hexdump line, here's the place */
1.6       deraadt  1073:                        y = 0;
                   1074:                }               /* if y */
1.1       deraadt  1075: notiac:
1.6       deraadt  1076:                p++;
                   1077:                x--;
                   1078:        }                       /* while x */
1.7       deraadt  1079: }
                   1080:
1.6       deraadt  1081: #endif                         /* TELNET */
1.1       deraadt  1082:
                   1083: /* readwrite :
                   1084:    handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
                   1085:    In this instance, return what might become our exit status. */
1.6       deraadt  1086: int
                   1087: readwrite(fd)
                   1088:        int     fd;
                   1089: {
                   1090:        register int rr;
                   1091:        register char *zp;      /* stdin buf ptr */
                   1092:        register char *np;      /* net-in buf ptr */
                   1093:        unsigned int rzleft;
                   1094:        unsigned int rnleft;
1.7       deraadt  1095:        u_short  netretry;      /* net-read retry counter */
                   1096:        u_short  wretry;                /* net-write sanity counter */
                   1097:        u_short  wfirst;                /* one-shot flag to skip first net read */
1.1       deraadt  1098:
                   1099: /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
1.7       deraadt  1100:    either find it or do your own bit-bashing: *fds1 |= (1 << fd), etc... */
1.6       deraadt  1101:        if (fd > FD_SETSIZE) {
                   1102:                holler("Preposterous fd value %d", fd);
                   1103:                return (1);
                   1104:        }
1.7       deraadt  1105:        FD_SET(fd, &fds1);      /* global: the net is open */
1.6       deraadt  1106:        netretry = 2;
                   1107:        wfirst = 0;
                   1108:        rzleft = rnleft = 0;
                   1109:        if (insaved) {
                   1110:                rzleft = insaved;       /* preload multi-mode fakeouts */
                   1111:                zp = bigbuf_in;
                   1112:                wfirst = 1;
                   1113:                if (Single)     /* if not scanning, this is a one-off first */
                   1114:                        insaved = 0;    /* buffer left over from argv
                   1115:                                         * construction, */
                   1116:                else {
1.7       deraadt  1117:                        FD_CLR(0, &fds1);       /* OR we've already got our
1.6       deraadt  1118:                                                 * repeat chunk, */
                   1119:                        close(0);       /* so we won't need any more stdin */
                   1120:                }               /* Single */
                   1121:        }                       /* insaved */
                   1122:        if (o_interval)
                   1123:                sleep(o_interval);      /* pause *before* sending stuff, too */
                   1124:        errno = 0;              /* clear from sleep, close, whatever */
1.1       deraadt  1125:
                   1126: /* and now the big ol' select shoveling loop ... */
1.7       deraadt  1127:        while (FD_ISSET(fd, &fds1)) {   /* i.e. till the *net* closes! */
1.9       art      1128:                struct timeval *tv;
                   1129:
1.6       deraadt  1130:                wretry = 8200;  /* more than we'll ever hafta write */
                   1131:                if (wfirst) {   /* any saved stdin buffer? */
                   1132:                        wfirst = 0;     /* clear flag for the duration */
                   1133:                        goto shovel;    /* and go handle it first */
                   1134:                }
1.7       deraadt  1135:                fds2 = fds1;
1.9       art      1136:                if (timer1.tv_sec > 0 || timer1.tv_usec > 0) {
                   1137:                        memcpy(&timer2, &timer1, sizeof(struct timeval));
                   1138:                        tv = &timer2;
                   1139:                } else
                   1140:                        tv = NULL;
                   1141:                rr = select(getdtablesize(), &fds2, 0, 0, tv);
1.6       deraadt  1142:                if (rr < 0) {
                   1143:                        if (errno != EINTR) {   /* might have gotten ^Zed, etc
                   1144:                                                 * ? */
                   1145:                                holler("select fuxored");
                   1146:                                close(fd);
                   1147:                                return (1);
                   1148:                        }
                   1149:                }               /* select fuckup */
                   1150:                /* if we have a timeout AND stdin is closed AND we haven't
                   1151:                 * heard anything from the net during that time, assume it's
                   1152:                 * dead and close it too. */
                   1153:                if (rr == 0) {
1.7       deraadt  1154:                        if (!FD_ISSET(0, &fds1))
1.6       deraadt  1155:                                netretry--;     /* we actually try a coupla
                   1156:                                                 * times. */
                   1157:                        if (!netretry) {
                   1158:                                if (o_verbose > 1)      /* normally we don't
                   1159:                                                         * care */
                   1160:                                        holler("net timeout");
                   1161:                                close(fd);
                   1162:                                return (0);     /* not an error! */
                   1163:                        }
                   1164:                }               /* select timeout */
                   1165:                /* xxx: should we check the exception fds too?  The read fds
                   1166:                 * seem to give us the right info, and none of the examples I
                   1167:                 * found bothered. */
                   1168:                /* Ding!!  Something arrived, go check all the incoming
                   1169:                 * hoppers, net first */
1.7       deraadt  1170:                if (FD_ISSET(fd, &fds2)) {      /* net: ding! */
1.6       deraadt  1171:                        rr = read(fd, bigbuf_net, BIGSIZ);
                   1172:                        if (rr <= 0) {
1.7       deraadt  1173:                                FD_CLR(fd, &fds1);      /* net closed, we'll
1.6       deraadt  1174:                                                         * finish up... */
                   1175:                                rzleft = 0;     /* can't write anymore: broken
                   1176:                                                 * pipe */
                   1177:                        } else {
                   1178:                                rnleft = rr;
                   1179:                                np = bigbuf_net;
1.1       deraadt  1180: #ifdef TELNET
1.6       deraadt  1181:                                if (o_tn)
                   1182:                                        atelnet(np, rr);        /* fake out telnet stuff */
                   1183: #endif                         /* TELNET */
                   1184:                        }       /* if rr */
                   1185:                        Debug(("got %d from the net, errno %d", rr, errno))
                   1186:                }               /* net:ding */
                   1187:                /* if we're in "slowly" mode there's probably still stuff in
                   1188:                 * the stdin buffer, so don't read unless we really need MORE
                   1189:                 * INPUT!  MORE INPUT! */
                   1190:                if (rzleft)
                   1191:                        goto shovel;
1.1       deraadt  1192:
                   1193: /* okay, suck more stdin */
1.7       deraadt  1194:                if (FD_ISSET(0, &fds2)) {       /* stdin: ding! */
1.6       deraadt  1195:                        rr = read(0, bigbuf_in, BIGSIZ);
1.1       deraadt  1196: /* Considered making reads here smaller for UDP mode, but 8192-byte
                   1197:    mobygrams are kinda fun and exercise the reassembler. */
1.6       deraadt  1198:                        if (rr <= 0) {  /* at end, or fukt, or ... */
1.7       deraadt  1199:                                FD_CLR(0, &fds1);       /* disable and close
1.6       deraadt  1200:                                                         * stdin */
                   1201:                                close(0);
                   1202:                        } else {
                   1203:                                rzleft = rr;
                   1204:                                zp = bigbuf_in;
1.1       deraadt  1205: /* special case for multi-mode -- we'll want to send this one buffer to every
                   1206:    open TCP port or every UDP attempt, so save its size and clean up stdin */
1.6       deraadt  1207:                                if (!Single) {  /* we might be scanning... */
                   1208:                                        insaved = rr;   /* save len */
1.7       deraadt  1209:                                        FD_CLR(0, &fds1);       /* disable further junk
1.6       deraadt  1210:                                                                 * from stdin */
                   1211:                                        close(0);       /* really, I mean it */
                   1212:                                }       /* Single */
                   1213:                        }       /* if rr/read */
                   1214:                }               /* stdin:ding */
1.1       deraadt  1215: shovel:
                   1216: /* now that we've dingdonged all our thingdings, send off the results.
                   1217:    Geez, why does this look an awful lot like the big loop in "rsh"? ...
                   1218:    not sure if the order of this matters, but write net -> stdout first. */
                   1219:
                   1220: /* sanity check.  Works because they're both unsigned... */
1.6       deraadt  1221:                if ((rzleft > 8200) || (rnleft > 8200)) {
                   1222:                        holler("Bogus buffers: %d, %d", rzleft, rnleft);
                   1223:                        rzleft = rnleft = 0;
                   1224:                }
1.1       deraadt  1225: /* net write retries sometimes happen on UDP connections */
1.6       deraadt  1226:                if (!wretry) {  /* is something hung? */
                   1227:                        holler("too many output retries");
                   1228:                        return (1);
                   1229:                }
                   1230:                if (rnleft) {
                   1231:                        rr = write(1, np, rnleft);
                   1232:                        if (rr > 0) {
                   1233:                                if (o_wfile)
                   1234:                                        oprint(1, np, rr);      /* log the stdout */
                   1235:                                np += rr;       /* fix up ptrs and whatnot */
                   1236:                                rnleft -= rr;   /* will get sanity-checked
                   1237:                                                 * above */
                   1238:                                wrote_out += rr;        /* global count */
                   1239:                        }
                   1240:                        Debug(("wrote %d to stdout, errno %d", rr, errno))
                   1241:                }               /* rnleft */
                   1242:                if (rzleft) {
                   1243:                        if (o_interval) /* in "slowly" mode ?? */
                   1244:                                rr = findline(zp, rzleft);
                   1245:                        else
                   1246:                                rr = rzleft;
                   1247:                        rr = write(fd, zp, rr); /* one line, or the whole
                   1248:                                                 * buffer */
                   1249:                        if (rr > 0) {
                   1250:                                if (o_wfile)
                   1251:                                        oprint(0, zp, rr);      /* log what got sent */
                   1252:                                zp += rr;
                   1253:                                rzleft -= rr;
                   1254:                                wrote_net += rr;        /* global count */
                   1255:                        }
                   1256:                        Debug(("wrote %d to net, errno %d", rr, errno))
                   1257:                }               /* rzleft */
                   1258:                if (o_interval) {       /* cycle between slow lines, or ... */
                   1259:                        sleep(o_interval);
                   1260:                        errno = 0;      /* clear from sleep */
                   1261:                        continue;       /* ...with hairy select loop... */
                   1262:                }
                   1263:                if ((rzleft) || (rnleft)) {     /* shovel that shit till they
                   1264:                                                 * ain't */
                   1265:                        wretry--;       /* none left, and get another load */
                   1266:                        goto shovel;
                   1267:                }
1.7       deraadt  1268:        }                       /* while fds1:netfd is open */
1.1       deraadt  1269:
                   1270: /* XXX: maybe want a more graceful shutdown() here, or screw around with
                   1271:    linger times??  I suspect that I don't need to since I'm always doing
                   1272:    blocking reads and writes and my own manual "last ditch" efforts to read
                   1273:    the net again after a timeout.  I haven't seen any screwups yet, but it's
                   1274:    not like my test network is particularly busy... */
1.6       deraadt  1275:        close(fd);
                   1276:        return (0);
1.7       deraadt  1277: }
1.1       deraadt  1278:
                   1279: /* main :
                   1280:    now we pull it all together... */
1.6       deraadt  1281: main(argc, argv)
                   1282:        int     argc;
                   1283:        char  **argv;
1.1       deraadt  1284: {
                   1285: #ifndef HAVE_GETOPT
1.6       deraadt  1286:        extern char *optarg;
                   1287:        extern int optind, optopt;
1.1       deraadt  1288: #endif
1.6       deraadt  1289:        register int x;
                   1290:        register char *cp;
1.7       deraadt  1291:        struct host_info   *gp;
                   1292:        struct host_info   *whereto = NULL;
                   1293:        struct host_info   *wherefrom = NULL;
                   1294:        struct in_addr     *ouraddr = NULL;
                   1295:        struct in_addr     *themaddr = NULL;
                   1296:        u_short  o_lport = 0;
                   1297:        u_short  ourport = 0;
                   1298:        u_short  loport = 0;    /* for scanning stuff */
                   1299:        u_short  hiport = 0;
                   1300:        u_short  curport = 0;
1.6       deraadt  1301:        char   *randports = NULL;
1.1       deraadt  1302:
                   1303: #ifdef HAVE_BIND
                   1304: /* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */
1.6       deraadt  1305:        res_init();
1.1       deraadt  1306: #endif
                   1307: /* I was in this barbershop quartet in Skokie IL ... */
                   1308: /* round up the usual suspects, i.e. malloc up all the stuff we need */
1.7       deraadt  1309:        lclend = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr));
                   1310:        remend = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr));
                   1311:        bigbuf_in = calloc(1, BIGSIZ);
                   1312:        bigbuf_net = calloc(1, BIGSIZ);
                   1313:        portpoop = (struct port_info *) calloc(1, sizeof(struct port_info));
1.6       deraadt  1314:
                   1315:        errno = 0;
                   1316:        gatesptr = 4;
                   1317:        h_errno = 0;
1.1       deraadt  1318:
                   1319: /* catch a signal or two for cleanup */
1.6       deraadt  1320:        signal(SIGINT, catch);
                   1321:        signal(SIGQUIT, catch);
                   1322:        signal(SIGTERM, catch);
1.1       deraadt  1323: /* and suppress others... */
                   1324: #ifdef SIGURG
1.6       deraadt  1325:        signal(SIGURG, SIG_IGN);
1.1       deraadt  1326: #endif
                   1327: #ifdef SIGPIPE
1.6       deraadt  1328:        signal(SIGPIPE, SIG_IGN);       /* important! */
1.1       deraadt  1329: #endif
                   1330:
                   1331: /* if no args given at all, get 'em from stdin, construct an argv, and hand
                   1332:    anything left over to readwrite(). */
1.6       deraadt  1333:        if (argc == 1) {
                   1334:                cp = argv[0];
1.7       deraadt  1335:                argv = (char **) calloc(1, 128 * sizeof(char *));       /* XXX: 128? */
1.6       deraadt  1336:                argv[0] = cp;   /* leave old prog name intact */
1.7       deraadt  1337:                cp = calloc(1, BIGSIZ);
1.6       deraadt  1338:                argv[1] = cp;   /* head of new arg block */
                   1339:                fprintf(stderr, "Cmd line: ");
                   1340:                fflush(stderr); /* I dont care if it's unbuffered or not! */
1.10    ! deraadt  1341:                insaved = read(0, cp, BIGSIZ-1); /* we're gonna fake fgets()
1.6       deraadt  1342:                                                 * here */
1.10    ! deraadt  1343:                cp[BIGSIZ-1] = '\0';
1.6       deraadt  1344:                if (insaved <= 0)
                   1345:                        bail("wrong");
                   1346:                x = findline(cp, insaved);
                   1347:                if (x)
                   1348:                        insaved -= x;   /* remaining chunk size to be sent */
                   1349:                if (insaved)    /* which might be zero... */
                   1350:                        memcpy(bigbuf_in, &cp[x], insaved);
                   1351:                cp = strchr(argv[1], '\n');
                   1352:                if (cp)
                   1353:                        *cp = '\0';
                   1354:                cp = strchr(argv[1], '\r');     /* look for ^M too */
                   1355:                if (cp)
                   1356:                        *cp = '\0';
1.1       deraadt  1357:
                   1358: /* find and stash pointers to remaining new "args" */
1.6       deraadt  1359:                cp = argv[1];
                   1360:                cp++;           /* skip past first char */
                   1361:                x = 2;          /* we know argv 0 and 1 already */
                   1362:                for (; *cp != '\0'; cp++) {
                   1363:                        if (*cp == ' ') {
                   1364:                                *cp = '\0';     /* smash all spaces */
                   1365:                                continue;
                   1366:                        } else {
                   1367:                                if (*(cp - 1) == '\0') {
                   1368:                                        argv[x] = cp;
                   1369:                                        x++;
                   1370:                                }
                   1371:                        }       /* if space */
                   1372:                }               /* for cp */
                   1373:                argc = x;
                   1374:        }                       /* if no args given */
                   1375:        /* If your shitbox doesn't have getopt, step into the nineties
                   1376:         * already. */
                   1377:        /* optarg, optind = next-argv-component [i.e. flag arg]; optopt =
                   1378:         * last-char */
                   1379:        while ((x = getopt(argc, argv, "ae:g:G:hi:lno:p:rs:tuvw:z")) != -1) {
1.1       deraadt  1380: /* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
1.6       deraadt  1381:                switch (x) {
                   1382:                case 'a':
                   1383:                        bail("all-A-records NIY");
                   1384:                        o_alla++;
                   1385:                        break;
1.1       deraadt  1386: #ifdef GAPING_SECURITY_HOLE
1.6       deraadt  1387:                case 'e':       /* prog to exec */
                   1388:                        pr00gie = optarg;
                   1389:                        break;
1.1       deraadt  1390: #endif
1.6       deraadt  1391:                case 'G':       /* srcrt gateways pointer val */
                   1392:                        x = atoi(optarg);
                   1393:                        if ((x) && (x == (x & 0x1c)))   /* mask off bits of fukt
                   1394:                                                         * values */
                   1395:                                gatesptr = x;
                   1396:                        else
                   1397:                                bail("invalid hop pointer %d, must be multiple of 4 <= 28", x);
                   1398:                        break;
                   1399:                case 'g':       /* srcroute hop[s] */
                   1400:                        if (gatesidx > 8)
                   1401:                                bail("too many -g hops");
                   1402:                        if (gates == NULL)      /* eat this, Billy-boy */
1.7       deraadt  1403:                                gates = (struct host_info **) calloc(1, sizeof(struct host_info *) * 10);
1.6       deraadt  1404:                        gp = gethostpoop(optarg, o_nflag);
                   1405:                        if (gp)
                   1406:                                gates[gatesidx] = gp;
                   1407:                        gatesidx++;
                   1408:                        break;
                   1409:                case 'h':
                   1410:                        errno = 0;
                   1411:                        helpme();       /* exits by itself */
                   1412:                case 'i':       /* line-interval time */
                   1413:                        o_interval = atoi(optarg) & 0xffff;
                   1414:                        if (!o_interval)
                   1415:                                bail("invalid interval time %s", optarg);
                   1416:                        break;
                   1417:                case 'l':       /* listen mode */
                   1418:                        o_listen++;
                   1419:                        break;
                   1420:                case 'n':       /* numeric-only, no DNS lookups */
                   1421:                        o_nflag++;
                   1422:                        break;
                   1423:                case 'o':       /* hexdump log */
                   1424:                        stage = (unsigned char *) optarg;
                   1425:                        o_wfile++;
                   1426:                        break;
                   1427:                case 'p':       /* local source port */
                   1428:                        o_lport = getportpoop(optarg, 0);
                   1429:                        if (o_lport == 0)
                   1430:                                bail("invalid local port %s", optarg);
                   1431:                        break;
                   1432:                case 'r':       /* randomize various things */
                   1433:                        o_random++;
                   1434:                        break;
                   1435:                case 's':       /* local source address */
1.1       deraadt  1436: /* do a full lookup [since everything else goes through the same mill],
                   1437:    unless -n was previously specified.  In fact, careful placement of -n can
                   1438:    be useful, so we'll still pass o_nflag here instead of forcing numeric.  */
1.6       deraadt  1439:                        wherefrom = gethostpoop(optarg, o_nflag);
                   1440:                        ouraddr = &wherefrom->iaddrs[0];
                   1441:                        break;
1.1       deraadt  1442: #ifdef TELNET
1.6       deraadt  1443:                case 't':       /* do telnet fakeout */
                   1444:                        o_tn++;
                   1445:                        break;
                   1446: #endif                         /* TELNET */
                   1447:                case 'u':       /* use UDP */
                   1448:                        o_udpmode++;
                   1449:                        break;
                   1450:                case 'v':       /* verbose */
                   1451:                        o_verbose++;
                   1452:                        break;
                   1453:                case 'w':       /* wait time */
                   1454:                        o_wait = atoi(optarg);
                   1455:                        if (o_wait <= 0)
                   1456:                                bail("invalid wait-time %s", optarg);
1.7       deraadt  1457:                        timer1.tv_sec = o_wait;
                   1458:                        timer1.tv_usec = 0;
1.6       deraadt  1459:                        break;
                   1460:                case 'z':       /* little or no data xfer */
                   1461:                        o_zero++;
                   1462:                        break;
                   1463:                default:
                   1464:                        errno = 0;
                   1465:                        bail("nc -h for help");
                   1466:                }               /* switch x */
                   1467:        }                       /* while getopt */
1.1       deraadt  1468:
                   1469: /* other misc initialization */
1.7       deraadt  1470:        Debug(("fd_set size %d", sizeof(*fds1)))        /* how big *is* it? */
                   1471:            FD_SET(0, &fds1);   /* stdin *is* initially open */
1.6       deraadt  1472:        if (o_random) {
                   1473:                SRAND(time(0));
1.7       deraadt  1474:                randports = calloc(1, 65536);   /* big flag array for ports */
1.6       deraadt  1475:        }
1.1       deraadt  1476: #ifdef GAPING_SECURITY_HOLE
1.6       deraadt  1477:        if (pr00gie) {
                   1478:                close(0);       /* won't need stdin */
                   1479:                o_wfile = 0;    /* -o with -e is meaningless! */
                   1480:                ofd = 0;
                   1481:        }
                   1482: #endif                         /* G_S_H */
                   1483:        if (o_wfile) {
                   1484:                ofd = open(stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
                   1485:                if (ofd <= 0)   /* must be > extant 0/1/2 */
                   1486:                        bail("can't open %s", stage);
1.7       deraadt  1487:                stage = (unsigned char *) calloc(1, 100);
1.6       deraadt  1488:        }
1.1       deraadt  1489: /* optind is now index of first non -x arg */
1.6       deraadt  1490:        Debug(("after go: x now %c, optarg %x optind %d", x, optarg, optind))
1.1       deraadt  1491: /* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */
                   1492: /* gonna only use first addr of host-list, like our IQ was normal; if you wanna
                   1493:    get fancy with addresses, look up the list yourself and plug 'em in for now.
                   1494:    unless we finally implement -a, that is. */
1.6       deraadt  1495:            if (argv[optind])
                   1496:                whereto = gethostpoop(argv[optind], o_nflag);
                   1497:        if (whereto && whereto->iaddrs)
                   1498:                themaddr = &whereto->iaddrs[0];
                   1499:        if (themaddr)
                   1500:                optind++;       /* skip past valid host lookup */
                   1501:        errno = 0;
                   1502:        h_errno = 0;
1.1       deraadt  1503:
                   1504: /* Handle listen mode here, and exit afterward.  Only does one connect;
                   1505:    this is arguably the right thing to do.  A "persistent listen-and-fork"
                   1506:    mode a la inetd has been thought about, but not implemented.  A tiny
                   1507:    wrapper script can handle such things... */
1.6       deraadt  1508:        if (o_listen) {
                   1509:                curport = 0;    /* rem port *can* be zero here... */
                   1510:                if (argv[optind]) {     /* any rem-port-arg? */
                   1511:                        curport = getportpoop(argv[optind], 0);
                   1512:                        if (curport == 0)       /* if given, demand
                   1513:                                                 * correctness */
                   1514:                                bail("invalid port %s", argv[optind]);
                   1515:                }               /* if port-arg */
                   1516:                netfd = dolisten(themaddr, curport, ouraddr, o_lport);
1.1       deraadt  1517: /* dolisten does its own connect reporting, so we don't holler anything here */
1.6       deraadt  1518:                if (netfd > 0) {
1.1       deraadt  1519: #ifdef GAPING_SECURITY_HOLE
1.6       deraadt  1520:                        if (pr00gie)    /* -e given? */
                   1521:                                doexec(netfd);
                   1522: #endif                         /* GAPING_SECURITY_HOLE */
                   1523:                        x = readwrite(netfd);   /* it even works with UDP! */
                   1524:                        if (o_verbose > 1)      /* normally we don't care */
                   1525:                                holler(wrote_txt, wrote_net, wrote_out);
                   1526:                        exit(x);/* "pack out yer trash" */
                   1527:                } else          /* if no netfd */
                   1528:                        bail("no connection");
                   1529:        }                       /* o_listen */
                   1530:        /* fall thru to outbound connects.  Now we're more picky about args... */
                   1531:        if (!themaddr)
                   1532:                bail("no destination");
                   1533:        if (argv[optind] == NULL)
                   1534:                bail("no port[s] to connect to");
                   1535:        if (argv[optind + 1])   /* look ahead: any more port args given? */
                   1536:                Single = 0;     /* multi-mode, case A */
                   1537:        ourport = o_lport;      /* which can be 0 */
1.1       deraadt  1538:
                   1539: /* everything from here down is treated as as ports and/or ranges thereof, so
                   1540:    it's all enclosed in this big ol' argv-parsin' loop.  Any randomization is
                   1541:    done within each given *range*, but in separate chunks per each succeeding
                   1542:    argument, so we can control the pattern somewhat. */
1.6       deraadt  1543:        while (argv[optind]) {
                   1544:                hiport = loport = 0;
                   1545:                cp = strchr(argv[optind], '-'); /* nn-mm range? */
                   1546:                if (cp) {
                   1547:                        *cp = '\0';
                   1548:                        cp++;
                   1549:                        hiport = getportpoop(cp, 0);
                   1550:                        if (hiport == 0)
                   1551:                                bail("invalid port %s", cp);
                   1552:                }               /* if found a dash */
                   1553:                loport = getportpoop(argv[optind], 0);
                   1554:                if (loport == 0)
                   1555:                        bail("invalid port %s", argv[optind]);
                   1556:                if (hiport > loport) {  /* was it genuinely a range? */
                   1557:                        Single = 0;     /* multi-mode, case B */
                   1558:                        curport = hiport;       /* start high by default */
                   1559:                        if (o_random) { /* maybe populate the random array */
                   1560:                                loadports(randports, loport, hiport);
                   1561:                                curport = nextport(randports);
                   1562:                        }
                   1563:                } else          /* not a range, including args like "25-25" */
                   1564:                        curport = loport;
                   1565:                Debug(("Single %d, curport %d", Single, curport))
1.1       deraadt  1566: /* Now start connecting to these things.  curport is already preloaded. */
1.6       deraadt  1567:                    while (loport <= curport) {
                   1568:                        if ((!o_lport) && (o_random)) { /* -p overrides random
                   1569:                                                         * local-port */
                   1570:                                ourport = (RAND() & 0xffff);    /* random local-bind --
                   1571:                                                                 * well above */
                   1572:                                if (ourport < 8192)     /* resv and any likely
                   1573:                                                         * listeners??? */
                   1574:                                        ourport += 8192;        /* if it *still*
                   1575:                                                                 * conflicts, use -s. */
                   1576:                        }
                   1577:                        curport = getportpoop(NULL, curport);
                   1578:                        netfd = doconnect(themaddr, curport, ouraddr, ourport);
                   1579:                        Debug(("netfd %d from port %d to port %d", netfd, ourport, curport))
                   1580:                            if (netfd > 0)
                   1581:                                if (o_zero && o_udpmode)        /* if UDP scanning... */
                   1582:                                        netfd = udptest(netfd, themaddr);
                   1583:                        if (netfd > 0) {        /* Yow, are we OPEN YET?! */
                   1584:                                x = 0;  /* pre-exit status */
                   1585:                                holler("%s [%s] %d (%s) open",
                   1586:                                    whereto->name, whereto->addrs[0], curport, portpoop->name);
1.1       deraadt  1587: #ifdef GAPING_SECURITY_HOLE
1.6       deraadt  1588:                                if (pr00gie)    /* exec is valid for outbound,
                   1589:                                                 * too */
                   1590:                                        doexec(netfd);
                   1591: #endif                         /* GAPING_SECURITY_HOLE */
                   1592:                                if (!o_zero)
                   1593:                                        x = readwrite(netfd);   /* go shovel shit */
                   1594:                        } else {/* no netfd... */
                   1595:                                x = 1;  /* preload exit status for later */
1.1       deraadt  1596: /* if we're scanning at a "one -v" verbosity level, don't print refusals.
                   1597:    Give it another -v if you want to see everything. */
1.6       deraadt  1598:                                if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
                   1599:                                        holler("%s [%s] %d (%s)",
                   1600:                                            whereto->name, whereto->addrs[0], curport, portpoop->name);
                   1601:                        }       /* if netfd */
                   1602:                        close(netfd);   /* just in case we didn't already */
                   1603:                        if (o_interval)
                   1604:                                sleep(o_interval);      /* if -i, delay between
                   1605:                                                         * ports too */
                   1606:                        if (o_random)
                   1607:                                curport = nextport(randports);
                   1608:                        else
                   1609:                                curport--;      /* just decrement... */
                   1610:                }               /* while curport within current range */
                   1611:                optind++;
                   1612:        }                       /* while remaining port-args -- end of big
                   1613:                                 * argv-ports loop */
                   1614:
                   1615:        errno = 0;
                   1616:        if (o_verbose > 1)      /* normally we don't care */
                   1617:                holler(wrote_txt, wrote_net, wrote_out);
                   1618:        if (Single)
                   1619:                exit(x);        /* give us status on one connection */
                   1620:        exit(0);                /* otherwise, we're just done */
1.7       deraadt  1621: }
1.1       deraadt  1622:
                   1623: /* helpme :
                   1624:    the obvious */
                   1625: helpme()
                   1626: {
1.6       deraadt  1627:        o_verbose = 1;
                   1628:        holler("[v1.10]\n\
1.1       deraadt  1629: connect to somewhere:  nc [-options] hostname port[s] [ports] ... \n\
                   1630: listen for inbound:    nc -l -p port [-options] [hostname] [port]\n\
                   1631: options:");
                   1632: /* sigh, this necessarily gets messy.  And the trailing \ characters may be
                   1633:    interpreted oddly by some compilers, generating or not generating extra
                   1634:    newlines as they bloody please.  u-fix... */
                   1635: #ifdef GAPING_SECURITY_HOLE    /* needs to be separate holler() */
1.6       deraadt  1636:        holler("\
1.1       deraadt  1637:        -e prog                 program to exec after connect [dangerous!!]");
                   1638: #endif
1.6       deraadt  1639:        holler("\
1.1       deraadt  1640:        -g gateway              source-routing hop point[s], up to 8\n\
                   1641:        -G num                  source-routing pointer: 4, 8, 12, ...\n\
                   1642:        -h                      this cruft\n\
                   1643:        -i secs                 delay interval for lines sent, ports scanned\n\
                   1644:        -l                      listen mode, for inbound connects\n\
                   1645:        -n                      numeric-only IP addresses, no DNS\n\
                   1646:        -o file                 hex dump of traffic\n\
                   1647:        -p port                 local port number\n\
                   1648:        -r                      randomize local and remote ports\n\
                   1649:        -s addr                 local source address");
                   1650: #ifdef TELNET
1.6       deraadt  1651:        holler("\
1.1       deraadt  1652:        -t                      answer TELNET negotiation");
                   1653: #endif
1.6       deraadt  1654:        holler("\
1.1       deraadt  1655:        -u                      UDP mode\n\
                   1656:        -v                      verbose [use twice to be more verbose]\n\
                   1657:        -w secs                 timeout for connects and final net reads\n\
                   1658:        -z                      zero-I/O mode [used for scanning]");
1.6       deraadt  1659:        bail("port numbers can be individual or ranges: lo-hi [inclusive]");
1.7       deraadt  1660: }