[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.16

1.16    ! ericj       1: /* $OpenBSD: netcat.c,v 1.15 2000/09/26 05:19:37 ericj Exp $ */
1.11      ericj       2:
1.1       deraadt     3: /* Netcat 1.10 RELEASE 960320
1.7       deraadt     4:  *
                      5:  *   A damn useful little "backend" utility begun 950915 or thereabouts,
                      6:  *   as *Hobbit*'s first real stab at some sockets programming.  Something that
                      7:  *   should have and indeed may have existed ten years ago, but never became a
                      8:  *   standard Unix utility.  IMHO, "nc" could take its place right next to cat,
                      9:  *   cp, rm, mv, dd, ls, and all those other cryptic and Unix-like things.
                     10:  *
                     11:  *   Read the README for the whole story, doc, applications, etc.
                     12:  *
                     13:  *   Layout:
                     14:  *     conditional includes:
                     15:  *     includes:
                     16:  *     handy defines:
                     17:  *     globals:
                     18:  *     malloced globals:
                     19:  *     cmd-flag globals:
                     20:  *     support routines:
                     21:  *     readwrite select loop:
                     22:  *     main:
                     23:  *
                     24:  *  bluesky:
                     25:  *     parse ranges of IP address as well as ports, perhaps
                     26:  *     RAW mode!
                     27:  *     backend progs to grab a pty and look like a real telnetd?!
                     28:  *     backend progs to do various encryption modes??!?!
1.1       deraadt    29: */
                     30:
                     31:
                     32: #define HAVE_BIND              /* ASSUMPTION -- seems to work everywhere! */
                     33:
1.7       deraadt    34: #include <sys/types.h>
                     35: #include <sys/time.h>
                     36: #include <sys/select.h>
                     37: #include <sys/socket.h>
                     38: #include <netinet/in.h>
                     39: #include <netinet/in_systm.h>
                     40: #include <netinet/ip.h>
                     41: #include <arpa/inet.h>
                     42: #include <netdb.h>             /* hostent, gethostby*, getservby* */
                     43: #include <stdio.h>
                     44: #include <string.h>
1.11      ericj      45: #include <err.h>
1.7       deraadt    46: #include <errno.h>
                     47: #include <setjmp.h>
                     48: #include <signal.h>
                     49: #include <fcntl.h>
1.13      ericj      50: #include <stdarg.h>
1.1       deraadt    51: #include <stdlib.h>
1.5       art        52: #include <unistd.h>
1.1       deraadt    53:
                     54: #define SLEAZE_PORT 31337      /* for UDP-scan RTT trick, change if ya want */
                     55: #define BIGSIZ 8192            /* big buffers */
                     56:
1.7       deraadt    57: struct host_info {
1.11      ericj      58:        char    name[MAXHOSTNAMELEN];   /* DNS name */
                     59:        char    addrs[8][24];           /* ascii-format IP addresses */
                     60:        struct  in_addr iaddrs[8];      /* in_addr.s_addr: ulong */
1.1       deraadt    61: };
                     62:
1.7       deraadt    63: struct port_info {
1.6       deraadt    64:        char    name[64];       /* name in /etc/services */
                     65:        char    anum[8];        /* ascii-format number */
1.7       deraadt    66:        u_short  num;           /* real host-order number */
1.1       deraadt    67: };
                     68:
                     69: /* globals: */
1.11      ericj      70: jmp_buf jbuf;                  /* timer jump buffer*/
1.6       deraadt    71: int     jval = 0;              /* timer crud */
                     72: int     netfd = -1;
                     73: int     ofd = 0;               /* hexdump output fd */
1.7       deraadt    74:
1.6       deraadt    75: int     gatesidx = 0;          /* LSRR hop count */
                     76: int     gatesptr = 4;          /* initial LSRR pointer, settable */
1.7       deraadt    77: u_short  Single = 1;           /* zero if scanning */
1.1       deraadt    78: unsigned int insaved = 0;      /* stdin-buffer size for multi-mode */
                     79: unsigned int wrote_out = 0;    /* total stdout bytes */
                     80: unsigned int wrote_net = 0;    /* total net bytes */
                     81: static char hexnibs[20] = "0123456789abcdef  ";
                     82:
                     83: /* will malloc up the following globals: */
1.7       deraadt    84: struct timeval timer1, timer2;
1.11      ericj      85: struct sockaddr_in    *lclend = NULL;  /* sockaddr_in structs */
1.7       deraadt    86: struct sockaddr_in    *remend = NULL;
1.11      ericj      87: struct host_info  **gates = NULL;      /* LSRR hop hinfo */
                     88: char   *optbuf = NULL;                 /* LSRR or sockopts */
                     89: char   *bigbuf_in;                     /* data buffers */
1.6       deraadt    90: char   *bigbuf_net;
1.7       deraadt    91: fd_set fds1, fds2;
1.11      ericj      92: struct port_info   *pinfo = NULL;      /* for getpinfo / getservby* */
                     93: unsigned char *stage = NULL;           /* hexdump line buffer */
1.1       deraadt    94:
                     95: /* global cmd flags: */
1.7       deraadt    96: u_short  o_alla = 0;
1.1       deraadt    97: unsigned int o_interval = 0;
1.7       deraadt    98: u_short  o_listen = 0;
                     99: u_short  o_nflag = 0;
                    100: u_short  o_wfile = 0;
                    101: u_short  o_random = 0;
                    102: u_short  o_udpmode = 0;
                    103: u_short  o_verbose = 0;
1.1       deraadt   104: unsigned int o_wait = 0;
1.7       deraadt   105: u_short  o_zero = 0;
1.1       deraadt   106:
1.11      ericj     107: /* Function Prototype's */
1.13      ericj     108: void   help    __P(());
1.11      ericj     109: void   usage   __P((int));
1.13      ericj     110: void   nlog __P((int, char *, ...));
1.11      ericj     111:
                    112: /*
                    113:  * support routines -- the bulk of this thing.  Placed in such an order that
                    114:  * we don't have to forward-declare anything:
                    115:  */
                    116:
                    117: /*
                    118:  * catch :
                    119:  * no-brainer interrupt handler
                    120:  */
1.6       deraadt   121: void
                    122: catch()
1.1       deraadt   123: {
1.6       deraadt   124:        errno = 0;
                    125:        if (o_verbose > 1)      /* normally we don't care */
1.13      ericj     126:                nlog(1, "Sent %i Rcvd %i", wrote_net, wrote_out);
                    127:        nlog(1, " punt!");
1.1       deraadt   128: }
                    129:
                    130: /* timeout and other signal handling cruft */
1.6       deraadt   131: void
                    132: tmtravel()
1.1       deraadt   133: {
1.6       deraadt   134:        signal(SIGALRM, SIG_IGN);
                    135:        alarm(0);
                    136:        if (jval == 0)
1.13      ericj     137:                nlog(1, "spurious timer interrupt!");
1.6       deraadt   138:        longjmp(jbuf, jval);
1.1       deraadt   139: }
                    140:
1.11      ericj     141: /*
                    142:  * arm :
                    143:  * set the timer.  Zero secs arg means unarm
                    144:  */
1.6       deraadt   145: void
                    146: arm(num, secs)
                    147:        unsigned int num;
                    148:        unsigned int secs;
                    149: {
1.11      ericj     150:        if (secs == 0) {
1.6       deraadt   151:                signal(SIGALRM, SIG_IGN);
                    152:                alarm(0);
                    153:                jval = 0;
1.11      ericj     154:        } else {
1.6       deraadt   155:                signal(SIGALRM, tmtravel);
                    156:                alarm(secs);
                    157:                jval = num;
1.11      ericj     158:        }
1.7       deraadt   159: }
1.1       deraadt   160:
1.11      ericj     161: /*
                    162:  * findline :
                    163:  * find the next newline in a buffer; return inclusive size of that "line",
                    164:  * or the entire buffer size, so the caller knows how much to then write().
                    165:  * Not distinguishing \n vs \r\n for the nonce; it just works as is...
                    166:  */
1.6       deraadt   167: unsigned int
                    168: findline(buf, siz)
                    169:        char   *buf;
                    170:        unsigned int siz;
                    171: {
1.11      ericj     172:        char *p;
                    173:        int x;
1.6       deraadt   174:        if (!buf)               /* various sanity checks... */
                    175:                return (0);
                    176:        if (siz > BIGSIZ)
                    177:                return (0);
                    178:        x = siz;
                    179:        for (p = buf; x > 0; x--) {
                    180:                if (*p == '\n') {
                    181:                        x = (int) (p - buf);
                    182:                        x++;    /* 'sokay if it points just past the end! */
                    183:                            return (x);
                    184:                }
                    185:                p++;
1.11      ericj     186:        }
1.6       deraadt   187:            return (siz);
1.7       deraadt   188: }
1.1       deraadt   189:
1.11      ericj     190: /*
                    191:  * comparehosts :
                    192:  * cross-check the host_info we have so far against new gethostby*() info,
                    193:  * and holler about mismatches.  Perhaps gratuitous, but it can't hurt to
                    194:  * point out when someone's DNS is fukt.  Returns 1 if mismatch, in case
                    195:  * someone else wants to do something about it.
                    196:  */
1.6       deraadt   197: int
1.11      ericj     198: comparehosts(hinfo, hp)
                    199:        struct host_info   *hinfo;
1.6       deraadt   200:        struct hostent *hp;
                    201: {
                    202:        errno = 0;
1.11      ericj     203:        if (strcasecmp(hinfo->name, hp->h_name) != 0) {
1.13      ericj     204:                nlog(0, "DNS fwd/rev mismatch: %s != %s", hinfo->name, hp->h_name);
1.6       deraadt   205:                return (1);
                    206:        }
                    207:        return (0);
1.7       deraadt   208: }
1.1       deraadt   209:
1.11      ericj     210: /*
                    211:  * gethinfo:
                    212:  * resolve a host 8 ways from sunday; return a new host_info struct with its
                    213:  * info.  The argument can be a name or [ascii] IP address; it will try its
                    214:  * damndest to deal with it.  "numeric" governs whether we do any DNS at all,
                    215:  * and we also check o_verbose for what's appropriate work to do.
                    216:  */
1.7       deraadt   217: struct host_info   *
1.11      ericj     218: gethinfo(name, numeric)
1.6       deraadt   219:        char   *name;
1.7       deraadt   220:        u_short  numeric;
1.6       deraadt   221: {
                    222:        struct hostent *hostent;
                    223:        struct in_addr iaddr;
1.11      ericj     224:        struct host_info *hinfo = NULL;
                    225:        int x;
1.1       deraadt   226:
1.6       deraadt   227:        errno = 0;
                    228:        if (name)
1.11      ericj     229:                hinfo = (struct host_info *) calloc(1, sizeof(struct host_info));
                    230:
                    231:        if (!hinfo)
1.13      ericj     232:                nlog(1, "error obtaining host information");
1.11      ericj     233:
                    234:        strlcpy(hinfo->name, "(UNKNOWN)", sizeof(hinfo->name));
1.7       deraadt   235:        if (inet_aton(name, &iaddr) == 0) {
1.11      ericj     236:                if (numeric)
1.13      ericj     237:                        nlog(1, "Can't parse %s as an IP address", name);
1.6       deraadt   238:
1.11      ericj     239:                /*
                    240:                 * failure to look up a name is fatal,
                    241:                 * since we can't do anything with it.
                    242:                 */
1.6       deraadt   243:                hostent = gethostbyname(name);
                    244:                if (!hostent)
1.13      ericj     245:                        nlog(1, "%s: forward host lookup failed: ", name);
1.11      ericj     246:
                    247:                strlcpy(hinfo->name, hostent->h_name, MAXHOSTNAMELEN);
1.6       deraadt   248:                for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
1.11      ericj     249:                        memcpy(&hinfo->iaddrs[x], hostent->h_addr_list[x],
1.7       deraadt   250:                            sizeof(struct in_addr));
1.11      ericj     251:                        strlcpy(hinfo->addrs[x], inet_ntoa(hinfo->iaddrs[x]),
                    252:                            sizeof(hinfo->addrs[0]));
1.7       deraadt   253:                }
1.11      ericj     254:                /* Go ahead and return if we don't want to view more */
                    255:                if (!o_verbose)
                    256:                        return (hinfo);
                    257:
                    258:                /*
                    259:                 * Do inverse lookups in separate loop based on our collected
                    260:                 * forward addrs, since gethostby* tends to crap into the same
                    261:                 * buffer over and over.
                    262:                 */
                    263:                for (x = 0; hinfo->iaddrs[x].s_addr && (x < 8); x++) {
                    264:                        hostent = gethostbyaddr((char *) &hinfo->iaddrs[x],
1.7       deraadt   265:                            sizeof(struct in_addr), AF_INET);
1.6       deraadt   266:                        if ((!hostent) || (!hostent->h_name))
1.13      ericj     267:                                nlog(0, "Warning: inverse host lookup failed for %s: ",
1.11      ericj     268:                                    hinfo->addrs[x]);
1.6       deraadt   269:                        else
1.11      ericj     270:                                (void) comparehosts(hinfo, hostent);
                    271:                }
1.6       deraadt   272:
                    273:        } else {                /* not INADDR_NONE: numeric addresses... */
1.11      ericj     274:                memcpy(hinfo->iaddrs, &iaddr, sizeof(struct in_addr));
                    275:                strlcpy(hinfo->addrs[0], inet_ntoa(iaddr), sizeof(hinfo->addrs));
                    276:                /* If all that's wanted is numeric IP, go ahead and leave */
                    277:                if (numeric)
                    278:                        return (hinfo);
                    279:
                    280:                /* Go ahead and return if we don't want to view more */
                    281:                if (!o_verbose)
                    282:                        return (hinfo);
                    283:
                    284:                hostent = gethostbyaddr((char *) &iaddr,
                    285:                                        sizeof(struct in_addr), AF_INET);
                    286:
                    287:                /*
                    288:                 * numeric or not, failure to look up a PTR is
                    289:                 * *not* considered fatal
                    290:                 */
1.6       deraadt   291:                if (!hostent)
1.13      ericj     292:                        nlog(0, "%s: inverse host lookup failed: ", name);
1.6       deraadt   293:                else {
1.11      ericj     294:                        strlcpy(hinfo->name, hostent->h_name, MAXHOSTNAMELEN);
                    295:                        hostent = gethostbyname(hinfo->name);
1.6       deraadt   296:                        if ((!hostent) || (!hostent->h_addr_list[0]))
1.13      ericj     297:                                nlog(0, "Warning: forward host lookup failed for %s: ",
1.11      ericj     298:                                    hinfo->name);
1.6       deraadt   299:                        else
1.11      ericj     300:                                (void) comparehosts(hinfo, hostent);
                    301:                }
                    302:        }
1.1       deraadt   303:
1.11      ericj     304:        /*
                    305:         * Whatever-all went down previously, we should now have a host_info
                    306:         * struct with at least one IP address in it.
                    307:         */
                    308:        return (hinfo);
1.7       deraadt   309: }
1.1       deraadt   310:
1.11      ericj     311: /*
                    312:  * getpinfo:
                    313:  * Same general idea as gethinfo-- look up a port in /etc/services, fill
                    314:  * in global port_info, but return the actual port *number*.  Pass ONE of:
                    315:  *     pstring to resolve stuff like "23" or "exec";
                    316:  *     pnum to reverse-resolve something that's already a number.
                    317:  * If o_nflag is on, fill in what we can but skip the getservby??? stuff.
                    318:  * Might as well have consistent behavior here, and it *is* faster.
                    319:  */
1.7       deraadt   320: u_short
1.11      ericj     321: getpinfo(pstring, pnum)
1.6       deraadt   322:        char   *pstring;
                    323:        unsigned int pnum;
                    324: {
                    325:        struct servent *servent;
1.11      ericj     326:        int x;
                    327:        int y;
1.7       deraadt   328:        char   *whichp = "tcp";
1.6       deraadt   329:        if (o_udpmode)
1.7       deraadt   330:                whichp = "udp";
1.1       deraadt   331:
1.11      ericj     332:        pinfo->name[0] = '?';/* fast preload */
                    333:        pinfo->name[1] = '\0';
                    334:
                    335:        /*
                    336:         * case 1: reverse-lookup of a number; placed first since this case
                    337:         * is much more frequent if we're scanning.
                    338:         */
1.6       deraadt   339:        if (pnum) {
1.11      ericj     340:                /* Can't be both */
                    341:                if (pstring)
1.6       deraadt   342:                        return (0);
1.11      ericj     343:
1.6       deraadt   344:                x = pnum;
                    345:                if (o_nflag)    /* go faster, skip getservbyblah */
                    346:                        goto gp_finish;
                    347:                y = htons(x);   /* gotta do this -- see Fig.1 below */
                    348:                servent = getservbyport(y, whichp);
                    349:                if (servent) {
                    350:                        y = ntohs(servent->s_port);
                    351:                        if (x != y)     /* "never happen" */
1.13      ericj     352:                                nlog(0, "Warning: port-bynum mismatch, %d != %d", x, y);
1.11      ericj     353:                        strlcpy(pinfo->name, servent->s_name,
                    354:                            sizeof(pinfo->name));
1.7       deraadt   355:                }
1.6       deraadt   356:                goto gp_finish;
1.11      ericj     357:        }
                    358:        /*
                    359:         * case 2: resolve a string, but we still give preference to numbers
1.6       deraadt   360:         * instead of trying to resolve conflicts.  None of the entries in *my*
                    361:         * extensive /etc/services begins with a digit, so this should "always
                    362:         * work" unless you're at 3com and have some company-internal services
1.11      ericj     363:         * defined.
                    364:         */
1.6       deraadt   365:        if (pstring) {
1.11      ericj     366:                /* Can't be both */
                    367:                if (pnum)
1.6       deraadt   368:                        return (0);
1.11      ericj     369:
1.6       deraadt   370:                x = atoi(pstring);
                    371:                if (x)
1.11      ericj     372:                        return (getpinfo(NULL, x));     /* recurse for
1.6       deraadt   373:                                                         * numeric-string-arg */
                    374:                if (o_nflag)    /* can't use names! */
                    375:                        return (0);
                    376:                servent = getservbyname(pstring, whichp);
                    377:                if (servent) {
1.11      ericj     378:                        strlcpy(pinfo->name, servent->s_name,
                    379:                            sizeof(pinfo->name));
1.6       deraadt   380:                        x = ntohs(servent->s_port);
                    381:                        goto gp_finish;
                    382:                }               /* if servent */
                    383:        }                       /* if pstring */
                    384:        return (0);             /* catches any problems so far */
1.1       deraadt   385:
                    386: gp_finish:
1.11      ericj     387:        /*
                    388:         * Fall here whether or not we have a valid servent at this point, with
                    389:         * x containing our [host-order and therefore useful, dammit] port number.
                    390:         */
                    391:        sprintf(pinfo->anum, "%d", x);  /* always load any numeric
1.6       deraadt   392:                                                 * specs! */
1.11      ericj     393:        pinfo->num = (x & 0xffff);      /* u_short, remember... */
                    394:        return (pinfo->num);
1.7       deraadt   395: }
1.1       deraadt   396:
1.11      ericj     397: /*
                    398:  * nextport :
                    399:  * Come up with the next port to try, be it random or whatever.  "block" is
                    400:  * a ptr to randports array, whose bytes [so far] carry these meanings:
                    401:  *     0       ignore
                    402:  *     1       to be tested
                    403:  *     2       tested [which is set as we find them here]
                    404:  * returns a u_short random port, or 0 if all the t-b-t ones are used up.
                    405:  */
1.7       deraadt   406: u_short
1.6       deraadt   407: nextport(block)
                    408:        char   *block;
                    409: {
1.11      ericj     410:        unsigned int x;
                    411:        unsigned int y;
1.6       deraadt   412:
1.11      ericj     413:        y = 70000;                      /* high safety count for rnd-tries */
1.6       deraadt   414:        while (y > 0) {
1.16    ! ericj     415:                x = (arc4random() & 0xffff);
1.6       deraadt   416:                if (block[x] == 1) {    /* try to find a not-done one... */
                    417:                        block[x] = 2;
                    418:                        break;
                    419:                }
1.11      ericj     420:                x = 0;
1.6       deraadt   421:                y--;
1.11      ericj     422:        }
1.6       deraadt   423:        if (x)
                    424:                return (x);
                    425:
                    426:        y = 65535;              /* no random one, try linear downsearch */
                    427:        while (y > 0) {         /* if they're all used, we *must* be sure! */
                    428:                if (block[y] == 1) {
                    429:                        block[y] = 2;
                    430:                        break;
                    431:                }
                    432:                y--;
1.11      ericj     433:        }
1.6       deraadt   434:        if (y)
                    435:                return (y);     /* at least one left */
1.1       deraadt   436:
1.11      ericj     437:        return (0);
1.7       deraadt   438: }
1.1       deraadt   439:
1.11      ericj     440: /*
                    441:  * loadports :
                    442:  * set "to be tested" indications in BLOCK, from LO to HI.  Almost too small
                    443:  * to be a separate routine, but makes main() a little cleaner.
                    444:  */
1.6       deraadt   445: void
                    446: loadports(block, lo, hi)
                    447:        char   *block;
1.7       deraadt   448:        u_short  lo;
                    449:        u_short  hi;
1.6       deraadt   450: {
1.7       deraadt   451:        u_short  x;
1.6       deraadt   452:
                    453:        if (!block)
1.13      ericj     454:                nlog(1, "loadports: no block?!");
1.6       deraadt   455:        if ((!lo) || (!hi))
1.13      ericj     456:                nlog(1, "loadports: bogus values %d, %d", lo, hi);
1.6       deraadt   457:        x = hi;
                    458:        while (lo <= x) {
                    459:                block[x] = 1;
                    460:                x--;
                    461:        }
1.7       deraadt   462: }
                    463:
1.1       deraadt   464:
1.11      ericj     465: /*
                    466:  * doconnect :
                    467:  * do all the socket stuff, and return an fd for one of
                    468:  *     an open outbound TCP connection
                    469:  *     a UDP stub-socket thingie
                    470:  * with appropriate socket options set up if we wanted source-routing, or
                    471:  *     an unconnected TCP or UDP socket to listen on.
                    472:  * Examines various global o_blah flags to figure out what-all to do.
                    473:  */
1.6       deraadt   474: int
                    475: doconnect(rad, rp, lad, lp)
1.7       deraadt   476:        struct in_addr     *rad;
                    477:        u_short  rp;
                    478:        struct in_addr     *lad;
                    479:        u_short  lp;
1.6       deraadt   480: {
1.14      ericj     481:        int nnetfd = 0;
1.11      ericj     482:        int rr;
1.6       deraadt   483:        int     x, y;
                    484:        errno = 0;
1.1       deraadt   485:
1.11      ericj     486:        /* grab a socket; set opts */
1.14      ericj     487:        while (nnetfd == 0) {
                    488:                if (o_udpmode)
                    489:                        nnetfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
                    490:                else
                    491:                        nnetfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
                    492:                if (nnetfd < 0)
                    493:                        nlog(1, "Can't get socket");
                    494:        }
                    495:
1.6       deraadt   496:        x = 1;
                    497:        rr = setsockopt(nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
                    498:        if (rr == -1)
1.13      ericj     499:                nlog(1, NULL);
1.6       deraadt   500:
                    501:        /* fill in all the right sockaddr crud */
                    502:        lclend->sin_family = AF_INET;
                    503:        remend->sin_family = AF_INET;
1.1       deraadt   504:
1.11      ericj     505:        /* if lad/lp, do appropriate binding */
1.6       deraadt   506:        if (lad)
1.7       deraadt   507:                memcpy(&lclend->sin_addr.s_addr, lad, sizeof(struct in_addr));
1.6       deraadt   508:        if (lp)
                    509:                lclend->sin_port = htons(lp);
1.11      ericj     510:
1.6       deraadt   511:        rr = 0;
                    512:        if (lad || lp) {
                    513:                x = (int) lp;
1.11      ericj     514:                /* try a few times for the local bind, a la ftp-data-port... */
1.6       deraadt   515:                for (y = 4; y > 0; y--) {
1.7       deraadt   516:                        rr = bind(nnetfd, (struct sockaddr *) lclend,
                    517:                            sizeof(struct sockaddr_in));
1.6       deraadt   518:                        if (rr == 0)
                    519:                                break;
                    520:                        if (errno != EADDRINUSE)
                    521:                                break;
                    522:                        else {
1.13      ericj     523:                                nlog(0, "retrying local %s:%d", inet_ntoa(lclend->sin_addr), lp);
1.6       deraadt   524:                                sleep(2);
                    525:                                errno = 0;      /* clear from sleep */
1.11      ericj     526:                        }
                    527:                }
                    528:        }
1.6       deraadt   529:        if (rr)
1.13      ericj     530:                nlog(1, "Can't grab %s:%d with bind",
1.6       deraadt   531:                    inet_ntoa(lclend->sin_addr), lp);
1.1       deraadt   532:
1.6       deraadt   533:        if (o_listen)
                    534:                return (nnetfd);/* thanks, that's all for today */
1.1       deraadt   535:
1.7       deraadt   536:        memcpy(&remend->sin_addr.s_addr, rad, sizeof(struct in_addr));
1.6       deraadt   537:        remend->sin_port = htons(rp);
1.1       deraadt   538:
1.6       deraadt   539:        /* wrap connect inside a timer, and hit it */
                    540:        arm(1, o_wait);
                    541:        if (setjmp(jbuf) == 0) {
1.11      ericj     542:                rr = connect(nnetfd, (struct sockaddr *) remend,
                    543:                                                sizeof(struct sockaddr));
                    544:        } else {
1.6       deraadt   545:                rr = -1;
1.11      ericj     546:                errno = ETIMEDOUT;
1.6       deraadt   547:        }
                    548:        arm(0, 0);
                    549:        if (rr == 0)
                    550:                return (nnetfd);
1.11      ericj     551:        close(nnetfd);
1.6       deraadt   552:        return (-1);
1.7       deraadt   553: }
1.1       deraadt   554:
1.11      ericj     555: /*
                    556:  * dolisten :
                    557:  * just like doconnect, and in fact calls a hunk of doconnect, but listens for
                    558:  * incoming and returns an open connection *from* someplace.  If we were
                    559:  * given host/port args, any connections from elsewhere are rejected.  This
                    560:  * in conjunction with local-address binding should limit things nicely.
                    561:  */
1.6       deraadt   562: int
                    563: dolisten(rad, rp, lad, lp)
1.7       deraadt   564:        struct in_addr     *rad;
                    565:        u_short  rp;
                    566:        struct in_addr     *lad;
                    567:        u_short  lp;
1.6       deraadt   568: {
1.11      ericj     569:        int nnetfd;
                    570:        int rr;
1.7       deraadt   571:        struct host_info   *whozis = NULL;
1.6       deraadt   572:        int     x;
                    573:        char   *cp;
1.7       deraadt   574:        u_short  z;
1.6       deraadt   575:        errno = 0;
1.1       deraadt   576:
1.11      ericj     577:        /*
                    578:         * Pass everything off to doconnect,
                    579:         * who in o_listen mode just gets a socket
                    580:         */
1.6       deraadt   581:        nnetfd = doconnect(rad, rp, lad, lp);
                    582:        if (nnetfd <= 0)
                    583:                return (-1);
1.11      ericj     584:        if (o_udpmode) {
                    585:                if (!lp)
1.13      ericj     586:                        nlog(1, "UDP listen needs -p arg");
1.6       deraadt   587:        } else {
1.11      ericj     588:                rr = listen(nnetfd, 1);
                    589:                if (rr < 0)
1.13      ericj     590:                        nlog(1, "error listening");
1.6       deraadt   591:        }
1.1       deraadt   592:
1.6       deraadt   593:        if (o_verbose) {
1.11      ericj     594:                x = sizeof(struct sockaddr);
1.7       deraadt   595:                rr = getsockname(nnetfd, (struct sockaddr *) lclend, &x);
1.6       deraadt   596:                if (rr < 0)
1.13      ericj     597:                        nlog(0, "local getsockname failed");
1.6       deraadt   598:                strcpy(bigbuf_net, "listening on [");   /* buffer reuse... */
                    599:                if (lclend->sin_addr.s_addr)
                    600:                        strcat(bigbuf_net, inet_ntoa(lclend->sin_addr));
                    601:                else
                    602:                        strcat(bigbuf_net, "any");
1.15      ericj     603:                strcat(bigbuf_net, "] ...");
1.6       deraadt   604:                z = ntohs(lclend->sin_port);
1.13      ericj     605:                nlog(0, "%s %d", bigbuf_net, z);
1.6       deraadt   606:        }                       /* verbose -- whew!! */
1.11      ericj     607:        /*
                    608:         * UDP is a speeeeecial case -- we have to do I/O *and* get the
1.6       deraadt   609:         * calling party's particulars all at once, listen() and accept()
                    610:         * don't apply. At least in the BSD universe, however, recvfrom/PEEK
                    611:         * is enough to tell us something came in, and we can set things up so
                    612:         * straight read/write actually does work after all.  Yow.  YMMV on
1.11      ericj     613:         * strange platforms!
                    614:         */
1.6       deraadt   615:        if (o_udpmode) {
1.7       deraadt   616:                x = sizeof(struct sockaddr);    /* retval for recvfrom */
1.6       deraadt   617:                arm(2, o_wait); /* might as well timeout this, too */
                    618:                if (setjmp(jbuf) == 0) {        /* do timeout for initial
                    619:                                                 * connect */
1.11      ericj     620:                        rr = recvfrom(nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK,
                    621:                                        (struct sockaddr *)remend, &x);
1.6       deraadt   622:                } else
1.11      ericj     623:                        goto dol_tmo;
1.6       deraadt   624:                arm(0, 0);
1.11      ericj     625:                rr = connect(nnetfd, (struct sockaddr *)remend,
                    626:                                                sizeof(struct sockaddr));
1.6       deraadt   627:                goto whoisit;
1.11      ericj     628:        }
1.6       deraadt   629:        /* fall here for TCP */
1.11      ericj     630:        x = sizeof(struct sockaddr);
                    631:        arm(2, o_wait);
1.6       deraadt   632:        if (setjmp(jbuf) == 0) {
1.7       deraadt   633:                rr = accept(nnetfd, (struct sockaddr *) remend, &x);
1.6       deraadt   634:        } else
1.11      ericj     635:                goto dol_tmo;
1.6       deraadt   636:        arm(0, 0);
                    637:        close(nnetfd);          /* dump the old socket */
                    638:        nnetfd = rr;            /* here's our new one */
1.1       deraadt   639:
                    640: whoisit:
1.6       deraadt   641:        if (rr < 0)
                    642:                goto dol_err;   /* bail out if any errors so far */
1.1       deraadt   643:
1.11      ericj     644:        /*
                    645:         * Find out what address the connection was *to* on
                    646:         * our end, in case we're doing a listen-on-any on
                    647:         * a multihomed machine. This allows one to offer
                    648:         * different services via different alias addresses,
                    649:         * such as the "virtual web site" hack.
                    650:         */
1.6       deraadt   651:        memset(bigbuf_net, 0, 64);
                    652:        cp = &bigbuf_net[32];
1.7       deraadt   653:        x = sizeof(struct sockaddr);
                    654:        rr = getsockname(nnetfd, (struct sockaddr *) lclend, &x);
1.12      ericj     655:        if (rr < 0 && o_verbose)
1.13      ericj     656:                nlog(0, "post-rcv getsockname failed");
1.6       deraadt   657:        strcpy(cp, inet_ntoa(lclend->sin_addr));
1.1       deraadt   658:
1.6       deraadt   659:        z = ntohs(remend->sin_port);
                    660:        strcpy(bigbuf_net, inet_ntoa(remend->sin_addr));
1.11      ericj     661:        whozis = gethinfo(bigbuf_net, o_nflag);
1.6       deraadt   662:        errno = 0;
1.11      ericj     663:        x = 0;
1.6       deraadt   664:        if (rad)                /* xxx: fix to go down the *list* if we have
                    665:                                 * one? */
1.7       deraadt   666:                if (memcmp(rad, whozis->iaddrs, sizeof(struct sockaddr)))
1.6       deraadt   667:                        x = 1;
1.11      ericj     668:        if (rp) {
1.6       deraadt   669:                if (z != rp)
                    670:                        x = 1;
1.11      ericj     671:        }
                    672:        if (x) {
1.13      ericj     673:                nlog(1, "invalid connection to [%s] from %s [%s] %d",
1.6       deraadt   674:                    cp, whozis->name, whozis->addrs[0], z);
1.11      ericj     675:        }
1.12      ericj     676:        if (o_verbose) {
1.13      ericj     677:                nlog(0, "connect to [%s] from %s [%s] %d",
1.12      ericj     678:                        cp, whozis->name, whozis->addrs[0], z);
                    679:        }
1.11      ericj     680:        return (nnetfd);
1.1       deraadt   681:
                    682: dol_tmo:
1.11      ericj     683:        errno = ETIMEDOUT;
1.1       deraadt   684: dol_err:
1.6       deraadt   685:        close(nnetfd);
                    686:        return (-1);
1.7       deraadt   687: }
1.1       deraadt   688:
1.11      ericj     689: /*
                    690:  * udptest :
                    691:  * fire a couple of packets at a UDP target port, just to see if it's really
                    692:  * there.  On BSD kernels, ICMP host/port-unreachable errors get delivered to
                    693:  * our socket as ECONNREFUSED write errors.  On SV kernels, we lose; we'll have
                    694:  * to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
                    695:  * backend.  Guess where one could swipe the appropriate code from...
                    696:  *
                    697:  * Use the time delay between writes if given, otherwise use the "tcp ping"
                    698:  * trick for getting the RTT.  [I got that idea from pluvius, and warped it.]
                    699:  * Return either the original fd, or clean up and return -1.
                    700:  */
1.6       deraadt   701: udptest(fd, where)
                    702:        int     fd;
1.7       deraadt   703:        struct in_addr     *where;
1.6       deraadt   704: {
1.11      ericj     705:        int rr;
1.6       deraadt   706:
                    707:        rr = write(fd, bigbuf_in, 1);
1.12      ericj     708:        if (rr != 1 && o_verbose)
1.13      ericj     709:                nlog(0, "udptest first write failed?! errno %d", errno);
1.6       deraadt   710:        if (o_wait)
                    711:                sleep(o_wait);
                    712:        else {
1.11      ericj     713:                o_udpmode = 0;
                    714:                o_wait = 5;
1.6       deraadt   715:                rr = doconnect(where, SLEAZE_PORT, 0, 0);
                    716:                if (rr > 0)
1.11      ericj     717:                        close(rr);
                    718:                o_wait = 0;
                    719:                o_udpmode++;
                    720:        }
                    721:        errno = 0;
1.6       deraadt   722:        rr = write(fd, bigbuf_in, 1);
1.11      ericj     723:        if (rr == 1)
1.6       deraadt   724:                return (fd);
1.11      ericj     725:        close(fd);
1.6       deraadt   726:        return (-1);
1.7       deraadt   727: }
                    728:
1.11      ericj     729: /*
                    730:  *  oprint :
                    731:  * Hexdump bytes shoveled either way to a running logfile, in the format:
                    732:  * D offset       -  - - - --- 16 bytes --- - - -  -     # .... ascii .....
                    733:  * where "which" sets the direction indicator, D:
                    734:  * 0 -- sent to network, or ">"
                    735:  * 1 -- rcvd and printed to stdout, or "<"
                    736:  * and "buf" and "n" are data-block and length.  If the current block generates
                    737:  * a partial line, so be it; we *want* that lockstep indication of who sent
                    738:  * what when.  Adapted from dgaudet's original example -- but must be ripping
                    739:  * *fast*, since we don't want to be too disk-bound.
                    740:  */
1.6       deraadt   741: void
                    742: oprint(which, buf, n)
                    743:        int     which;
                    744:        char   *buf;
                    745:        int     n;
                    746: {
                    747:        int     bc;             /* in buffer count */
                    748:        int     obc;            /* current "global" offset */
                    749:        int     soc;            /* stage write count */
1.11      ericj     750:        unsigned char *p;       /* main buf ptr; m.b. unsigned here */
                    751:        unsigned char *op;      /* out hexdump ptr */
                    752:        unsigned char *a;       /* out asc-dump ptr */
                    753:        int x;
                    754:        unsigned int y;
1.6       deraadt   755:
                    756:        if (!ofd)
1.13      ericj     757:                nlog(1, "oprint called with no open fd?!");
1.6       deraadt   758:        if (n == 0)
                    759:                return;
                    760:
                    761:        op = stage;
                    762:        if (which) {
                    763:                *op = '<';
                    764:                obc = wrote_out;/* use the globals! */
                    765:        } else {
                    766:                *op = '>';
                    767:                obc = wrote_net;
                    768:        }
                    769:        op++;                   /* preload "direction" */
                    770:        *op = ' ';
                    771:        p = (unsigned char *) buf;
                    772:        bc = n;
                    773:        stage[59] = '#';        /* preload separator */
                    774:        stage[60] = ' ';
                    775:
                    776:        while (bc) {            /* for chunk-o-data ... */
                    777:                x = 16;
                    778:                soc = 78;       /* len of whole formatted line */
                    779:                if (bc < x) {
                    780:                        soc = soc - 16 + bc;    /* fiddle for however much is
                    781:                                                 * left */
                    782:                        x = (bc * 3) + 11;      /* 2 digits + space per, after
                    783:                                                 * D & offset */
                    784:                        op = &stage[x];
                    785:                        x = 16 - bc;
                    786:                        while (x) {
                    787:                                *op++ = ' ';    /* preload filler spaces */
                    788:                                *op++ = ' ';
                    789:                                *op++ = ' ';
                    790:                                x--;
                    791:                        }
                    792:                        x = bc; /* re-fix current linecount */
                    793:                }               /* if bc < x */
                    794:                bc -= x;        /* fix wrt current line size */
                    795:                sprintf(&stage[2], "%8.8x ", obc);      /* xxx: still slow? */
                    796:                obc += x;       /* fix current offset */
                    797:                op = &stage[11];/* where hex starts */
                    798:                a = &stage[61]; /* where ascii starts */
                    799:
                    800:                while (x) {     /* for line of dump, however long ... */
                    801:                        y = (int) (*p >> 4);    /* hi half */
                    802:                        *op = hexnibs[y];
                    803:                        op++;
                    804:                        y = (int) (*p & 0x0f);  /* lo half */
                    805:                        *op = hexnibs[y];
                    806:                        op++;
                    807:                        *op = ' ';
                    808:                        op++;
                    809:                        if ((*p > 31) && (*p < 127))
                    810:                                *a = *p;        /* printing */
                    811:                        else
                    812:                                *a = '.';       /* nonprinting, loose def */
                    813:                        a++;
                    814:                        p++;
                    815:                        x--;
                    816:                }               /* while x */
                    817:                *a = '\n';      /* finish the line */
                    818:                x = write(ofd, stage, soc);
                    819:                if (x < 0)
1.13      ericj     820:                        nlog(1, "ofd write err");
1.11      ericj     821:        }
1.7       deraadt   822: }
                    823:
1.1       deraadt   824: #ifdef TELNET
1.7       deraadt   825: u_short  o_tn = 0;             /* global -t option */
1.1       deraadt   826:
1.11      ericj     827: /*
                    828:  *  atelnet :
                    829:  * Answer anything that looks like telnet negotiation with don't/won't.
                    830:  * This doesn't modify any data buffers, update the global output count,
                    831:  * or show up in a hexdump -- it just shits into the outgoing stream.
                    832:  * Idea and codebase from Mudge@l0pht.com.
                    833:  */
1.6       deraadt   834: void
                    835: atelnet(buf, size)
                    836:        unsigned char *buf;     /* has to be unsigned here! */
                    837:        unsigned int size;
                    838: {
                    839:        static unsigned char obuf[4];   /* tiny thing to build responses into */
1.11      ericj     840:        int x;
                    841:        unsigned char y;
                    842:        unsigned char *p;
1.6       deraadt   843:
                    844:        y = 0;
                    845:        p = buf;
                    846:        x = size;
                    847:        while (x > 0) {
                    848:                if (*p != 255)  /* IAC? */
                    849:                        goto notiac;
                    850:                obuf[0] = 255;
                    851:                p++;
                    852:                x--;
                    853:                if ((*p == 251) || (*p == 252)) /* WILL or WONT */
                    854:                        y = 254;/* -> DONT */
                    855:                if ((*p == 253) || (*p == 254)) /* DO or DONT */
                    856:                        y = 252;/* -> WONT */
                    857:                if (y) {
                    858:                        obuf[1] = y;
                    859:                        p++;
                    860:                        x--;
1.11      ericj     861:                        obuf[2] = *p;
1.6       deraadt   862:                        (void) write(netfd, obuf, 3);
1.11      ericj     863:                        /*
                    864:                         * if one wanted to bump wrote_net or do
                    865:                         * a hexdump line, here's the place.
                    866:                         */
1.6       deraadt   867:                        y = 0;
1.11      ericj     868:                }
1.1       deraadt   869: notiac:
1.6       deraadt   870:                p++;
                    871:                x--;
1.11      ericj     872:        }
1.7       deraadt   873: }
1.11      ericj     874: #endif /* TELNET */
1.7       deraadt   875:
1.11      ericj     876: /*
                    877:  *  readwrite :
                    878:  * handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
                    879:  * In this instance, return what might become our exit status.
                    880:  */
1.6       deraadt   881: int
                    882: readwrite(fd)
                    883:        int     fd;
                    884: {
1.11      ericj     885:        int rr;
                    886:        char *zp;       /* stdin buf ptr */
                    887:        char *np;       /* net-in buf ptr */
1.6       deraadt   888:        unsigned int rzleft;
                    889:        unsigned int rnleft;
1.7       deraadt   890:        u_short  netretry;      /* net-read retry counter */
1.11      ericj     891:        u_short  wretry;        /* net-write sanity counter */
                    892:        u_short  wfirst;        /* one-shot flag to skip first net read */
1.1       deraadt   893:
1.11      ericj     894:        /*
                    895:         * if you don't have all this FD_* macro hair in sys/types.h,
                    896:         * you'll have to either find it or do your own bit-bashing:
                    897:         * *ds1 |= (1 << fd), etc.
                    898:         */
1.6       deraadt   899:        if (fd > FD_SETSIZE) {
1.13      ericj     900:                nlog(0, "Preposterous fd value %d", fd);
1.6       deraadt   901:                return (1);
                    902:        }
1.11      ericj     903:        FD_SET(fd, &fds1);
1.6       deraadt   904:        netretry = 2;
                    905:        wfirst = 0;
                    906:        rzleft = rnleft = 0;
                    907:        if (insaved) {
                    908:                rzleft = insaved;       /* preload multi-mode fakeouts */
                    909:                zp = bigbuf_in;
                    910:                wfirst = 1;
1.11      ericj     911:                /* If not scanning, this is a one-off first */
                    912:                if (Single)
                    913:                        insaved = 0;
1.6       deraadt   914:                else {
1.11      ericj     915:                        FD_CLR(0, &fds1);
                    916:                        close(0);
                    917:                }
                    918:        }
1.6       deraadt   919:        if (o_interval)
1.11      ericj     920:                sleep(o_interval);
                    921:        errno = 0;
1.1       deraadt   922:
1.7       deraadt   923:        while (FD_ISSET(fd, &fds1)) {   /* i.e. till the *net* closes! */
1.9       art       924:                struct timeval *tv;
                    925:
1.11      ericj     926:                wretry = 8200;          /* more than we'll ever hafta write */
                    927:                if (wfirst) {           /* any saved stdin buffer? */
1.6       deraadt   928:                        wfirst = 0;     /* clear flag for the duration */
                    929:                        goto shovel;    /* and go handle it first */
                    930:                }
1.7       deraadt   931:                fds2 = fds1;
1.9       art       932:                if (timer1.tv_sec > 0 || timer1.tv_usec > 0) {
                    933:                        memcpy(&timer2, &timer1, sizeof(struct timeval));
                    934:                        tv = &timer2;
                    935:                } else
                    936:                        tv = NULL;
                    937:                rr = select(getdtablesize(), &fds2, 0, 0, tv);
1.6       deraadt   938:                if (rr < 0) {
1.11      ericj     939:                        if (errno != EINTR) {
1.13      ericj     940:                                nlog(0, "Select Failure");
1.6       deraadt   941:                                close(fd);
                    942:                                return (1);
                    943:                        }
1.11      ericj     944:                }
1.6       deraadt   945:                /* if we have a timeout AND stdin is closed AND we haven't
                    946:                 * heard anything from the net during that time, assume it's
                    947:                 * dead and close it too. */
                    948:                if (rr == 0) {
1.7       deraadt   949:                        if (!FD_ISSET(0, &fds1))
1.6       deraadt   950:                                netretry--;     /* we actually try a coupla
                    951:                                                 * times. */
                    952:                        if (!netretry) {
1.12      ericj     953:                                if (o_verbose)  /* normally we don't
1.6       deraadt   954:                                                         * care */
1.13      ericj     955:                                        nlog(0, "net timeout");
1.6       deraadt   956:                                close(fd);
                    957:                                return (0);     /* not an error! */
                    958:                        }
                    959:                }               /* select timeout */
1.11      ericj     960:                /* XXX: should we check the exception fds too?  The read fds
1.6       deraadt   961:                 * seem to give us the right info, and none of the examples I
                    962:                 * found bothered. */
                    963:                /* Ding!!  Something arrived, go check all the incoming
                    964:                 * hoppers, net first */
1.7       deraadt   965:                if (FD_ISSET(fd, &fds2)) {      /* net: ding! */
1.6       deraadt   966:                        rr = read(fd, bigbuf_net, BIGSIZ);
                    967:                        if (rr <= 0) {
1.7       deraadt   968:                                FD_CLR(fd, &fds1);      /* net closed, we'll
1.6       deraadt   969:                                                         * finish up... */
                    970:                                rzleft = 0;     /* can't write anymore: broken
                    971:                                                 * pipe */
                    972:                        } else {
                    973:                                rnleft = rr;
                    974:                                np = bigbuf_net;
1.1       deraadt   975: #ifdef TELNET
1.6       deraadt   976:                                if (o_tn)
                    977:                                        atelnet(np, rr);        /* fake out telnet stuff */
1.11      ericj     978: #endif /* TELNET */
                    979:                        }
                    980:                }
1.6       deraadt   981:                /* if we're in "slowly" mode there's probably still stuff in
                    982:                 * the stdin buffer, so don't read unless we really need MORE
                    983:                 * INPUT!  MORE INPUT! */
                    984:                if (rzleft)
                    985:                        goto shovel;
1.1       deraadt   986:
1.11      ericj     987:                if (FD_ISSET(0, &fds2)) {
1.6       deraadt   988:                        rr = read(0, bigbuf_in, BIGSIZ);
1.11      ericj     989:                        if (rr <= 0) {
                    990:                                FD_CLR(0, &fds1);       /* disable and close */
1.6       deraadt   991:                                close(0);
                    992:                        } else {
                    993:                                rzleft = rr;
                    994:                                zp = bigbuf_in;
1.11      ericj     995:                                if (!Single) {
                    996:                                        insaved = rr;
                    997:                                        FD_CLR(0, &fds1);
                    998:                                        close(0);
                    999:                                }
                   1000:                        }
                   1001:                }
1.1       deraadt  1002: shovel:
1.11      ericj    1003:                /* sanity check.  Works because they're both unsigned... */
1.6       deraadt  1004:                if ((rzleft > 8200) || (rnleft > 8200)) {
                   1005:                        rzleft = rnleft = 0;
                   1006:                }
1.11      ericj    1007:                /* net write retries sometimes happen on UDP connections */
1.6       deraadt  1008:                if (!wretry) {  /* is something hung? */
1.13      ericj    1009:                        nlog(0, "too many output retries");
1.6       deraadt  1010:                        return (1);
                   1011:                }
                   1012:                if (rnleft) {
                   1013:                        rr = write(1, np, rnleft);
                   1014:                        if (rr > 0) {
                   1015:                                if (o_wfile)
1.11      ericj    1016:                                        oprint(1, np, rr);
                   1017:                                np += rr;
                   1018:                                rnleft -= rr;
1.6       deraadt  1019:                                wrote_out += rr;        /* global count */
                   1020:                        }
1.11      ericj    1021:                }
1.6       deraadt  1022:                if (rzleft) {
1.11      ericj    1023:                        if (o_interval)
1.6       deraadt  1024:                                rr = findline(zp, rzleft);
                   1025:                        else
                   1026:                                rr = rzleft;
1.11      ericj    1027:                        rr = write(fd, zp, rr);
1.6       deraadt  1028:                        if (rr > 0) {
                   1029:                                if (o_wfile)
1.11      ericj    1030:                                        oprint(0, zp, rr);
1.6       deraadt  1031:                                zp += rr;
                   1032:                                rzleft -= rr;
1.11      ericj    1033:                                wrote_net += rr;
1.6       deraadt  1034:                        }
1.11      ericj    1035:                }
                   1036:                if (o_interval) {
1.6       deraadt  1037:                        sleep(o_interval);
1.11      ericj    1038:                        errno = 0;
                   1039:                        continue;
1.6       deraadt  1040:                }
1.11      ericj    1041:                if ((rzleft) || (rnleft)) {
                   1042:                        wretry--;
1.6       deraadt  1043:                        goto shovel;
                   1044:                }
1.11      ericj    1045:        }
1.1       deraadt  1046:
1.6       deraadt  1047:        close(fd);
                   1048:        return (0);
1.7       deraadt  1049: }
1.1       deraadt  1050:
                   1051: /* main :
                   1052:    now we pull it all together... */
1.16    ! ericj    1053: int
1.6       deraadt  1054: main(argc, argv)
                   1055:        int     argc;
                   1056:        char  **argv;
1.1       deraadt  1057: {
1.11      ericj    1058:        int x, ch;
                   1059:        char *cp;
1.7       deraadt  1060:        struct host_info   *gp;
                   1061:        struct host_info   *whereto = NULL;
                   1062:        struct host_info   *wherefrom = NULL;
                   1063:        struct in_addr     *ouraddr = NULL;
                   1064:        struct in_addr     *themaddr = NULL;
                   1065:        u_short  o_lport = 0;
                   1066:        u_short  ourport = 0;
                   1067:        u_short  loport = 0;    /* for scanning stuff */
                   1068:        u_short  hiport = 0;
                   1069:        u_short  curport = 0;
1.6       deraadt  1070:        char   *randports = NULL;
1.1       deraadt  1071:
                   1072: #ifdef HAVE_BIND
1.6       deraadt  1073:        res_init();
1.1       deraadt  1074: #endif
1.7       deraadt  1075:        lclend = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr));
                   1076:        remend = (struct sockaddr_in *) calloc(1, sizeof(struct sockaddr));
                   1077:        bigbuf_in = calloc(1, BIGSIZ);
                   1078:        bigbuf_net = calloc(1, BIGSIZ);
1.11      ericj    1079:        pinfo= (struct port_info *) calloc(1, sizeof(struct port_info));
1.6       deraadt  1080:
                   1081:        errno = 0;
                   1082:        gatesptr = 4;
1.1       deraadt  1083:
1.11      ericj    1084:        /*
                   1085:         * We want to catch a few of these signals.
                   1086:         * Others we disgard.
                   1087:         */
1.6       deraadt  1088:        signal(SIGINT, catch);
                   1089:        signal(SIGQUIT, catch);
                   1090:        signal(SIGTERM, catch);
                   1091:        signal(SIGURG, SIG_IGN);
                   1092:        signal(SIGPIPE, SIG_IGN);       /* important! */
1.1       deraadt  1093:
1.11      ericj    1094:        /*
                   1095:         * If no args given at all, get 'em from stdin, construct an argv,
                   1096:         * and hand anything left over to readwrite().
                   1097:         */
1.6       deraadt  1098:        if (argc == 1) {
1.16    ! ericj    1099:                /* Loop until we get a command to try */
        !          1100:                for (;;) {
        !          1101:                        cp = argv[0];
        !          1102:                        argv = (char **) calloc(1, 128 * sizeof(char *));
        !          1103:                        argv[0] = cp;   /* leave old prog name intact */
        !          1104:                        cp = calloc(1, BIGSIZ);
        !          1105:                        argv[1] = cp;   /* head of new arg block */
        !          1106:                        fprintf(stderr, "Cmd line: ");
        !          1107:                        fflush(stderr); /* I dont care if it's unbuffered or not! */
        !          1108:                        insaved = read(0, cp, BIGSIZ-1); /* we're gonna fake fgets()
        !          1109:                                                          * here */
        !          1110:                        cp[BIGSIZ-1] = '\0';
        !          1111:                        if (*cp != '\n' && *cp != '\t')
        !          1112:                                break;
        !          1113:                }
1.6       deraadt  1114:                if (insaved <= 0)
1.13      ericj    1115:                        nlog(1, "wrong");
1.6       deraadt  1116:                x = findline(cp, insaved);
                   1117:                if (x)
                   1118:                        insaved -= x;   /* remaining chunk size to be sent */
                   1119:                if (insaved)    /* which might be zero... */
                   1120:                        memcpy(bigbuf_in, &cp[x], insaved);
                   1121:                cp = strchr(argv[1], '\n');
                   1122:                if (cp)
                   1123:                        *cp = '\0';
                   1124:                cp = strchr(argv[1], '\r');     /* look for ^M too */
                   1125:                if (cp)
                   1126:                        *cp = '\0';
1.1       deraadt  1127:
1.11      ericj    1128:                /*
                   1129:                 * Find and stash pointers to remaining new "args"
                   1130:                 */
1.6       deraadt  1131:                cp = argv[1];
                   1132:                cp++;           /* skip past first char */
                   1133:                x = 2;          /* we know argv 0 and 1 already */
                   1134:                for (; *cp != '\0'; cp++) {
                   1135:                        if (*cp == ' ') {
                   1136:                                *cp = '\0';     /* smash all spaces */
                   1137:                                continue;
                   1138:                        } else {
                   1139:                                if (*(cp - 1) == '\0') {
                   1140:                                        argv[x] = cp;
                   1141:                                        x++;
                   1142:                                }
                   1143:                        }       /* if space */
                   1144:                }               /* for cp */
                   1145:                argc = x;
1.11      ericj    1146:        }
                   1147:
                   1148:        while ((ch = getopt(argc, argv, "g:G:hi:lno:p:rs:tuvw:z")) != -1) {
                   1149:                switch (ch) {
                   1150:                case 'G':                       /* srcrt gateways pointer val */
1.6       deraadt  1151:                        x = atoi(optarg);
1.11      ericj    1152:                        /* Mask of bits */
                   1153:                        if ((x) && (x == (x & 0x1c)))
1.6       deraadt  1154:                                gatesptr = x;
                   1155:                        else
1.13      ericj    1156:                                nlog(1, "invalid hop pointer %d, must be multiple of 4 <= 28", x);
1.6       deraadt  1157:                        break;
1.11      ericj    1158:                case 'g':                       /* srcroute hop[s] */
1.6       deraadt  1159:                        if (gatesidx > 8)
1.13      ericj    1160:                                nlog(1, "Too many -g hops!");
1.11      ericj    1161:                        if (gates == NULL)
                   1162:                                gates = (struct host_info **) calloc(1,
                   1163:                                                sizeof(struct host_info *) * 10);
                   1164:                        gp = gethinfo(optarg, o_nflag);
1.6       deraadt  1165:                        if (gp)
                   1166:                                gates[gatesidx] = gp;
                   1167:                        gatesidx++;
                   1168:                        break;
                   1169:                case 'h':
1.11      ericj    1170:                        help();
                   1171:                        break;
                   1172:                case 'i':                       /* line-interval time */
1.6       deraadt  1173:                        o_interval = atoi(optarg) & 0xffff;
                   1174:                        if (!o_interval)
1.13      ericj    1175:                                nlog(1, "invalid interval time %s", optarg);
1.6       deraadt  1176:                        break;
1.11      ericj    1177:                case 'l':                       /* listen mode */
1.6       deraadt  1178:                        o_listen++;
                   1179:                        break;
1.11      ericj    1180:                case 'n':                       /* numeric-only, no DNS lookups */
1.6       deraadt  1181:                        o_nflag++;
                   1182:                        break;
1.11      ericj    1183:                case 'o':                       /* hexdump log */
1.6       deraadt  1184:                        stage = (unsigned char *) optarg;
                   1185:                        o_wfile++;
                   1186:                        break;
1.11      ericj    1187:                case 'p':                       /* local source port */
                   1188:                        o_lport = getpinfo(optarg, 0);
1.6       deraadt  1189:                        if (o_lport == 0)
1.13      ericj    1190:                                nlog(1, "invalid local port %s", optarg);
1.6       deraadt  1191:                        break;
1.11      ericj    1192:                case 'r':                       /* randomize various things */
1.6       deraadt  1193:                        o_random++;
                   1194:                        break;
1.11      ericj    1195:                /*
                   1196:                 * Do a full lookup [since everything else goes through the same
                   1197:                 * mill], unless -n was previously specified. In fact, careful
                   1198:                 * placement of -n can be useful, so we'll still pass o_nflag
                   1199:                 * here instead of forcing numeric.
                   1200:                 */
                   1201:                case 's':                       /* local source address */
                   1202:                        wherefrom = gethinfo(optarg, o_nflag);
1.6       deraadt  1203:                        ouraddr = &wherefrom->iaddrs[0];
                   1204:                        break;
1.1       deraadt  1205: #ifdef TELNET
1.11      ericj    1206:                case 't':                       /* do telnet fakeout */
1.6       deraadt  1207:                        o_tn++;
                   1208:                        break;
1.11      ericj    1209: #endif
                   1210:                case 'u':                       /* use UDP */
1.6       deraadt  1211:                        o_udpmode++;
                   1212:                        break;
1.11      ericj    1213:                case 'v':                       /* verbose */
1.6       deraadt  1214:                        o_verbose++;
                   1215:                        break;
1.11      ericj    1216:                case 'w':                       /* wait time */
1.6       deraadt  1217:                        o_wait = atoi(optarg);
                   1218:                        if (o_wait <= 0)
1.13      ericj    1219:                                nlog(1, "invalid wait-time %s", optarg);
1.7       deraadt  1220:                        timer1.tv_sec = o_wait;
                   1221:                        timer1.tv_usec = 0;
1.6       deraadt  1222:                        break;
1.11      ericj    1223:                case 'z':                       /* little or no data xfer */
1.6       deraadt  1224:                        o_zero++;
                   1225:                        break;
                   1226:                default:
1.11      ericj    1227:                        usage(1);
                   1228:                }
                   1229:        }
1.1       deraadt  1230:
1.11      ericj    1231:        /* other misc initialization */
1.7       deraadt  1232:            FD_SET(0, &fds1);   /* stdin *is* initially open */
1.6       deraadt  1233:        if (o_random) {
1.11      ericj    1234:                randports = calloc(1, 65536);   /* big flag array for ports */
1.6       deraadt  1235:        }
                   1236:        if (o_wfile) {
                   1237:                ofd = open(stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
                   1238:                if (ofd <= 0)   /* must be > extant 0/1/2 */
1.13      ericj    1239:                        nlog(1, "Can't open %s", stage);
1.7       deraadt  1240:                stage = (unsigned char *) calloc(1, 100);
1.6       deraadt  1241:        }
1.11      ericj    1242:        /* optind is now index of first non -x arg */
                   1243:        if (argv[optind])
                   1244:                whereto = gethinfo(argv[optind], o_nflag);
1.6       deraadt  1245:        if (whereto && whereto->iaddrs)
                   1246:                themaddr = &whereto->iaddrs[0];
                   1247:        if (themaddr)
                   1248:                optind++;       /* skip past valid host lookup */
                   1249:        errno = 0;
1.1       deraadt  1250:
1.11      ericj    1251:        /*
                   1252:         * Handle listen mode here, and exit afterward.  Only does one connect;
                   1253:         * this is arguably the right thing to do.  A "persistent listen-and-fork"
                   1254:         * mode a la inetd has been thought about, but not implemented.  A tiny
                   1255:         * wrapper script can handle such things.
                   1256:         */
1.6       deraadt  1257:        if (o_listen) {
1.11      ericj    1258:                curport = 0;
                   1259:                if (argv[optind]) {
                   1260:                        curport = getpinfo(argv[optind], 0);
                   1261:                        if (curport == 0)
1.13      ericj    1262:                                nlog(1, "invalid port %s", argv[optind]);
1.11      ericj    1263:                }
1.6       deraadt  1264:                netfd = dolisten(themaddr, curport, ouraddr, o_lport);
                   1265:                if (netfd > 0) {
1.11      ericj    1266:                        x = readwrite(netfd);
1.12      ericj    1267:                        if (o_verbose)
1.13      ericj    1268:                                nlog(0, "Sent %i Rcvd %i", wrote_net, wrote_out);
1.11      ericj    1269:                        exit(x);
                   1270:                } else
1.13      ericj    1271:                        nlog(1, "no connection");
1.11      ericj    1272:        }
1.6       deraadt  1273:        /* fall thru to outbound connects.  Now we're more picky about args... */
                   1274:        if (!themaddr)
1.13      ericj    1275:                nlog(1, "no destination");
1.6       deraadt  1276:        if (argv[optind] == NULL)
1.13      ericj    1277:                nlog(1, "no port[s] to connect to");
1.11      ericj    1278:        if (argv[optind + 1])
                   1279:                Single = 0;
                   1280:        ourport = o_lport;
                   1281:
1.6       deraadt  1282:        while (argv[optind]) {
                   1283:                hiport = loport = 0;
1.11      ericj    1284:                cp = strchr(argv[optind], '-');
1.6       deraadt  1285:                if (cp) {
                   1286:                        *cp = '\0';
                   1287:                        cp++;
1.11      ericj    1288:                        hiport = getpinfo(cp, 0);
1.6       deraadt  1289:                        if (hiport == 0)
1.13      ericj    1290:                                nlog(1, "invalid port %s", cp);
1.6       deraadt  1291:                }               /* if found a dash */
1.11      ericj    1292:                loport = getpinfo(argv[optind], 0);
1.6       deraadt  1293:                if (loport == 0)
1.13      ericj    1294:                        nlog(1, "invalid port %s", argv[optind]);
1.16    ! ericj    1295:                if (hiport > loport) {
        !          1296:                        Single = 0;
        !          1297:                        if (o_random) {
1.6       deraadt  1298:                                loadports(randports, loport, hiport);
                   1299:                                curport = nextport(randports);
1.11      ericj    1300:                        } else
                   1301:                                curport = hiport;
1.6       deraadt  1302:                } else          /* not a range, including args like "25-25" */
                   1303:                        curport = loport;
1.11      ericj    1304:                    /*
                   1305:                     * Now start connecting to these things.
                   1306:                     * curport is already preloaded.
                   1307:                     */
1.6       deraadt  1308:                    while (loport <= curport) {
1.11      ericj    1309:                        curport = getpinfo(NULL, curport);
1.6       deraadt  1310:                        netfd = doconnect(themaddr, curport, ouraddr, ourport);
1.11      ericj    1311:                        if (netfd > 0)
                   1312:                                if (o_zero && o_udpmode)
1.6       deraadt  1313:                                        netfd = udptest(netfd, themaddr);
1.11      ericj    1314:                        if (netfd > 0) {
                   1315:                                x = 0;
                   1316:                                if (o_verbose) {
1.13      ericj    1317:                                        nlog(0, "%s [%s] %d (%s) open",
1.11      ericj    1318:                                                whereto->name,
                   1319:                                                whereto->addrs[0], curport,
                   1320:                                                pinfo->name);
                   1321:                                }
1.6       deraadt  1322:                                if (!o_zero)
1.11      ericj    1323:                                        x = readwrite(netfd);
                   1324:                        } else {
                   1325:                                x = 1;
                   1326:                                if ((Single || (o_verbose > 1))
                   1327:                                   || (errno != ECONNREFUSED)) {
1.13      ericj    1328:                                        nlog(0, "%s [%s] %d (%s)",
                   1329:                                             whereto->name, whereto->addrs[0],
                   1330:                                             curport, pinfo->name);
1.11      ericj    1331:                                }
                   1332:                        }
                   1333:                        close(netfd);
1.6       deraadt  1334:                        if (o_interval)
1.11      ericj    1335:                                sleep(o_interval);
1.6       deraadt  1336:                        if (o_random)
                   1337:                                curport = nextport(randports);
                   1338:                        else
1.11      ericj    1339:                                curport--;
                   1340:                }
1.6       deraadt  1341:                optind++;
1.11      ericj    1342:        }
1.6       deraadt  1343:
                   1344:        errno = 0;
1.13      ericj    1345:        nlog(0, "Sent %i Rcvd %i", wrote_net, wrote_out);
1.6       deraadt  1346:        if (Single)
1.11      ericj    1347:                exit(x);
                   1348:        exit(0);
1.13      ericj    1349: }
                   1350:
                   1351: /*
                   1352:  * nlog:
                   1353:  * dual purpose function, does both warn() and err()
                   1354:  * and pays attention to o_verbose.
                   1355:  */
                   1356: void
                   1357: nlog(doexit, fmt)
1.14      ericj    1358:        char *fmt;
1.13      ericj    1359: {
1.14      ericj    1360:        va_list args;
1.13      ericj    1361:
1.14      ericj    1362:        if (o_verbose || doexit) {
                   1363:                va_start(args, fmt);
                   1364:                vfprintf(stderr, fmt, args);
                   1365:                if (h_errno)
1.13      ericj    1366:                         herror(NULL);
1.14      ericj    1367:                else
                   1368:                        putc('\n', stderr);
1.16    ! ericj    1369:                va_end(args);
1.14      ericj    1370:        }
1.13      ericj    1371:
1.14      ericj    1372:        if (doexit)
                   1373:                exit(1);
1.7       deraadt  1374: }
1.1       deraadt  1375:
1.11      ericj    1376: void
                   1377: usage(doexit)
1.1       deraadt  1378: {
1.11      ericj    1379:        fprintf(stderr, "netcat - [v1.10]\n");
                   1380:        fprintf(stderr, "nc [-lnrtuvz] [-e command] [-g intermediates]\n");
                   1381:        fprintf(stderr, "   [-G hopcount] [-i interval] [-o filename] [-p source port]\n");
                   1382:        fprintf(stderr, "   [-s ip address] [-w timeout] [hostname] [port[s...]]\n");
                   1383:        if (doexit)
                   1384:                exit(1);
                   1385: }
                   1386:
                   1387: void
                   1388: help()
                   1389: {
                   1390:        usage(0);
                   1391:        fprintf(stderr, "\tCommand Summary:\n\
                   1392:         \t-g gateway   source-routing hop point[s], up to 8\n\
                   1393:         \t-G num\t     source-routing pointer: 4, 8, 12, ...\n\
                   1394:         \t-h           this help text\n\
                   1395:         \t-i secs\t    delay interval for lines sent, ports scanned\n\
                   1396:         \t-l           listen mode, for inbound connects\n\
                   1397:         \t-n           numeric-only IP addresses, no DNS\n\
                   1398:         \t-o file\t    hex dump of traffic\n\
                   1399:         \t-r           randomize local and remote ports\n\
                   1400:         \t-s addr\t    local source address\n");
1.1       deraadt  1401: #ifdef TELNET
1.11      ericj    1402:         fprintf(stderr, "\t\t-t                answer TELNET negotiation\n");
1.1       deraadt  1403: #endif
1.11      ericj    1404:         fprintf(stderr, "\t\t-u                UDP mode\n\
                   1405:         \t-v           verbose [use twice to be more verbose]\n\
                   1406:         \t-w secs\t    timeout for connects and final net reads\n\
                   1407:         \t-z           zero-I/O mode [used for scanning]\n\
                   1408:         Port numbers can be individual or ranges: lo-hi [inclusive]\n");
                   1409:        exit(1);
1.7       deraadt  1410: }