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