netcat-win86

Netcat prebuilt executable for Windows machines
git clone https://s.sonu.ch/~srket/netcat-win86.git
Log | Files | Refs | LICENSE

netcat.c (67756B)


      1 // for license see license.txt
      2 
      3 /* Netcat 1.00 951010
      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 	main:
     22 
     23   todo:
     24 	more of the portability swamp, and an updated generic.h
     25 	frontend progs to generate various packets, raw or otherwise...
     26 	char-mode [cbreak, fcntl-unbuffered, etc...]
     27 	connect-to-all-A-records hack
     28   bluesky:
     29 	RAW mode!
     30 	backend progs to grab a pty and look like a real telnetd?!
     31 */
     32 
     33 #include "generic.h"		/* same as with L5, skey, etc */
     34 
     35 #ifdef WIN32
     36 #pragma comment (lib, "ws2_32") /* winsock support */
     37 #endif
     38 
     39 /* conditional includes -- a very messy section: */
     40 /* #undef _POSIX_SOURCE		/* might need this for something? */
     41 #define HAVE_BIND		/* XXX -- for now, see below... */
     42 #define HAVE_HELP		/* undefine if you dont want the help text */
     43 /* #define ANAL			/* if you want case-sensitive DNS matching */
     44 #ifdef HAVE_STDLIB_H
     45 #include <stdlib.h>
     46 #else
     47 #include <malloc.h>		/* xxx: or does it live in sys/ ?? */
     48 #endif
     49 
     50 /* have to do this *before* including types.h. xxx: Linux still has it wrong */
     51 #ifdef FD_SETSIZE		/* should be in types.h, butcha never know. */
     52 #undef FD_SETSIZE		/* if we ever need more than 16 active */
     53 #endif				/* fd's, something is horribly wrong! */
     54 #ifdef WIN32
     55 #define FD_SETSIZE 64		/* WIN32 does this as an array not a bitfield and it likes 64 */
     56 #else
     57 #define FD_SETSIZE 16		/* <-- this'll give us a long anyways, wtf */
     58 #endif
     59 #include <sys/types.h>		/* *now* do it.  Sigh, this is broken */
     60 
     61 
     62 #ifdef WIN32
     63 #undef HAVE_RANDOM
     64 #undef IP_OPTIONS
     65 #undef SO_REUSEPORT
     66 #include <windows.h>
     67 #endif
     68 
     69 
     70 #ifdef HAVE_RANDOM
     71 #define SRAND srandom
     72 #define RAND random
     73 #else
     74 #define SRAND srand
     75 #define RAND rand
     76 #endif /* HAVE_RANDOM */
     77 
     78 /* xxx: these are rsh leftovers, move to new generic.h */
     79 /* will we even need any nonblocking shit?  Doubt it. */
     80 /* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
     81 /* #include <sys/filio.h> */
     82 /*
     83 #include <sys/ioctl.h>
     84 #include <sys/file.h>
     85 */
     86 
     87 /* includes: */
     88 
     89 #ifdef WIN32
     90 #include "getopt.h"
     91 #define sleep			_sleep
     92 #define strcasecmp		strcmpi
     93 #define EADDRINUSE		WSAEADDRINUSE
     94 #define ETIMEDOUT		WSAETIMEDOUT
     95 #define ECONNREFUSED	WSAECONNREFUSED
     96 #endif
     97 
     98 #ifndef WIN32
     99 #include <sys/time.h>		/* timeval, time_t */
    100 #else
    101 #include <time.h>
    102 #endif
    103 
    104 #include <setjmp.h>		/* jmp_buf et al */
    105 
    106 #ifndef WIN32
    107 #include <sys/socket.h>		/* basics, SO_ and AF_ defs, sockaddr, ... */
    108 #include <netinet/in.h>		/* sockaddr_in, htons, in_addr */
    109 #include <netinet/in_systm.h>	/* misc crud that netinet/ip.h references */
    110 #include <netinet/ip.h>		/* IPOPT_LSRR, header stuff */
    111 #include <netdb.h>		/* hostent, gethostby*, getservby* */
    112 #include <arpa/inet.h>		/* inet_ntoa */
    113 #else
    114 #include <fcntl.h>
    115 #include <io.h>
    116 #include <conio.h>
    117 //#include <winsock2.h>
    118 #endif
    119 
    120 #include <stdio.h>
    121 #include <string.h>		/* strcpy, strchr, yadda yadda */
    122 #include <errno.h>
    123 #include <signal.h>
    124 
    125 /* handy stuff: */
    126 #define SA struct sockaddr	/* socket overgeneralization braindeath */
    127 #define SAI struct sockaddr_in	/* ... whoever came up with this model */
    128 #define IA struct in_addr	/* ... should be taken out and shot, */
    129 				/* ... not that TLI is any better.  sigh.. */
    130 #define SLEAZE_PORT 31337	/* for UDP-scan RTT trick, change if ya want */
    131 #define USHORT unsigned short	/* use these for options an' stuff */
    132 #define BIGSIZ 8192		/* big buffers */
    133 #define SMALLSIZ 256		/* small buffers, hostnames, etc */
    134 
    135 #ifndef INADDR_NONE
    136 #define INADDR_NONE 0xffffffff
    137 #endif
    138 #ifdef MAXHOSTNAMELEN
    139 #undef MAXHOSTNAMELEN		/* might be too small on aix, so fix it */
    140 #endif
    141 #define MAXHOSTNAMELEN 256
    142 struct host_poop {
    143   char name[MAXHOSTNAMELEN];	/* dns name */
    144   char addrs[8][24];		/* ascii-format IP addresses */
    145   struct in_addr iaddrs[8];	/* real addresses: in_addr.s_addr: ulong */
    146 };
    147 #define HINF struct host_poop
    148 struct port_poop {
    149   char name [64];		/* name in /etc/services */
    150   char anum [8];		/* ascii-format number */
    151   USHORT num;			/* real host-order number */
    152 };
    153 #define PINF struct port_poop
    154 
    155 /* globals: */
    156 jmp_buf jbuf;			/* timer crud */
    157 int jval = 0;			/* timer crud */
    158 int netfd = -1;
    159 int ofd = 0;			/* hexdump output fd */
    160 static char unknown[] = "(UNKNOWN)";
    161 static char p_tcp[] = "tcp";	/* for getservby* */
    162 static char p_udp[] = "udp";
    163 
    164 #ifndef WIN32
    165 #ifdef HAVE_BIND
    166 extern int h_errno;
    167 #endif
    168 #endif
    169 int gatesidx = 0;		/* LSRR hop count */
    170 int gatesptr = 4;		/* initial LSRR pointer, settable */
    171 USHORT Single = 1;		/* zero if scanning */
    172 unsigned int insaved = 0;	/* stdin-buffer size for multi-mode */
    173 unsigned int wrote_out = 0;	/* total stdout bytes */
    174 unsigned int wrote_net = 0;	/* total net bytes */
    175 static char wrote_txt[] = " sent %d, rcvd %d";
    176 static char hexnibs[20] = "0123456789abcdef  ";
    177 
    178 /* will malloc up the following globals: */
    179 struct timeval * timer1 = NULL;
    180 struct timeval * timer2 = NULL;
    181 SAI * lclend = NULL;		/* sockaddr_in structs */
    182 SAI * remend = NULL;
    183 HINF ** gates = NULL;		/* LSRR hop hostpoop */
    184 char * optbuf = NULL;		/* LSRR or sockopts */
    185 char * bigbuf_in;		/* data buffers */
    186 char * bigbuf_net;
    187 fd_set * ding1;			/* for select loop */
    188 fd_set * ding2;
    189 PINF * portpoop = NULL;		/* for getportpoop / getservby* */
    190 unsigned char * stage = NULL;	/* hexdump line buffer */
    191 
    192 #ifdef WIN32
    193   char * setsockopt_c;
    194 int nnetfd;
    195 #endif
    196 
    197 /* global cmd flags: */
    198 USHORT o_alla = 0;
    199 unsigned int o_interval = 0;
    200 USHORT o_listen = 0;
    201 USHORT o_nflag = 0;
    202 USHORT o_wfile = 0;
    203 USHORT o_random = 0;
    204 USHORT o_udpmode = 0;
    205 USHORT o_verbose = 0;
    206 unsigned int o_wait = 0;
    207 USHORT o_zero = 0;
    208 USHORT o_crlf = 0;
    209 
    210 /* Debug macro: squirt whatever to stderr and sleep a bit so we can see it go
    211    by.  need to call like Debug ((stuff)) [with no ; ] so macro args match!
    212    Beware: writes to stdOUT... */
    213 #ifdef DEBUG
    214 #define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
    215 #else
    216 #define Debug(x)	/* nil... */
    217 #endif
    218 
    219 /* support routines -- the bulk of this thing.  Placed in such an order that
    220    we don't have to forward-declare anything: */
    221 
    222 int helpme(); /* oop */
    223 
    224 #ifdef WIN32
    225 
    226 /* res_init
    227    winsock needs to be initialized. Might as well do it as the res_init
    228    call for Win32 */
    229 
    230 void res_init()
    231 {
    232 WORD wVersionRequested; 
    233 WSADATA wsaData; 
    234 int err; 
    235 wVersionRequested = MAKEWORD(1, 1); 
    236  
    237 err = WSAStartup(wVersionRequested, &wsaData); 
    238  
    239 if (err != 0) 
    240     /* Tell the user that we couldn't find a useable */ 
    241     /* winsock.dll.     */ 
    242     return; 
    243  
    244 /* Confirm that the Windows Sockets DLL supports 1.1.*/ 
    245 /* Note that if the DLL supports versions greater */ 
    246 /* than 1.1 in addition to 1.1, it will still return */ 
    247 /* 1.1 in wVersion since that is the version we */ 
    248 /* requested. */ 
    249  
    250 if ( LOBYTE( wsaData.wVersion ) != 1 || 
    251         HIBYTE( wsaData.wVersion ) != 1 ) { 
    252     /* Tell the user that we couldn't find a useable */ 
    253     /* winsock.dll. */ 
    254     WSACleanup(); 
    255     return; 
    256     }
    257  
    258 }
    259 
    260 
    261 
    262 
    263 /* winsockstr
    264    Windows Sockets cannot report errors through perror() so we need to define
    265    our own error strings to print. Someday all the string should be prettied up.
    266    Prettied the errors I usually get */
    267 char * winsockstr(error)
    268 int error;
    269 {
    270 	switch (error)
    271 	{
    272 	case WSAEINTR          : return("INTR          ");
    273 	case WSAEBADF          : return("BADF          ");
    274 	case WSAEACCES         : return("ACCES         ");
    275 	case WSAEFAULT         : return("FAULT         ");
    276 	case WSAEINVAL         : return("INVAL         ");
    277 	case WSAEMFILE         : return("MFILE         ");
    278 	case WSAEWOULDBLOCK    : return("WOULDBLOCK    ");
    279 	case WSAEINPROGRESS    : return("INPROGRESS    ");
    280 	case WSAEALREADY       : return("ALREADY       ");
    281 	case WSAENOTSOCK       : return("NOTSOCK       ");
    282 	case WSAEDESTADDRREQ   : return("DESTADDRREQ   ");
    283 	case WSAEMSGSIZE       : return("MSGSIZE       ");
    284 	case WSAEPROTOTYPE     : return("PROTOTYPE     ");
    285 	case WSAENOPROTOOPT    : return("NOPROTOOPT    ");
    286 	case WSAEPROTONOSUPPORT: return("PROTONOSUPPORT");
    287 	case WSAESOCKTNOSUPPORT: return("SOCKTNOSUPPORT");
    288 	case WSAEOPNOTSUPP     : return("OPNOTSUPP     ");
    289 	case WSAEPFNOSUPPORT   : return("PFNOSUPPORT   ");
    290 	case WSAEAFNOSUPPORT   : return("AFNOSUPPORT   ");
    291 	case WSAEADDRINUSE     : return("ADDRINUSE     ");
    292 	case WSAEADDRNOTAVAIL  : return("ADDRNOTAVAIL  ");
    293 	case WSAENETDOWN       : return("NETDOWN       ");
    294 	case WSAENETUNREACH    : return("NETUNREACH    ");
    295 	case WSAENETRESET      : return("NETRESET      ");
    296 	case WSAECONNABORTED   : return("CONNABORTED   ");
    297 	case WSAECONNRESET     : return("CONNRESET     ");
    298 	case WSAENOBUFS        : return("NOBUFS        ");
    299 	case WSAEISCONN        : return("ISCONN        ");
    300 	case WSAENOTCONN       : return("NOTCONN       ");
    301 	case WSAESHUTDOWN      : return("SHUTDOWN      ");
    302 	case WSAETOOMANYREFS   : return("TOOMANYREFS   ");
    303 	case WSAETIMEDOUT      : return("TIMEDOUT      ");
    304 	case WSAECONNREFUSED   : return("connection refused");
    305 	case WSAELOOP          : return("LOOP          ");
    306 	case WSAENAMETOOLONG   : return("NAMETOOLONG   ");
    307 	case WSAEHOSTDOWN      : return("HOSTDOWN      ");
    308 	case WSAEHOSTUNREACH   : return("HOSTUNREACH   ");
    309 	case WSAENOTEMPTY      : return("NOTEMPTY      ");
    310 	case WSAEPROCLIM       : return("PROCLIM       ");
    311 	case WSAEUSERS         : return("USERS         ");
    312 	case WSAEDQUOT         : return("DQUOT         ");
    313 	case WSAESTALE         : return("STALE         ");
    314 	case WSAEREMOTE        : return("REMOTE        ");
    315 	case WSAEDISCON        : return("DISCON        ");
    316 	case WSASYSNOTREADY    : return("SYSNOTREADY    ");
    317 	case WSAVERNOTSUPPORTED: return("VERNOTSUPPORTED");
    318 	case WSANOTINITIALISED : return("NOTINITIALISED ");
    319 	case WSAHOST_NOT_FOUND : return("HOST_NOT_FOUND ");
    320 	case WSATRY_AGAIN      : return("TRY_AGAIN      ");
    321 	case WSANO_RECOVERY    : return("NO_RECOVERY    ");
    322 	case WSANO_DATA        : return("NO_DATA        ");
    323 	default : return("unknown socket error");
    324 	}
    325 }
    326 #endif
    327 
    328 
    329 
    330 
    331 
    332 /* holler :
    333    fake varargs -- need to do this way because we wind up calling through
    334    more levels of indirection than vanilla varargs can handle, and not all
    335    machines have vfprintf/vsyslog/whatever!  6 params oughta be enough. */
    336 void holler (str, p1, p2, p3, p4, p5, p6)
    337   char * str;
    338   char * p1, * p2, * p3, * p4, * p5, * p6;
    339 {
    340   if (o_verbose) {
    341     fprintf (stderr, str, p1, p2, p3, p4, p5, p6);
    342 #ifdef WIN32
    343 	if (h_errno)
    344 		fprintf (stderr, ": %s\n",winsockstr(h_errno));
    345 #else
    346     if (errno) {		/* this gives funny-looking messages, but */
    347       perror (" ");		/* it's more portable than sys_errlist[]... */
    348     }				/* xxx: do something better.  */
    349 #endif
    350 	else
    351       fprintf (stderr, "\n");
    352     fflush (stderr);
    353   }
    354 } /* holler */
    355 
    356 /* bail :
    357    error-exit handler, callable from anywhere */
    358 void bail (str, p1, p2, p3, p4, p5, p6)
    359   char * str;
    360   char * p1, * p2, * p3, * p4, * p5, * p6;
    361 {
    362   o_verbose = 1;
    363   holler (str, p1, p2, p3, p4, p5, p6);
    364 #ifdef WIN32
    365   shutdown(netfd, 0x02);  /* Kirby */
    366   closesocket (netfd);
    367 #else
    368   close (netfd);
    369 #endif
    370   sleep (1);
    371   exit (1);
    372 } /* bail */
    373 
    374 /* catch :
    375    no-brainer interrupt handler */
    376 void catch ()
    377 {
    378   errno = 0;
    379    if (o_verbose > 1)		/* normally we don't care */
    380     bail (wrote_txt, wrote_net, wrote_out);
    381 
    382   bail (" punt!");
    383 }
    384 
    385 /* timeout and other signal handling cruft */
    386 void tmtravel ()
    387 {
    388 #ifdef NTFIXTHIS
    389   signal (SIGALRM, SIG_IGN);
    390   alarm (0);
    391 #endif
    392   if (jval == 0)
    393     bail ("spurious timer interrupt!");
    394   longjmp (jbuf, jval);
    395 }
    396 
    397 
    398 
    399 UINT theTimer;
    400 
    401 /* arm :
    402    set the timer.  Zero secs arg means unarm  */
    403 void arm (num, secs)
    404   unsigned int num;
    405   unsigned int secs;
    406 {
    407 
    408 #ifdef WIN32
    409 	HANDLE stdhnd;
    410 	stdhnd = GetStdHandle(STD_OUTPUT_HANDLE);
    411 #ifdef DEBUG
    412 	if (stdhnd != INVALID_HANDLE_VALUE)
    413 		printf("handle is %ld\n", stdhnd);
    414 	else
    415 		printf("failed to get stdhndl\n");
    416 #endif
    417 #else
    418 if (secs == 0) {			/* reset */
    419 	signal (SIGALRM, SIG_IGN);
    420     alarm (0);
    421     jval = 0;
    422   } else {				/* set */
    423     signal (SIGALRM, tmtravel);
    424     alarm (secs);
    425     jval = num;
    426   } /* if secs */
    427 #endif /* WIN32 */
    428 } /* arm */
    429 
    430 /* Hmalloc :
    431    malloc up what I want, rounded up to *4, and pre-zeroed.  Either succeeds
    432    or bails out on its own, so that callers don't have to worry about it. */
    433 char * Hmalloc (size)
    434   unsigned int size;
    435 {
    436   unsigned int s = (size + 4) & 0xfffffffc;	/* 4GB?! */
    437   char * p = malloc (s);
    438   if (p != NULL)
    439     memset (p, 0, s);
    440   else
    441     bail ("Hmalloc %d failed", s);
    442   return (p);
    443 } /* Hmalloc */
    444 
    445 /* findline :
    446    find the next newline in a buffer; return inclusive size of that "line",
    447    or the entire buffer size, so the caller knows how much to then write().
    448    Not distinguishing \n vs \r\n for the nonce; it just works as is... */
    449 unsigned int findline (buf, siz)
    450   char * buf;
    451   unsigned int siz;
    452 {
    453   register char * p;
    454   register int x;
    455   if (! buf)			/* various sanity checks... */
    456     return (0);
    457   if (siz > BIGSIZ)
    458     return (0);
    459   x = siz;
    460   for (p = buf; x > 0; x--) {
    461     if (*p == '\n') {
    462       x = (int) (p - buf);
    463       x++;			/* 'sokay if it points just past the end! */
    464 Debug (("findline returning %d", x))
    465       return (x);
    466     }
    467     p++;
    468   } /* for */
    469 Debug (("findline returning whole thing: %d", siz))
    470   return (siz);
    471 } /* findline */
    472 
    473 /* comparehosts :
    474    cross-check the host_poop we have so far against new gethostby*() info,
    475    and holler about mismatches.  Perhaps gratuitous, but it can't hurt to
    476    point out when someone's DNS is fukt.  Returns 1 if mismatch, in case
    477    someone else wants to do something about it. */
    478 int comparehosts (poop, hp)
    479   HINF * poop;
    480   struct hostent * hp;
    481 {
    482   errno = 0;
    483 #ifndef WIN32
    484   h_errno = 0;
    485 #endif
    486 /* The DNS spec is officially case-insensitive, but for those times when you
    487    *really* wanna see any and all discrepancies, by all means define this. */
    488 #ifdef ANAL			
    489   if (strcmp (poop->name, hp->h_name) != 0) {		/* case-sensitive */
    490 #else
    491   if (strcasecmp (poop->name, hp->h_name) != 0) {	/* normal */
    492 #endif
    493     holler ("DNS fwd/rev mismatch: %s != %s", poop->name, hp->h_name);
    494     return (1);
    495   }
    496   return (0);
    497 /* ... do we need to do anything over and above that?? */
    498 } /* comparehosts */
    499 
    500 /* gethostpoop :
    501    resolve a host 8 ways from sunday; return a new host_poop struct with its
    502    info.  The argument can be a name or [ascii] IP address; it will try its
    503    damndest to deal with it.  "numeric" governs whether we do any DNS at all,
    504    and we also check o_verbose for what's appropriate work to do. */
    505 HINF * gethostpoop (name, numeric)
    506   char * name;
    507   USHORT numeric;
    508 {
    509   struct hostent * hostent;
    510   struct in_addr iaddr;
    511   register HINF * poop = NULL;
    512   register int x;
    513 
    514 /* I really want to strangle the twit who dreamed up all these sockaddr and
    515    hostent abstractions, and then forced them all to be incompatible with
    516    each other so you *HAVE* to do all this ridiculous casting back and forth.
    517    If that wasn't bad enough, all the doc insists on referring to local ports
    518    and addresses as "names", which makes NO sense down at the bare metal.
    519 
    520    What an absolutely horrid paradigm, and to think of all the people who
    521    have been wasting significant amounts of time fighting with this stupid
    522    deliberate obfuscation over the last 10 years... then again, I like
    523    languages wherein a pointer is a pointer, what you put there is your own
    524    business, the compiler stays out of your face, and sheep are nervous.
    525    Maybe that's why my C code reads like assembler half the time... */
    526 
    527 /* If we want to see all the DNS stuff, do the following hair --
    528    if inet_addr, do reverse and forward with any warnings; otherwise try
    529    to do forward and reverse with any warnings.  In other words, as long
    530    as we're here, do a complete DNS check on these clowns.  Yes, it slows
    531    things down a bit for a first run, but once it's cached, who cares? */
    532 
    533   errno = 0;
    534 #ifndef WIN32
    535   h_errno = 0;
    536 #endif
    537   if (name)
    538     poop = (HINF *) Hmalloc (sizeof (HINF));
    539   if (! poop)
    540     bail ("gethostpoop fuxored");
    541   strcpy (poop->name, unknown);		/* preload it */
    542 /* see wzv:workarounds.c for dg/ux return-a-struct inet_addr lossage */
    543   iaddr.s_addr = inet_addr (name);
    544 
    545   if (iaddr.s_addr == INADDR_NONE) {	/* here's the great split: names... */
    546     if (numeric)
    547       bail ("Can't parse %s as an IP address", name);
    548     hostent = gethostbyname (name);
    549     if (! hostent)
    550 /* failure to look up a name is fatal, since we can't do anything with it */
    551 /* XXX: h_errno only if BIND?  look up how telnet deals with this */
    552       bail ("%s: forward host lookup failed: h_errno %d", name, h_errno);
    553     strncpy (poop->name, hostent->h_name, sizeof (poop->name));
    554     for (x = 0; hostent->h_addr_list[x] && (x < 8); x++) {
    555       memcpy (&poop->iaddrs[x], hostent->h_addr_list[x], sizeof (IA));
    556       strncpy (poop->addrs[x], inet_ntoa (poop->iaddrs[x]),
    557 	sizeof (poop->addrs[0]));
    558     } /* for x -> addrs, part A */
    559     if (! o_verbose)			/* if we didn't want to see the */
    560       return (poop);			/* inverse stuff, we're done. */
    561 /* do inverse lookups in separate loop based on our collected forward addrs,
    562    since gethostby* tends to crap into the same buffer over and over */
    563     for (x = 0; poop->iaddrs[x].s_addr && (x < 8); x++) {
    564       hostent = gethostbyaddr ((char *)&poop->iaddrs[x],
    565 				sizeof (IA), AF_INET);
    566       if ((! hostent) || (! hostent-> h_name))
    567 	holler ("Warning: inverse host lookup failed for %s: h_errno %d",
    568 	  poop->addrs[x], h_errno);
    569       else
    570 	(void) comparehosts (poop, hostent);
    571     } /* for x -> addrs, part B */
    572 
    573   } else {			/* not INADDR_NONE: numeric addresses... */
    574     memcpy (poop->iaddrs, &iaddr, sizeof (IA));
    575     strncpy (poop->addrs[0], inet_ntoa (iaddr), sizeof (poop->addrs));
    576     if (numeric)			/* if numeric-only, we're done */
    577       return (poop);
    578     if (! o_verbose)			/* likewise if we don't want */
    579       return (poop);			/* the full DNS hair */
    580     hostent = gethostbyaddr ((char *) &iaddr, sizeof (IA), AF_INET);
    581 /* numeric or not, failure to look up a PTR is *not* considered fatal */
    582     if (! hostent)
    583 	holler ("%s: inverse host lookup failed: h_errno %d", name, h_errno);
    584     else {
    585 	strncpy (poop->name, hostent->h_name, MAXHOSTNAMELEN - 2);
    586 	hostent = gethostbyname (poop->name);
    587 	if ((! hostent) || (! hostent->h_addr_list[0]))
    588 	  holler ("Warning: forward host lookup failed for %s: h_errno %d",
    589 		poop->name, h_errno);
    590 	else
    591 	  (void) comparehosts (poop, hostent);
    592     } /* if hostent */
    593   } /* INADDR_NONE Great Split */
    594 
    595 /* whatever-all went down previously, we should now have a host_poop struct
    596    with at least one IP address in it. */
    597 #ifndef WIN32
    598   h_errno = 0;
    599 #endif
    600   return (poop);
    601 } /* gethostpoop */
    602 
    603 /* getportpoop :
    604    Same general idea as gethostpoop -- look up a port in /etc/services, fill
    605    in global port_poop, but return the actual port *number*.  Pass ONE of:
    606 	pstring to resolve stuff like "23" or "exec";
    607 	pnum to reverse-resolve something that's already a number.
    608    If o_nflag is on, fill in what we can but skip the getservby??? stuff.
    609    Might as well have consistent behavior here... */
    610 USHORT getportpoop (pstring, pnum)
    611   char * pstring;
    612   unsigned int pnum;
    613 {
    614   struct servent * servent;
    615 #ifndef WIN32
    616   register int x;
    617   register int y;
    618 #else
    619   u_short x;
    620   u_short y;
    621 #endif
    622   char * whichp = p_tcp;
    623   if (o_udpmode)
    624     whichp = p_udp;
    625   portpoop->name[0] = '?';		/* fast preload */
    626   portpoop->name[1] = '\0';
    627 
    628 /* case 1: reverse-lookup of a number; placed first since this case is much
    629    more frequent if we're scanning */
    630   if (pnum) {
    631     if (pstring)			/* one or the other, pleeze */
    632       return (0);
    633     x = pnum;
    634     if (o_nflag)			/* go faster, skip getservbyblah */
    635       goto gp_finish;
    636     y = htons (x);			/* gotta do this -- see Fig.1 below */
    637     servent = getservbyport (y, whichp);
    638     if (servent) {
    639       y = ntohs (servent->s_port);
    640       if (x != y)			/* "never happen" */
    641 	holler ("Warning: port-bynum mismatch, %d != %d", x, y);
    642       strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
    643     } /* if servent */
    644     goto gp_finish;
    645   } /* if pnum */
    646 
    647 /* case 2: resolve a string, but we still give preference to numbers instead
    648    of trying to resolve conflicts.  None of the entries in *my* extensive
    649    /etc/services begins with a digit, so this should "always work" unless
    650    you're at 3com and have some company-internal services defined... */
    651   if (pstring) {
    652     if (pnum)				/* one or the other, pleeze */
    653       return (0);
    654     x = atoi (pstring);
    655     if (x)
    656       return (getportpoop (NULL, x));	/* recurse for numeric-string-arg */
    657     if (o_nflag)			/* can't use names! */
    658       return (0);
    659     servent = getservbyname (pstring, whichp);
    660     if (servent) {
    661       strncpy (portpoop->name, servent->s_name, sizeof (portpoop->name));
    662       x = ntohs (servent->s_port);
    663       goto gp_finish;
    664     } /* if servent */
    665   } /* if pstring */
    666 
    667   return (0);				/* catches any problems so far */
    668 
    669 /* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
    670    Despite this, we still have to treat it as a short when copying it around.
    671    Not only that, but we have to convert it *back* into net order for
    672    getservbyport to work.  Manpages generally aren't clear on all this, but
    673    there are plenty of examples in which it is just quietly done.  More BSD
    674    lossage... since everything getserv* ever deals with is local to our own
    675    host, why bother with all this network-order/host-order crap at all?!
    676    That should be saved for when we want to actually plug the port[s] into
    677    some real network calls -- and guess what, we have to *re*-convert at that
    678    point as well.  Fuckheads. */
    679 
    680 gp_finish:
    681 /* Fall here whether or not we have a valid servent at this point, with
    682    x containing our [host-order and therefore useful, dammit] port number */
    683   sprintf (portpoop->anum, "%d", x);	/* always load any numeric specs! */
    684   portpoop->num = (x & 0xffff);		/* ushort, remember... */
    685   return (portpoop->num);
    686 } /* getportpoop */
    687 
    688 /* nextport :
    689    Come up with the next port to try, be it random or whatever.  "block" is
    690    a ptr to randports array, whose bytes [so far] carry these meanings:
    691 	0	ignore
    692 	1	to be tested
    693 	2	tested [which is set as we find them here]
    694    returns a USHORT random port, or 0 if all the t-b-t ones are used up. */
    695 USHORT nextport (block)
    696   char * block;
    697 {
    698   register unsigned int x;
    699   register unsigned int y;
    700 
    701   y = 70000;			/* high safety count for rnd-tries */
    702   while (y > 0) {
    703     x = (RAND() & 0xffff);
    704     if (block[x] == 1) {	/* try to find a not-done one... */
    705       block[x] = 2;
    706       break;
    707     }
    708     x = 0;			/* bummer. */
    709     y--;
    710   } /* while y */
    711   if (x)
    712     return (x);
    713 
    714   y = 65535;			/* no random one, try linear downsearch */
    715   while (y > 0) {		/* if they're all used, we *must* be sure! */
    716     if (block[y] == 1) {
    717       block[y] = 2;
    718       break;
    719     }
    720     y--;
    721   } /* while y */
    722   if (y)
    723     return (y);			/* at least one left */
    724 
    725   return (0);			/* no more left! */
    726 } /* nextport */
    727 
    728 /* loadports :
    729    set "to be tested" indications in BLOCK, from LO to HI.  Almost too small
    730    to be a separate routine, but makes main() a little cleaner... */
    731 void loadports (block, lo, hi)
    732   char * block;
    733   USHORT lo;
    734   USHORT hi;
    735 {
    736   USHORT x;
    737 
    738   if (! block)
    739     bail ("loadports: no block?!");
    740   if ((! lo) || (! hi))
    741     bail ("loadports: bogus values %d, %d", lo, hi);
    742   x = hi;
    743   while (lo <= x) {
    744     block[x] = 1;
    745     x--;
    746   }
    747 } /* loadports */
    748 
    749 #ifdef GAPING_SECURITY_HOLE
    750 char * pr00gie = NULL;			/* global ptr to -e arg */
    751 #ifdef WIN32
    752 BOOL doexec(SOCKET  ClientSocket);  // this is in doexec.c
    753 #else
    754 
    755 /* doexec :
    756    fiddle all the file descriptors around, and hand off to another prog.  Sort
    757    of like a one-off "poor man's inetd".  This is the only section of code
    758    that would be security-critical, which is why it's ifdefed out by default.
    759    Use at your own hairy risk; if you leave shells lying around behind open
    760    listening ports you deserve to lose!! */
    761 doexec (fd)
    762   int fd;
    763 {
    764   register char * p;
    765 
    766   dup2 (fd, 0);				/* the precise order of fiddlage */
    767 #ifdef WIN32
    768   shutdown(fd, SD_BOTH);  /* Kirby */
    769   closesocket (fd);
    770 #else
    771   close (fd);				/* is apparently crucial; this is */
    772 #endif
    773   dup2 (0, 1);				/* swiped directly out of "inetd". */
    774   dup2 (0, 2);
    775   p = strrchr (pr00gie, '/');		/* shorter argv[0] */
    776   if (p)
    777     p++;
    778   else
    779     p = pr00gie;
    780 Debug (("gonna exec %s as %s...", pr00gie, p))
    781   execl (pr00gie, p, NULL);
    782   bail ("exec %s failed", pr00gie);	/* this gets sent out.  Hmm... */
    783 } /* doexec */
    784 #endif
    785 #endif /* GAPING_SECURITY_HOLE */
    786 
    787 /* doconnect :
    788    do all the socket stuff, and return an fd for one of
    789 	an open outbound TCP connection
    790 	a UDP stub-socket thingie
    791    with appropriate socket options set up if we wanted source-routing, or
    792 	an unconnected TCP or UDP socket to listen on.
    793    Examines various global o_blah flags to figure out what-all to do. */
    794 int doconnect (rad, rp, lad, lp)
    795   IA * rad;
    796   USHORT rp;
    797   IA * lad;
    798   USHORT lp;
    799 {
    800 #ifndef WIN32
    801   register int nnetfd;
    802 #endif
    803   register int rr;
    804   int x, y;
    805 
    806   errno = 0;
    807 #ifdef WIN32
    808 	WSASetLastError(0);
    809 #endif
    810 /* grab a socket; set opts */
    811   if (o_udpmode)
    812     nnetfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    813   else
    814     nnetfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    815   if (nnetfd < 0)
    816     bail ("Can't get socket");
    817   if (nnetfd == 0)		/* might *be* zero if stdin was closed! */
    818     nnetfd = dup (nnetfd);	/* so fix it.  Leave the old 0 hanging. */
    819 #ifdef WIN32
    820   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, (const char FAR *)setsockopt_c, sizeof (setsockopt_c));
    821 #else
    822   x = 1;
    823   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
    824 #endif
    825   if (rr == -1)
    826     holler ("nnetfd reuseaddr failed");		/* ??? */
    827 #ifdef SO_REUSEPORT	/* doesnt exist everywhere... */
    828 #ifdef WIN32
    829   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &c, sizeof (c));
    830 #else
    831   rr = setsockopt (nnetfd, SOL_SOCKET, SO_REUSEPORT, &x, sizeof (x));
    832 #endif
    833   if (rr == -1)
    834     holler ("nnetfd reuseport failed");		/* ??? */
    835 #endif
    836 
    837 /* fill in all the right sockaddr crud */
    838   lclend->sin_family = AF_INET;
    839   remend->sin_family = AF_INET;
    840 
    841 /* if lad/lp, do appropriate binding */
    842   if (lad)
    843     memcpy (&lclend->sin_addr.s_addr, lad, sizeof (IA));
    844   if (lp)
    845     lclend->sin_port = htons (lp);
    846   rr = 0;
    847   if (lad || lp) {
    848     x = (int) lp;
    849 /* try a few times for the local bind, a la ftp-data-port... */
    850     for (y = 4; y > 0; y--) {
    851       rr = bind (nnetfd, (SA *)lclend, sizeof (SA));
    852       if (rr == 0)
    853 	break;
    854       if (errno != EADDRINUSE)
    855 	break;
    856       else {
    857 	holler ("retrying local %s:%d", inet_ntoa (lclend->sin_addr), lp);
    858 	sleep (1);
    859 	errno = 0;			/* clear from sleep */
    860       } /* if EADDRINUSE */
    861     } /* for y counter */
    862   } /* if lad or lp */
    863   if (rr)
    864     bail ("Can't grab %s:%d with bind",
    865 	inet_ntoa(lclend->sin_addr), lp);
    866 
    867   if (o_listen)
    868     return (nnetfd);			/* thanks, that's all for today */
    869 
    870   memcpy (&remend->sin_addr.s_addr, rad, sizeof (IA));
    871   remend->sin_port = htons (rp);
    872 
    873 /* rough format of LSRR option and explanation of weirdness.
    874 -Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5.
    875 -IHL is multiples of 4, i.e. real len = ip_hl << 2.
    876 -	type 131	1	; 0x83: copied, option class 0, number 3
    877 -	len		1	; of *whole* option!
    878 -	pointer		1	; nxt-hop-addr; 1-relative, not 0-relative
    879 -	addrlist...	var	; 4 bytes per hop-addr
    880 -	pad-to-32	var	; ones, i.e. "NOP"
    881 -
    882 -If we want to route A -> B via hops C and D, we must add C, D, *and* B to the
    883 -options list.  Why?  Because when we hand the kernel A -> B with list C, D, B
    884 -the "send shuffle" inside the kernel changes it into A -> C with list D, B and
    885 -the outbound packet gets sent to C.  If B wasn't also in the hops list, the
    886 -final destination would have been lost at this point.
    887 -
    888 -When C gets the packet, it changes it to A -> D with list C', B where C' is
    889 -the interface address that C used to forward the packet.  This "records" the
    890 -route hop from B's point of view, i.e. which address points "toward" B.  This
    891 -is to make B better able to return the packets.  The pointer gets bumped by 4,
    892 -so that D does the right thing instead of trying to forward back to C.
    893 -
    894 -When B finally gets the packet, it sees that the pointer is at the end of the
    895 -LSRR list and is thus "completed".  B will then try to use the packet instead
    896 -of forwarding it, i.e. deliver it up to some application.
    897 -
    898 -Note that by moving the pointer yourself, you could send the traffic directly
    899 -to B but have it return via your preconstructed source-route.  Playing with
    900 -this and watching "tcpdump -v" is the best way to understand what's going on.
    901 -
    902 -Only works for TCP in BSD-flavor kernels.  UDP is a loss; udp_input calls
    903 -stripoptions() early on, and the code to save the srcrt is notdef'ed.
    904 -Linux is also still a loss at 1.3.x it looks like; the lsrr code is { }...
    905 -*/
    906 
    907 
    908 /* if any -g arguments were given, set up source-routing.  We hit this after
    909    the gates are all looked up and ready to rock, any -G pointer is set,
    910    and gatesidx is now the *number* of hops */
    911   if (gatesidx) {		/* if we wanted any srcrt hops ... */
    912 /* don't even bother compiling if we can't do IP options here! */
    913 /* #ifdef IP_OPTIONS */
    914 #ifndef WIN32 
    915     if (! optbuf) {		/* and don't already *have* a srcrt set */
    916       char * opp;		/* then do all this setup hair */
    917       optbuf = Hmalloc (48);
    918       opp = optbuf;
    919       *opp++ = IPOPT_LSRR;					/* option */
    920       *opp++ = (char)
    921 	(((gatesidx + 1) * sizeof (IA)) + 3) & 0xff;		/* length */
    922       *opp++ = gatesptr;					/* pointer */
    923 /* opp now points at first hop addr -- insert the intermediate gateways */
    924       for ( x = 0; x < gatesidx; x++) {
    925 	memcpy (opp, gates[x]->iaddrs, sizeof (IA));
    926 	opp += sizeof (IA);
    927       }
    928 /* and tack the final destination on the end [needed!] */
    929       memcpy (opp, rad, sizeof (IA));
    930       opp += sizeof (IA);
    931       *opp = IPOPT_NOP;			/* alignment filler */
    932     } /* if empty optbuf */
    933 /* calculate length of whole option mess, which is (3 + [hops] + [final] + 1),
    934    and apply it [have to do this every time through, of course] */
    935     x = ((gatesidx + 1) * sizeof (IA)) + 4;
    936     rr = setsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, x);
    937     if (rr == -1)
    938       bail ("srcrt setsockopt fuxored");
    939 #else /* IP_OPTIONS */
    940     holler ("Warning: source routing unavailable on this machine, ignoring");
    941 #endif /* IP_OPTIONS*/
    942   } /* if gatesidx */
    943 
    944 /* wrap connect inside a timer, and hit it */
    945   arm (1, o_wait);
    946   if (setjmp (jbuf) == 0) {
    947     rr = connect (nnetfd, (SA *)remend, sizeof (SA));
    948   } else {				/* setjmp: connect failed... */
    949     rr = -1;
    950 #ifdef WIN32
    951     WSASetLastError(WSAETIMEDOUT);			/* fake it */
    952 #else
    953     errno = ETIMEDOUT;			/* fake it */
    954 #endif
    955   }
    956   arm (0, 0);
    957   if (rr == 0)
    958     return (nnetfd);
    959 #ifdef WIN32
    960   errno = h_errno;
    961   shutdown(nnetfd, 0x02);  /* Kirby */
    962   closesocket (nnetfd);
    963   WSASetLastError(errno); /* don't want to lose connect error */
    964 #else
    965   close (nnetfd);			/* clean up junked socket FD!! */
    966 #endif
    967   return (-1);
    968 } /* doconnect */
    969 
    970 /* dolisten :
    971    just like doconnect, and in fact calls a hunk of doconnect, but listens for
    972    incoming and returns an open connection *from* someplace.  If we were
    973    given host/port args, any connections from elsewhere are rejected.  This
    974    in conjunction with local-address binding should limit things nicely... */
    975 int dolisten (rad, rp, lad, lp)
    976   IA * rad;
    977   USHORT rp;
    978   IA * lad;
    979   USHORT lp;
    980 {
    981   register int nnetfd;
    982   register int rr;
    983   HINF * whozis = NULL;
    984   int x;
    985   char * cp;
    986   USHORT z;
    987   errno = 0;
    988 
    989 /* Pass everything off to doconnect, who in o_listen mode just gets a socket */
    990   nnetfd = doconnect (rad, rp, lad, lp);
    991   if (nnetfd <= 0)
    992     return (-1);
    993   if (o_udpmode) {			/* apparently UDP can listen ON */
    994     if (! lp)				/* "port 0",  but that's not useful */
    995       bail ("UDP listen needs -p arg");
    996   } else {
    997     rr = listen (nnetfd, 1);		/* gotta listen() before we can get */
    998     if (rr < 0)				/* our local random port.  sheesh. */
    999       bail ("local listen fuxored");
   1000   }
   1001 
   1002 /* I can't believe I have to do all this to get my own goddamn bound address
   1003    and port number.  It should just get filled in during bind() or something.
   1004    All this is only useful if we didn't say -p for listening, since if we
   1005    said -p we *know* what port we're listening on.  At any rate we won't bother
   1006    with it all unless we wanted to see it, although listening quietly on a
   1007    random unknown port is probably not very useful without "netstat". */
   1008   if (o_verbose) {
   1009     x = sizeof (SA);		/* how 'bout getsockNUM instead, pinheads?! */
   1010     rr = getsockname (nnetfd, (SA *) lclend, &x);
   1011       if (rr < 0)
   1012 	holler ("local getsockname failed");
   1013     strcpy (bigbuf_net, "listening on [");	/* buffer reuse... */
   1014       if (lclend->sin_addr.s_addr)
   1015 	strcat (bigbuf_net, inet_ntoa (lclend->sin_addr));
   1016       else
   1017 	strcat (bigbuf_net, "any");
   1018     strcat (bigbuf_net, "] %d ...");
   1019     z = ntohs (lclend->sin_port);
   1020     holler (bigbuf_net, z);
   1021   } /* verbose -- whew!! */
   1022 
   1023 /* UDP is a speeeeecial case -- we have to do I/O *and* get the calling
   1024    party's particulars all at once, listen() and accept() don't apply.
   1025    At least in the BSD universe, however, recvfrom/PEEK is enough to tell
   1026    us something came in, and we can set things up so straight read/write
   1027    actually does work after all.  Yow.  YMMV on strange platforms!  */
   1028   if (o_udpmode) {
   1029     x = sizeof (SA);		/* retval for recvfrom */
   1030     arm (2, o_wait);		/* might as well timeout this, too */
   1031     if (setjmp (jbuf) == 0) {	/* do timeout for initial connect */
   1032       rr = recvfrom		/* and here we block... */
   1033 	(nnetfd, bigbuf_net, BIGSIZ, MSG_PEEK, (SA *) remend, &x);
   1034 Debug (("dolisten/recvfrom ding, rr = %d, netbuf %s ", rr, bigbuf_net))
   1035     } else
   1036       goto dol_tmo;		/* timeout */
   1037     arm (0, 0);
   1038 /* I'm not completely clear on how this works -- BSD seems to make UDP
   1039    just magically work in a connect()ed context, but we'll undoubtedly run
   1040    into systems this deal doesn't work on.  For now, we apparently have to
   1041    issue a connect() on our just-tickled socket so we can write() back.
   1042    Again, why the fuck doesn't it just get filled in and taken care of?!
   1043    This hack is anything but optimal.  Basically, if you want your listener
   1044    to also be able to send data back, you need this connect() line, which
   1045    also has the side effect that now anything from a different source or even a
   1046    different port on the other end won't show up and will cause ICMP errors.
   1047    I guess that's what they meant by "connect".
   1048    Let's try to remember what the "U" is *really* for, eh?
   1049 */
   1050     rr = connect (nnetfd, (SA *)remend, sizeof (SA));
   1051     goto whoisit;
   1052   } /* o_udpmode */
   1053 
   1054 /* fall here for TCP */
   1055   x = sizeof (SA);		/* retval for accept */
   1056   arm (2, o_wait);		/* wrap this in a timer, too; 0 = forever */
   1057   if (setjmp (jbuf) == 0) {
   1058     rr = accept (nnetfd, (SA *)remend, &x);
   1059   } else
   1060     goto dol_tmo;		/* timeout */
   1061   arm (0, 0);
   1062 #ifdef WIN32
   1063   shutdown(nnetfd, 0x02);  /* Kirby */
   1064   closesocket (nnetfd);
   1065 #else
   1066   close (nnetfd);		/* dump the old socket */
   1067 #endif
   1068   nnetfd = rr;			/* here's our new one */
   1069 
   1070 whoisit:
   1071   if (rr < 0)
   1072     goto dol_err;		/* bail out if any errors so far */
   1073 
   1074 /* Various things that follow temporarily trash bigbuf_net, which might contain
   1075    a copy of any recvfrom()ed packet, but we'll read() another copy later. */
   1076 
   1077 /* If we can, look for any IP options.  Useful for testing the receiving end of
   1078    such things, and is a good exercise in dealing with it.  We do this before
   1079    the connect message, to ensure that the connect msg is uniformly the LAST
   1080    thing to emerge after all the intervening crud.  Doesn't work for UDP on
   1081    any machines I've tested, but feel free to surprise me. */
   1082 /* #ifdef IP_OPTIONS */
   1083 #ifndef WIN32
   1084   if (! o_verbose)			/* if we wont see it, we dont care */
   1085     goto dol_noop;
   1086   optbuf = Hmalloc (40);
   1087   x = 40;
   1088   rr = getsockopt (nnetfd, IPPROTO_IP, IP_OPTIONS, optbuf, &x);
   1089   if (rr < 0)
   1090     holler ("getsockopt failed");
   1091 Debug (("ipoptions ret len %d", x))
   1092   if (x) {				/* we've got options, lessee em... */
   1093     unsigned char * q = (unsigned char *) optbuf;
   1094     char * p = bigbuf_net;		/* local variables, yuk! */
   1095     char * pp = &bigbuf_net[128];	/* get random space farther out... */
   1096     memset (bigbuf_net, 0, 256);	/* clear it all first */
   1097     while (x > 0) {
   1098 	sprintf (pp, "%2.2x ", *q);	/* clumsy, but works: turn into hex */
   1099 	strcat (p, pp);			/* and build the final string */
   1100 	q++; p++;
   1101 	x--;
   1102     }
   1103     holler ("IP options: %s", bigbuf_net);
   1104   } /* if x, i.e. any options */
   1105 dol_noop:
   1106 #endif /* IP_OPTIONS */
   1107 
   1108 /* find out what address the connection was *to* on our end, in case we're
   1109    doing a listen-on-any on a multihomed machine.  This allows one to
   1110    offer different services via different alias addresses, such as the
   1111    "virtual web site" hack. */
   1112   memset (bigbuf_net, 0, 64);
   1113   cp = &bigbuf_net[32];
   1114   x = sizeof (SA);
   1115   rr = getsockname (nnetfd, (SA *) lclend, &x);
   1116   if (rr < 0)
   1117     holler ("post-rcv getsockname failed");
   1118   strcpy (cp, inet_ntoa (lclend->sin_addr));
   1119 
   1120 
   1121 /* now check out who it is.  We don't care about mismatched DNS names here,
   1122    but any ADDR and PORT we specified had better fucking well match the caller.
   1123    Converting from addr to inet_ntoa and back again is a bit of a kludge, but
   1124    gethostpoop wants a string and there's much gnarlier code out there already,
   1125    so I don't feel bad.
   1126    The *real* question is why BFD sockets wasn't designed to allow listens for
   1127    connections *from* specific hosts/ports, instead of requiring the caller to
   1128    accept the connection and then reject undesireable ones by closing. */
   1129   z = ntohs (remend->sin_port);
   1130   strcpy (bigbuf_net, inet_ntoa (remend->sin_addr));
   1131   whozis = gethostpoop (bigbuf_net, o_nflag);
   1132   errno = 0;
   1133   x = 0;				/* use as a flag... */
   1134   if (rad)
   1135     if (memcmp (rad, whozis->iaddrs, sizeof (SA)))
   1136       x = 1;
   1137   if (rp)
   1138     if (z != rp)
   1139       x = 1;
   1140   if (x)					/* guilty! */
   1141 	bail ("invalid connection to [%s] from %s [%s] %d",
   1142 	cp, whozis->name, whozis->addrs[0], z);
   1143   	holler ("connect to [%s] from %s [%s] %d",		/* oh, you're okay.. */
   1144 	cp, whozis->name, whozis->addrs[0], z);
   1145 
   1146   return (nnetfd);				/* open! */
   1147 
   1148 dol_tmo:
   1149   errno = ETIMEDOUT;			/* fake it */
   1150 dol_err:
   1151 #ifdef WIN32
   1152   shutdown(nnetfd, 0x02);  /* Kirby */
   1153   closesocket (nnetfd);
   1154 #else
   1155   close (nnetfd);
   1156 #endif
   1157   return (-1);
   1158 } /* dolisten */
   1159 
   1160 /* udptest :
   1161    fire a couple of packets at a UDP target port, just to see if it's really
   1162    there.  On BSD kernels, ICMP host/port-unreachable errors get delivered to
   1163    our socket as ECONNREFUSED write errors.  On SV kernels, we lose; we'll have
   1164    to collect and analyze raw ICMP ourselves a la satan's probe_udp_ports
   1165    backend.  Guess where could swipe the appropriate code from...
   1166 
   1167    Use the time delay between writes if given, otherwise use the "tcp ping"
   1168    trick for getting the RTT.  [I got that idea from pluvius, and warped it.]
   1169    Return either the original fd, or clean up and return -1. */
   1170 udptest (fd, where)
   1171   int fd;
   1172   IA * where;
   1173 {
   1174   register int rr;
   1175 
   1176 #ifdef WIN32
   1177   rr = send (fd, bigbuf_in, 1, 0);
   1178 #else
   1179   rr = write (fd, bigbuf_in, 1);
   1180 #endif
   1181   if (rr != 1)
   1182     holler ("udptest first write failed?! errno %d", errno);
   1183   if (o_wait)
   1184     sleep (o_wait);
   1185   else {
   1186 /* use the tcp-ping trick: try connecting to a normally refused port, which
   1187    causes us to block for the time that SYN gets there and RST gets back.
   1188    Not completely reliable, but it *does* mostly work. */
   1189     o_udpmode = 0;			/* so doconnect does TCP this time */
   1190 /* Set a temporary connect timeout, so packet filtration doesnt cause
   1191    us to hang forever, and hit it */
   1192     o_wait = 5;				/* XXX: enough to notice?? */
   1193     rr = doconnect (where, SLEAZE_PORT, 0, 0);
   1194     if (rr > 0)
   1195 #ifdef WIN32
   1196 	  shutdown(fd, 0x02);  /* Kirby */
   1197 	  closesocket (rr);
   1198 #else
   1199       close (rr);			/* in case it *did* open */
   1200 #endif
   1201     o_wait = 0;				/* reset it */
   1202     o_udpmode++;			/* we *are* still doing UDP, right? */
   1203   } /* if o_wait */
   1204   errno = 0;				/* clear from sleep */
   1205 #ifdef WIN32
   1206   rr = send (fd, bigbuf_in, 1, 0);
   1207 #else
   1208   rr = write (fd, bigbuf_in, 1);
   1209 #endif
   1210   if (rr == 1)				/* if write error, no UDP listener */
   1211     return (fd);
   1212 #ifdef WIN32
   1213   shutdown(fd, 0x02);  /* Kirby */
   1214   closesocket (fd);
   1215 #else
   1216   close (fd);				/* use it or lose it! */
   1217 #endif
   1218   return (-1);
   1219 } /* udptest */
   1220 
   1221 /* oprint :
   1222    Hexdump bytes shoveled either way to a running logfile, in the format:
   1223 D offset       -  - - - --- 16 bytes --- - - -  -     # .... ascii .....
   1224    where "which" sets the direction indicator, D:
   1225 	0 -- sent to network, or ">"
   1226 	1 -- rcvd and printed to stdout, or "<"
   1227    and "buf" and "n" are data-block and length.  If the current block generates
   1228    a partial line, so be it; we *want* that lockstep indication of who sent
   1229    what when.  Adapted from dgaudet's original example -- but must be ripping
   1230    *fast*, since we don't want to be too disk-bound... */
   1231 void oprint (which, buf, n)
   1232   int which;
   1233   char * buf;
   1234   int n;
   1235 {
   1236   int bc;			/* in buffer count */
   1237   int obc;			/* current "global" offset */
   1238   int soc;			/* stage write count */
   1239   register unsigned char * p;	/* main buf ptr; m.b. unsigned here */
   1240   register unsigned char * op;	/* out hexdump ptr */
   1241   register unsigned char * a;	/* out asc-dump ptr */
   1242   register int x;
   1243   register unsigned int y;
   1244 
   1245   if (! ofd)
   1246     bail ("oprint called with no open fd?!");
   1247   if (n == 0)
   1248     return;
   1249 
   1250   op = stage;
   1251   if (which) {
   1252     *op = '<';
   1253     obc = wrote_out;		/* use the globals! */
   1254   } else {
   1255     *op = '>';
   1256     obc = wrote_net;
   1257   }
   1258   op++;				/* preload "direction" */
   1259   *op = ' ';
   1260   p = (unsigned char *) buf;
   1261   bc = n;
   1262   stage[59] = '#';		/* preload separator */
   1263   stage[60] = ' ';
   1264 
   1265   while (bc) {			/* for chunk-o-data ... */
   1266     x = 16;
   1267     soc = 78;			/* len of whole formatted line */
   1268     if (bc < x) {
   1269       soc = soc - 16 + bc;	/* fiddle for however much is left */
   1270       x = (bc * 3) + 11;	/* 2 digits + space per, after D & offset */
   1271       op = &stage[x];
   1272       x = 16 - bc;
   1273       while (x) {
   1274 	*op++ = ' ';		/* preload filler spaces */
   1275 	*op++ = ' ';
   1276 	*op++ = ' ';
   1277 	x--;
   1278       }
   1279       x = bc;			/* re-fix current linecount */
   1280     } /* if bc < x */
   1281 
   1282     bc -= x;			/* fix wrt current line size */
   1283     sprintf (&stage[2], "%8.8x ", obc);		/* xxx: still slow? */
   1284     obc += x;			/* fix current offset */
   1285     op = &stage[11];		/* where hex starts */
   1286     a = &stage[61];		/* where ascii starts */
   1287 
   1288     while (x) {			/* for line of dump, however long ... */
   1289       y = (int)(*p >> 4);	/* hi half */
   1290       *op = hexnibs[y];
   1291       op++;
   1292       y = (int)(*p & 0x0f);	/* lo half */
   1293       *op = hexnibs[y];
   1294       op++;
   1295       *op = ' ';
   1296       op++;
   1297       if ((*p > 31) && (*p < 127))
   1298 	*a = *p;		/* printing */
   1299       else
   1300 	*a = '.';		/* nonprinting, loose def */
   1301       a++;
   1302       p++;
   1303       x--;
   1304     } /* while x */
   1305     *a = '\n';			/* finish the line */
   1306     x = write (ofd, stage, soc);
   1307     if (x < 0)
   1308       bail ("ofd write err");
   1309   } /* while bc */
   1310 } /* oprint */
   1311 
   1312 #ifdef TELNET
   1313 USHORT o_tn = 0;		/* global -t option */
   1314 
   1315 /* atelnet :
   1316    Answer anything that looks like telnet negotiation with don't/won't.
   1317    This doesn't modify any data buffers, update the global output count,
   1318    or show up in a hexdump -- it just shits into the outgoing stream.
   1319    Idea and codebase from Mudge@l0pht.com. */
   1320 void atelnet (buf, size)
   1321   unsigned char * buf;		/* has to be unsigned here! */
   1322   unsigned int size;
   1323 {
   1324   static unsigned char obuf [4];  /* tiny thing to build responses into */
   1325   register int x;
   1326   register unsigned char y;
   1327   register unsigned char * p;
   1328 
   1329   y = 0;
   1330   p = buf;
   1331   x = size;
   1332   while (x > 0) {
   1333     if (*p != 255)			/* IAC? */
   1334       goto notiac;
   1335     obuf[0] = 255;
   1336     p++; x--;
   1337     if ((*p == 251) || (*p == 252))	/* WILL or WONT */
   1338       y = 254;				/* -> DONT */
   1339     if ((*p == 253) || (*p == 254))	/* DO or DONT */
   1340       y = 252;				/* -> WONT */
   1341     if (y) {
   1342       obuf[1] = y;
   1343       p++; x--;
   1344       obuf[2] = *p;			/* copy actual option byte */
   1345 #ifdef WIN32
   1346 	  (void) send (netfd, obuf, 3, 0);	/* one line, or the whole buffer */
   1347 #else
   1348       (void) write (netfd, obuf, 3);
   1349 #endif
   1350 /* if one wanted to bump wrote_net or do a hexdump line, here's the place */
   1351       y = 0;
   1352     } /* if y */
   1353 notiac:
   1354     p++; x--;
   1355   } /* while x */
   1356 } /* atelnet */
   1357 #endif /* TELNET */
   1358 
   1359 
   1360 /* readwrite :
   1361    handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
   1362    In this instance, return what might become our exit status. */
   1363 int readwrite (fd)
   1364 #ifdef WIN32
   1365   unsigned int fd;
   1366 #else
   1367   int fd;
   1368 #endif
   1369 {
   1370   register int rr;
   1371   register char * zp;		/* stdin buf ptr */
   1372   register char * np;		/* net-in buf ptr */
   1373   unsigned int rzleft;
   1374   unsigned int rnleft;
   1375   USHORT netretry;		/* net-read retry counter */
   1376   USHORT wretry;		/* net-write sanity counter */
   1377   USHORT wfirst;		/* one-shot flag to skip first net read */
   1378 
   1379 #ifdef WIN32 /* (weld) WIN32 must poll because of weak stdin handling so we need a
   1380 				short timer */
   1381   struct timeval timer3;
   1382   int istty;
   1383   time_t start, current;
   1384   int foo;
   1385 
   1386   timer3.tv_sec = 0;
   1387   timer3.tv_usec = 1000;
   1388 
   1389   /* save the time so we can bail when we reach timeout */
   1390   time( &start );
   1391 
   1392 
   1393   /* sets stdin and stdout to binary so no crlf translation if its a tty */
   1394   if (!_isatty( 1 ))
   1395 	_setmode( 1, _O_BINARY ); 
   1396 
   1397   if ((istty = _isatty( 0 )) == FALSE)
   1398 	_setmode( 0, _O_BINARY ); /* (weld) I think we want to do this */
   1399 
   1400 #endif
   1401 
   1402 /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
   1403    either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
   1404 #ifndef WIN32  /* fd is not implemented as a real file handle in WIN32 */
   1405   if (fd > FD_SETSIZE) {
   1406     holler ("Preposterous fd value %d", fd);
   1407     return (1);
   1408   }
   1409 #endif
   1410   FD_SET (fd, ding1);		/* global: the net is open */
   1411   netretry = 2;
   1412   wfirst = 0;
   1413   rzleft = rnleft = 0;
   1414   if (insaved) {
   1415     rzleft = insaved;		/* preload multi-mode fakeouts */
   1416     zp = bigbuf_in;
   1417 
   1418 	wfirst = 1;
   1419     if (Single)			/* if not scanning, this is a one-off first */
   1420       insaved = 0;		/* buffer left over from argv construction, */
   1421     else {
   1422       FD_CLR (0, ding1);	/* OR we've already got our repeat chunk, */
   1423       close (0);		/* so we won't need any more stdin */
   1424     } /* Single */
   1425   } /* insaved */
   1426 
   1427   if (o_interval)
   1428     sleep (o_interval);		/* pause *before* sending stuff, too */
   1429   errno = 0;			/* clear from sleep */
   1430 #ifdef WIN32
   1431   WSASetLastError(0);
   1432 #endif
   1433 
   1434 /* and now the big ol' select shoveling loop ... */
   1435   while (FD_ISSET (fd, ding1)) {	/* i.e. till the *net* closes! */
   1436     wretry = 8200;			/* more than we'll ever hafta write */
   1437     if (wfirst) {			/* any saved stdin buffer? */
   1438       wfirst = 0;			/* clear flag for the duration */
   1439       goto shovel;			/* and go handle it first */
   1440     }
   1441     *ding2 = *ding1;			/* FD_COPY ain't portable... */
   1442 	
   1443 /* some systems, notably linux, crap into their select timers on return, so
   1444    we create a expendable copy and give *that* to select.  *Fuck* me ... */
   1445     if (timer1)
   1446       memcpy (timer2, timer1, sizeof (struct timeval));
   1447 #ifdef WIN32 /* (weld)we must use our own small timeval to poll */
   1448     rr = select (16, ding2, 0, 0, &timer3);	/* here it is, kiddies */
   1449 #else
   1450     rr = select (16, ding2, 0, 0, timer2);	/* here it is, kiddies */
   1451 #endif
   1452     if (rr < 0) {
   1453 #ifdef WIN32
   1454 		if (h_errno != WSAEINTR) {		/* might have gotten ^Zed, etc ?*/
   1455 #else
   1456 		if (errno != EINTR) {		/* might have gotten ^Zed, etc ?*/
   1457 #endif
   1458 		  foo = h_errno;
   1459 		  holler ("select fuxored");
   1460 #ifdef WIN32
   1461 		  shutdown(fd, 0x02);  /* Kirby */
   1462 		  closesocket (fd);
   1463 #else
   1464 		  close (fd);
   1465 #endif
   1466 		  return (1);
   1467 		}
   1468     } /* select fuckup */
   1469 /* if we have a timeout AND stdin is closed AND we haven't heard anything
   1470    from the net during that time, assume it's dead and close it too. */
   1471 #ifndef WIN32  /* (weld) need to write some code here */
   1472     if (rr == 0) {
   1473 	if (! FD_ISSET (0, ding1))
   1474 	  netretry--;			/* we actually try a coupla times. */
   1475 	if (! netretry) {
   1476 	  if (o_verbose > 1)		/* normally we don't care */
   1477 	    holler ("net timeout");
   1478 	  close (fd);
   1479 	  return (0);			/* not an error! */
   1480 		}
   1481     } /* select timeout */
   1482 #else
   1483 	if (rr == 0) {
   1484 		time( &current );
   1485 		if ( o_wait > 0 && (current - start) > timer1->tv_sec)	{
   1486 			if (o_verbose > 1)		/* normally we don't care */
   1487 				holler ("net timeout");
   1488 			shutdown(fd, 0x02);  /* Kirby */
   1489 			closesocket (fd);
   1490 			FD_ZERO(ding1);
   1491 			WSASetLastError(0); 
   1492 			return (0);			/* not an error! */
   1493 		}
   1494     } /* select timeout */
   1495 #endif
   1496 /* xxx: should we check the exception fds too?  The read fds seem to give
   1497    us the right info, and none of the examples I found bothered. */
   1498 
   1499 /* Ding!!  Something arrived, go check all the incoming hoppers, net first */
   1500     if (FD_ISSET (fd, ding2)) {		/* net: ding! */
   1501 #ifdef WIN32
   1502 	// reset timer
   1503 	time( &start );
   1504 
   1505 	rr = recv (fd, bigbuf_net, BIGSIZ, 0);
   1506 #else
   1507 	rr = read (fd, bigbuf_net, BIGSIZ);
   1508 #endif
   1509 	if (rr <= 0) {
   1510 	  FD_CLR (fd, ding1);		/* net closed, we'll finish up... */
   1511 	  rzleft = 0;			/* can't write anymore: broken pipe */
   1512 	} else {
   1513 	  rnleft = rr;
   1514 	  np = bigbuf_net;
   1515 #ifdef TELNET
   1516 	  if (o_tn)
   1517 	    atelnet (np, rr);		/* fake out telnet stuff */
   1518 #endif /* TELNET */
   1519 	} /* if rr */
   1520 Debug (("got %d from the net, errno %d", rr, errno))
   1521     } /* net:ding */
   1522 
   1523 /* if we're in "slowly" mode there's probably still stuff in the stdin
   1524    buffer, so don't read unless we really need MORE INPUT!  MORE INPUT! */
   1525     if (rzleft)
   1526 	goto shovel;
   1527 
   1528 /* okay, suck more stdin */
   1529 #ifndef WIN32
   1530     if (FD_ISSET (0, ding2)) {		/* stdin: ding! */
   1531 	rr = read (0, bigbuf_in, BIGSIZ);
   1532 
   1533 /* xxx: maybe make reads here smaller for UDP mode, so that the subsequent
   1534    writes are smaller -- 1024 or something?  "oh, frag it", etc, although
   1535    mobygrams are kinda fun and exercise the reassembler. */
   1536 	if (rr <= 0) {			/* at end, or fukt, or ... */
   1537 	  FD_CLR (0, ding1);		/* disable and close stdin */
   1538 	  close (0);
   1539 	} else {
   1540 	  rzleft = rr;
   1541 	  zp = bigbuf_in;
   1542 /* special case for multi-mode -- we'll want to send this one buffer to every
   1543    open TCP port or every UDP attempt, so save its size and clean up stdin */
   1544 	  if (! Single) {		/* we might be scanning... */
   1545 	    insaved = rr;		/* save len */
   1546 	    FD_CLR (0, ding1);		/* disable further junk from stdin */
   1547 	    close (0);			/* really, I mean it */
   1548 	  } /* Single */
   1549 	} /* if rr/read */
   1550     } /* stdin:ding */
   1551 #else
   1552 	if (istty) {
   1553 		/* (weld) cool, we can actually peek a tty and not have to block */
   1554 		/* needs to be cleaned up */
   1555 		if (kbhit()) {
   1556 /*			bigbuf_in[0] = getche(); */
   1557 			gets(bigbuf_in);
   1558 			if (o_crlf)
   1559 		  	  strcat(bigbuf_in, "\x0d");
   1560 		  	strcat(bigbuf_in, "\x0a");
   1561 			rr = strlen(bigbuf_in);
   1562 			rzleft = rr;
   1563 			zp = bigbuf_in;
   1564 /* special case for multi-mode -- we'll want to send this one buffer to every
   1565    open TCP port or every UDP attempt, so save its size and clean up stdin */
   1566 			if (! Single) {		/* we might be scanning... */
   1567 				insaved = rr;		/* save len */
   1568 				close (0);			/* really, I mean it */
   1569 			}
   1570 		}
   1571 	} else {
   1572 		/* (weld) this is gonna block until a <cr> so it kinda sucks */
   1573 		rr = read (0, bigbuf_in, BIGSIZ);
   1574 		if (rr <= 0) {			/* at end, or fukt, or ... */
   1575 			close (0);
   1576 		} else {
   1577 			rzleft = rr;
   1578 			zp = bigbuf_in;
   1579 /* special case for multi-mode -- we'll want to send this one buffer to every
   1580    open TCP port or every UDP attempt, so save its size and clean up stdin */
   1581 			if (! Single) {		/* we might be scanning... */
   1582 				insaved = rr;		/* save len */
   1583 				close (0);			/* really, I mean it */
   1584 			} /* Single */
   1585 		} /* if rr/read */
   1586 	}
   1587 
   1588 #endif
   1589 shovel:
   1590 /* now that we've dingdonged all our thingdings, send off the results.
   1591    Geez, why does this look an awful lot like the big loop in "rsh"? ...
   1592    not sure if the order of this matters, but write net -> stdout first. */
   1593 
   1594 /* sanity check.  Works because they're both unsigned... */
   1595     if ((rzleft > 8200) || (rnleft > 8200)) {
   1596 	holler ("Preposterous Pointers: %d, %d", rzleft, rnleft);
   1597 	rzleft = rnleft = 0;
   1598     }
   1599 /* net write retries sometimes happen on UDP connections */
   1600     if (! wretry) {			/* is something hung? */
   1601 	holler ("too many output retries");
   1602 	return (1);
   1603     }
   1604     if (rnleft) {
   1605 	rr = write (1, np, rnleft);
   1606 	fflush(stdin);
   1607 	if (rr > 0) {
   1608 	  if (o_wfile)
   1609 	    oprint (1, np, rr);		/* log the stdout */
   1610 	  np += rr;			/* fix up ptrs and whatnot */
   1611 	  rnleft -= rr;			/* will get sanity-checked above */
   1612 	  wrote_out += rr;		/* global count */
   1613 	}
   1614 Debug (("wrote %d to stdout, errno %d", rr, errno))
   1615     } /* rnleft */
   1616     if (rzleft) {
   1617 	if (o_interval)			/* in "slowly" mode ?? */
   1618 	  rr = findline (zp, rzleft);
   1619 	else
   1620 	  rr = rzleft;
   1621 #ifdef WIN32
   1622 	rr = send (fd, zp, rr, 0);	/* one line, or the whole buffer */
   1623 #else
   1624 	rr = write (fd, zp, rr);	/* one line, or the whole buffer */
   1625 #endif
   1626 	if (rr > 0) {
   1627 	  zp += rr;
   1628 	  rzleft -= rr;
   1629 	  wrote_net += rr;		/* global count */
   1630 	}
   1631 Debug (("wrote %d to net, errno %d", rr, errno))
   1632     } /* rzleft */
   1633     if (o_interval) {			/* cycle between slow lines, or ... */
   1634 	sleep (o_interval);
   1635 	errno = 0;			/* clear from sleep */
   1636 	continue;			/* ...with hairy select loop... */
   1637     }
   1638     if ((rzleft) || (rnleft)) {		/* shovel that shit till they ain't */
   1639 	wretry--;			/* none left, and get another load */
   1640 	goto shovel;
   1641     }
   1642   } /* while ding1:netfd is open */
   1643 
   1644 /* XXX: maybe want a more graceful shutdown() here, or screw around with
   1645    linger times??  I suspect that I don't need to since I'm always doing
   1646    blocking reads and writes and my own manual "last ditch" efforts to read
   1647    the net again after a timeout.  I haven't seen any screwups yet, but it's
   1648    not like my test network is particularly busy... */
   1649 #ifdef WIN32
   1650   shutdown(fd, 0x02);  /* Kirby */
   1651   closesocket (fd);
   1652 #else
   1653   close (fd);
   1654 #endif
   1655   return (0);
   1656 } /* readwrite */
   1657 
   1658 /* main :
   1659    now we pull it all together... */
   1660 main (argc, argv)
   1661   int argc;
   1662   char ** argv;
   1663 {
   1664 #ifndef HAVE_GETOPT
   1665   extern char * optarg;
   1666   extern int optind, optopt;
   1667 #endif
   1668   register int x;
   1669   register char *cp;
   1670   HINF * gp;
   1671   HINF * whereto = NULL;
   1672   HINF * wherefrom = NULL;
   1673   IA * ouraddr = NULL;
   1674   IA * themaddr = NULL;
   1675   USHORT o_lport = 0;
   1676   USHORT ourport = 0;
   1677   USHORT loport = 0;		/* for scanning stuff */
   1678   USHORT hiport = 0;
   1679   USHORT curport = 0;
   1680   char * randports = NULL;
   1681   int cycle = 0;
   1682 
   1683 #ifdef HAVE_BIND
   1684 /* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */
   1685   res_init();
   1686 #endif
   1687 /* I was in this barbershop quartet in Skokie IL ... */
   1688 /* round up the usual suspects, i.e. malloc up all the stuff we need */
   1689   lclend = (SAI *) Hmalloc (sizeof (SA));
   1690   remend = (SAI *) Hmalloc (sizeof (SA));
   1691   bigbuf_in = Hmalloc (BIGSIZ);
   1692   bigbuf_net = Hmalloc (BIGSIZ);
   1693   ding1 = (fd_set *) Hmalloc (sizeof (fd_set));
   1694   ding2 = (fd_set *) Hmalloc (sizeof (fd_set));
   1695   portpoop = (PINF *) Hmalloc (sizeof (PINF));
   1696 
   1697 #ifdef WIN32
   1698   setsockopt_c = (char *)malloc(sizeof(char));
   1699   *setsockopt_c	= 1;
   1700 #endif
   1701 
   1702   errno = 0;
   1703   gatesptr = 4;
   1704 #ifndef WIN32
   1705   h_errno = 0;	
   1706 #endif
   1707 /* catch a signal or two for cleanup */
   1708 #ifdef NTFIXTHIS
   1709   signal (SIGINT, catch);
   1710   signal (SIGQUIT, catch);
   1711   signal (SIGTERM, catch);
   1712   signal (SIGURG, SIG_IGN);
   1713 #endif
   1714 
   1715 recycle:
   1716 
   1717 /* if no args given at all, get 'em from stdin and construct an argv. */
   1718   if (argc == 1) {
   1719     cp = argv[0];
   1720     argv = (char **) Hmalloc (128 * sizeof (char *));	/* XXX: 128? */
   1721     argv[0] = cp;			/* leave old prog name intact */
   1722     cp = Hmalloc (BIGSIZ);
   1723     argv[1] = cp;			/* head of new arg block */
   1724     fprintf (stderr, "Cmd line: ");
   1725     fflush (stderr);		/* I dont care if it's unbuffered or not! */
   1726 	insaved = read (0, cp, BIGSIZ);	/* we're gonna fake fgets() here */
   1727     if (insaved <= 0)
   1728       bail ("wrong");
   1729     x = findline (cp, insaved);
   1730     if (x)
   1731       insaved -= x;		/* remaining chunk size to be sent */
   1732     if (insaved)		/* which might be zero... */
   1733       memcpy (bigbuf_in, &cp[x], insaved);
   1734     cp = strchr (argv[1], '\n');
   1735     if (cp)
   1736       *cp = '\0';
   1737     cp = strchr (argv[1], '\r');	/* look for ^M too */
   1738     if (cp)
   1739       *cp = '\0';
   1740 
   1741 /* find and stash pointers to remaining new "args" */
   1742     cp = argv[1];
   1743     cp++;				/* skip past first char */
   1744     x = 2;				/* we know argv 0 and 1 already */
   1745     for (; *cp != '\0'; cp++) {
   1746       if (*cp == ' ') {
   1747 	*cp = '\0';			/* smash all spaces */
   1748 	continue;
   1749       } else {
   1750 	if (*(cp-1) == '\0') {
   1751 	  argv[x] = cp;
   1752 	  x++;
   1753 	}
   1754       } /* if space */
   1755     } /* for cp */
   1756     argc = x;
   1757   } /* if no args given */
   1758 
   1759 /* If your shitbox doesn't have getopt, step into the nineties already. */
   1760 /* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */
   1761    while ((x = getopt (argc, argv, "ade:g:G:hi:lLno:p:rs:tcuvw:z")) != EOF) {
   1762 /* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
   1763     switch (x) {
   1764       case 'a':
   1765 	bail ("all-A-records NIY");
   1766 	o_alla++; break;
   1767 #ifdef GAPING_SECURITY_HOLE
   1768       case 'e':				/* prog to exec */
   1769 	pr00gie = optarg;
   1770 	break;
   1771 #endif
   1772 	        case 'L':				/* listen then cycle back to start instead of exiting */
   1773 	o_listen++; 
   1774   	cycle = 1;
   1775 	  break;
   1776 
   1777 
   1778         case 'd':				/* detach from console */
   1779   	FreeConsole();;
   1780 	  break;
   1781 
   1782 
   1783       case 'G':				/* srcrt gateways pointer val */
   1784 	x = atoi (optarg);
   1785 	if ((x) && (x == (x & 0x1c)))	/* mask off bits of fukt values */
   1786 	  gatesptr = x;
   1787 	else
   1788 	  bail ("invalid hop pointer %d, must be multiple of 4 <= 28", x);
   1789 	break;
   1790       case 'g':				/* srcroute hop[s] */
   1791 	if (gatesidx > 8)
   1792 	  bail ("too many -g hops");
   1793 	if (gates == NULL)		/* eat this, Billy-boy */
   1794 	  gates = (HINF **) Hmalloc (sizeof (HINF *) * 10);
   1795 	gp = gethostpoop (optarg, o_nflag);
   1796 	if (gp)
   1797 	  gates[gatesidx] = gp;
   1798 	gatesidx++;
   1799 	break;
   1800       case 'h':
   1801 	errno = 0;
   1802 #ifdef HAVE_HELP
   1803 	helpme();			/* exits by itself */
   1804 #else
   1805 	bail ("no help available, dork -- RTFS");
   1806 #endif
   1807       case 'i':				/* line-interval time */
   1808 	o_interval = atoi (optarg) & 0xffff;
   1809 #ifdef WIN32
   1810 	o_interval *= 1000;
   1811 #endif
   1812 	if (! o_interval)
   1813 	  bail ("invalid interval time %s", optarg);
   1814 	break;
   1815       case 'l':				/* listen mode */
   1816 	o_listen++; break;
   1817       case 'n':				/* numeric-only, no DNS lookups */
   1818 	o_nflag++; break;
   1819       case 'o':				/* hexdump log */
   1820 	stage = (unsigned char *) optarg;
   1821 	o_wfile++; break;
   1822       case 'p':				/* local source port */
   1823 	o_lport = getportpoop (optarg, 0);
   1824 	if (o_lport == 0)
   1825 	  bail ("invalid local port %s", optarg);
   1826 	break;
   1827       case 'r':				/* randomize various things */
   1828 	o_random++; break;
   1829       case 's':				/* local source address */
   1830 /* do a full lookup [since everything else goes through the same mill],
   1831    unless -n was previously specified.  In fact, careful placement of -n can
   1832    be useful, so we'll still pass o_nflag here instead of forcing numeric.  */
   1833 	wherefrom = gethostpoop (optarg, o_nflag);
   1834 	ouraddr = &wherefrom->iaddrs[0];
   1835 	break;
   1836 #ifdef TELNET
   1837       case 't':				/* do telnet fakeout */
   1838 	o_tn++; break;
   1839 #endif /* TELNET */
   1840 
   1841       case 'c':				/* do telnet fakeout */
   1842 	o_crlf++; break;
   1843       case 'u':				/* use UDP */
   1844 	o_udpmode++; break;
   1845       case 'v':				/* verbose */
   1846 	o_verbose++; break;
   1847       case 'w':				/* wait time */
   1848 	o_wait = atoi (optarg);
   1849 	if (o_wait <= 0)
   1850 	  bail ("invalid wait-time %s", optarg);
   1851 	timer1 = (struct timeval *) Hmalloc (sizeof (struct timeval));
   1852 	timer2 = (struct timeval *) Hmalloc (sizeof (struct timeval));
   1853 	timer1->tv_sec = o_wait;	/* we need two.  see readwrite()... */
   1854 	break;
   1855       case 'z':				/* little or no data xfer */
   1856 	o_zero++;
   1857 	break;
   1858       default:
   1859 	errno = 0;
   1860 	bail ("nc -h for help");
   1861     } /* switch x */
   1862   } /* while getopt */
   1863 
   1864 /* other misc initialization */
   1865 #ifndef WIN32  /* Win32 doesn't like to mix file handles and sockets */
   1866   Debug (("fd_set size %d", sizeof (*ding1)))	/* how big *is* it? */
   1867   FD_SET (0, ding1);			/* stdin *is* initially open */
   1868 #endif
   1869   if (o_random) {
   1870     SRAND (time (0));
   1871     randports = Hmalloc (65536);	/* big flag array for ports */
   1872   }
   1873 #ifdef GAPING_SECURITY_HOLE
   1874   if (pr00gie) {
   1875     close (0);				/* won't need stdin */
   1876     o_wfile = 0;			/* -o with -e is meaningless! */
   1877     ofd = 0;
   1878   }
   1879 #endif /* G_S_H */
   1880   if (o_wfile) {
   1881     ofd = open (stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
   1882     if (ofd <= 0)			/* must be > extant 0/1/2 */
   1883       bail ("can't open %s", stage);
   1884     stage = (unsigned char *) Hmalloc (100);
   1885   }
   1886  
   1887 
   1888 /* optind is now index of first non -x arg */
   1889 Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
   1890 /* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */
   1891 /* gonna only use first addr of host-list, like our IQ was normal; if you wanna
   1892    get fancy with addresses, look up the list yourself and plug 'em in for now.
   1893    unless we finally implement -a, that is. */
   1894   if (argv[optind])
   1895     whereto = gethostpoop (argv[optind], o_nflag);
   1896   if (whereto && whereto->iaddrs)
   1897     themaddr = &whereto->iaddrs[0];
   1898   if (themaddr)
   1899     optind++;				/* skip past valid host lookup */
   1900   errno = 0;
   1901 #ifndef WIN32
   1902   h_errno = 0;
   1903 #endif
   1904 
   1905 /* Handle listen mode here, and exit afterward.  Only does one connect;
   1906    this is arguably the right thing to do.  A "persistent listen-and-fork"
   1907    mode a la inetd has been thought about, but not implemented.  A tiny
   1908    wrapper script can handle such things... */
   1909   if (o_listen) {
   1910     curport = 0;			/* rem port *can* be zero here... */
   1911     if (argv[optind]) {			/* any rem-port-args? */
   1912       curport = getportpoop (argv[optind], 0);
   1913       if (curport == 0)			/* if given, demand correctness */
   1914 	bail ("invalid port %s", argv[optind]);
   1915     } /* if port-arg */
   1916     netfd = dolisten (themaddr, curport, ouraddr, o_lport);
   1917 /* dolisten does its own connect reporting, so we don't holler anything here */
   1918     if (netfd > 0) {
   1919 #ifdef GAPING_SECURITY_HOLE
   1920 	if (pr00gie)			/* -e given? */
   1921 		doexec (netfd);
   1922 #ifdef WIN32
   1923 	if (!pr00gie)  // doexec does the read/write for win32
   1924 #endif
   1925 
   1926 #endif /* GAPING_SECURITY_HOLE */
   1927     x = readwrite (netfd);		/* it even works with UDP! */
   1928 	if (o_verbose > 1)		/* normally we don't care */
   1929 		holler (wrote_txt, wrote_net, wrote_out);
   1930 	if (cycle == 1)
   1931 		goto recycle;
   1932 	exit (x);				/* "pack out yer trash" */
   1933     } else
   1934       bail ("no connection");
   1935   } /* o_listen */
   1936 
   1937 /* fall thru to outbound connects.  Now we're more picky about args... */
   1938   if (! themaddr)
   1939     bail ("no destination");
   1940   if (argv[optind] == NULL)
   1941     bail ("no port[s] to connect to");
   1942   if (argv[optind + 1])		/* look ahead: any more port args given? */
   1943     Single = 0;				/* multi-mode, case A */
   1944   ourport = o_lport;			/* which can be 0 */
   1945 
   1946 /* everything from here down is treated as as ports and/or ranges thereof, so
   1947    it's all enclosed in this big ol' argv-parsin' loop.  Any randomization is
   1948    done within each given *range*, but in separate chunks per each succeeding
   1949    argument, so we can control the pattern somewhat. */
   1950   while (argv[optind]) {
   1951     hiport = loport = 0;
   1952     cp = strchr (argv[optind], '-');	/* nn-mm range? */
   1953     if (cp) {
   1954       *cp = '\0';
   1955       cp++;
   1956       hiport = getportpoop (cp, 0);
   1957       if (hiport == 0)
   1958 	bail ("invalid port %s", cp);
   1959     } /* if found a dash */
   1960     loport = getportpoop (argv[optind], 0);
   1961     if (loport == 0)
   1962       bail ("invalid port %s", argv[optind]);
   1963     if (hiport > loport) {		/* was it genuinely a range? */
   1964       Single = 0;			/* multi-mode, case B */
   1965       curport = hiport;			/* start high by default */
   1966       if (o_random) {			/* maybe populate the random array */
   1967 	loadports (randports, loport, hiport);
   1968 	curport = nextport (randports);
   1969       }
   1970     } else			/* not a range, including args like "25-25" */
   1971       curport = loport;
   1972 Debug (("Single %d, curport %d", Single, curport))
   1973 
   1974 /* Now start connecting to these things.  curport is already preloaded. */
   1975     while (loport <= curport) {
   1976       if ((! o_lport) && (o_random)) {	/* -p overrides random local-port */
   1977 	ourport = (RAND() & 0xffff);	/* random local-bind -- well above */
   1978 	if (ourport < 8192)		/* resv and any likely listeners??? */
   1979 	  ourport += 8192;		/* xxx: may still conflict; use -s? */
   1980       }
   1981       curport = getportpoop (NULL, curport);
   1982       netfd = doconnect (themaddr, curport, ouraddr, ourport);
   1983 Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
   1984       if (netfd > 0)
   1985 	if (o_zero && o_udpmode)	/* if UDP scanning... */
   1986 	  netfd = udptest (netfd, themaddr);
   1987       if (netfd > 0) {			/* Yow, are we OPEN YET?! */
   1988 		x = 0;				/* pre-exit status */
   1989 		holler ("%s [%s] %d (%s) open",
   1990 	  	whereto->name, whereto->addrs[0], curport, portpoop->name);
   1991 #ifdef GAPING_SECURITY_HOLE
   1992 		if (pr00gie)			/* exec is valid for outbound, too */
   1993 	doexec (netfd);
   1994 #endif /* GAPING_SECURITY_HOLE */
   1995 	if (! o_zero)
   1996 #ifdef WIN32 
   1997 #ifdef GAPING_SECURITY_HOLE
   1998 	if (!pr00gie)  // doexec does the read/write for win32
   1999 #endif
   2000 #endif
   2001 	  x = readwrite (netfd);	/* go shovel shit */
   2002       } else { /* no netfd... */
   2003 	x = 1;				/* preload exit status for later */
   2004 /* if we're scanning at a "one -v" verbosity level, don't print refusals.
   2005    Give it another -v if you want to see everything. */
   2006 #ifdef WIN32
   2007 	if ((Single || (o_verbose > 1)) || (h_errno != WSAECONNREFUSED))
   2008 #else
   2009 	if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
   2010 #endif
   2011 	  holler ("%s [%s] %d (%s)",
   2012 	    whereto->name, whereto->addrs[0], curport, portpoop->name);
   2013       } /* if netfd */
   2014 #ifdef WIN32
   2015 	  shutdown(netfd, 0x02);  /* Kirby */
   2016       closesocket (netfd);			/* just in case we didn't already */
   2017 #else
   2018       close (netfd);			/* just in case we didn't already */
   2019 #endif
   2020       if (o_interval)
   2021 	sleep (o_interval);		/* if -i, delay between ports too */
   2022       if (o_random)
   2023 	curport = nextport (randports);
   2024       else
   2025 	curport--;			/* just decrement... */
   2026     } /* while curport within current range */
   2027     optind++;
   2028   } /* while remaining port-args -- end of big argv-ports loop*/
   2029 
   2030   errno = 0;
   2031   if (o_verbose > 1)		/* normally we don't care */
   2032     holler ("sent %d, rcvd %d", wrote_net, wrote_out);
   2033 
   2034 #ifdef WIN32
   2035     WSACleanup(); 
   2036 #endif
   2037 
   2038   	if (cycle == 1)
   2039 		goto recycle;
   2040 
   2041   if (Single)
   2042     exit (x);			/* give us status on one connection */
   2043   exit (0);			/* otherwise, we're just done */
   2044   return(0);
   2045 } /* main */
   2046 
   2047 #ifdef HAVE_HELP		/* unless we wanna be *really* cryptic */
   2048 /* helpme :
   2049    the obvious */
   2050 int helpme()
   2051 {
   2052   o_verbose = 1;
   2053   holler ("[v1.12 NT http://eternallybored.org/misc/netcat/]\n\
   2054 connect to somewhere:	nc [-options] hostname port[s] [ports] ... \n\
   2055 listen for inbound:	nc -l -p port [options] [hostname] [port]\n\
   2056 options:");
   2057   holler ("\
   2058 	-d		detach from console, background mode\n");
   2059 
   2060 #ifdef GAPING_SECURITY_HOLE	/* needs to be separate holler() */
   2061   holler ("\
   2062 	-e prog		inbound program to exec [dangerous!!]");
   2063 #endif
   2064   holler ("\
   2065 	-g gateway	source-routing hop point[s], up to 8\n\
   2066 	-G num		source-routing pointer: 4, 8, 12, ...\n\
   2067 	-h		this cruft\n\
   2068 	-i secs		delay interval for lines sent, ports scanned\n\
   2069 	-l		listen mode, for inbound connects\n\
   2070 	-L		listen harder, re-listen on socket close\n\
   2071 	-n		numeric-only IP addresses, no DNS\n\
   2072 	-o file		hex dump of traffic\n\
   2073 	-p port		local port number\n\
   2074 	-r		randomize local and remote ports\n\
   2075 	-s addr		local source address");
   2076 #ifdef TELNET
   2077   holler ("\
   2078 	-t		answer TELNET negotiation");
   2079 #endif
   2080   holler ("\
   2081 	-c		send CRLF instead of just LF\n\
   2082 	-u		UDP mode\n\
   2083 	-v		verbose [use twice to be more verbose]\n\
   2084 	-w secs		timeout for connects and final net reads\n\
   2085 	-z		zero-I/O mode [used for scanning]");
   2086   bail ("port numbers can be individual or ranges: m-n [inclusive]");
   2087   return(0);
   2088 } /* helpme */
   2089 #endif /* HAVE_HELP */
   2090 
   2091 
   2092 
   2093 
   2094 /* None genuine without this seal!  _H*/