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
#if 0
34
#undef _POSIX_SOURCE		/* might need this for something? */
35
#endif
36
#define HAVE_BIND		/* ASSUMPTION -- seems to work everywhere! */
37
#define HAVE_HELP		/* undefine if you dont want the help text */
38
#if 0
39
#define ANAL			/* if you want case-sensitive DNS matching */
40
#endif
41
42
#ifdef HAVE_STDLIB_H
43
#include <stdlib.h>
44
#else
45
#include <malloc.h>
46
#endif
47
#ifdef HAVE_SELECT_H		/* random SV variants need this */
48
#include <sys/select.h>
49
#endif
50
51
/* have to do this *before* including types.h. xxx: Linux still has it wrong */
52
#ifdef FD_SETSIZE		/* should be in types.h, butcha never know. */
53
#undef FD_SETSIZE		/* if we ever need more than 16 active */
54
#endif				/* fd's, something is horribly wrong! */
55
#define FD_SETSIZE 16		/* <-- this'll give us a long anyways, wtf */
56
#include <sys/types.h>		/* *now* do it.  Sigh, this is broken */
57
58
#ifdef HAVE_RANDOM		/* aficionados of ?rand48() should realize */
59
#define SRAND srandom		/* that this doesn't need *strong* random */
60
#define RAND random		/* numbers just to mix up port numbers!! */
61
#else
62
#define SRAND srand
63
#define RAND rand
64
#endif /* HAVE_RANDOM */
65
66
/* includes: */
67
#include <sys/time.h>		/* timeval, time_t */
68
#include <setjmp.h>		/* jmp_buf et al */
69
#include <sys/socket.h>		/* basics, SO_ and AF_ defs, sockaddr, ... */
70
71
#include <netinet/in.h>		/* sockaddr_in, htons, in_addr */
72
73
#if 0
74
#include <netinet/in_systm.h>	/* misc crud that netinet/ip.h references */
75
#endif
76
#include <netinet/ip.h>		/* IPOPT_LSRR, header stuff */
77
#include <netdb.h>		/* hostent, gethostby*, getservby* */
78
#include <arpa/inet.h>		/* inet_ntoa */
79
#include <stdio.h>
80
#include <string.h>		/* strcpy, strchr, yadda yadda */
81
#include <errno.h>
82
#include <signal.h>
83
#include <fcntl.h>		/* O_WRONLY et al */
84
85
/* handy stuff: */
86
#define SA struct sockaddr	/* socket overgeneralization braindeath */
87
#define SAI struct sockaddr_in	/* ... whoever came up with this model */
88
#define IA struct in_addr	/* ... should be taken out and shot, */
89
				/* ... not that TLI is any better.  sigh.. */
90
#define SLEAZE_PORT 31337	/* for UDP-scan RTT trick, change if ya want */
91
#define USHORT unsigned short	/* use these for options an' stuff */
92
#define BIGSIZ 8192		/* big buffers */
93
94
#ifndef INADDR_NONE
95
#define INADDR_NONE 0xffffffff
96
#endif
97
#ifdef MAXHOSTNAMELEN
98
#undef MAXHOSTNAMELEN		/* might be too small on aix, so fix it */
99
#endif
100
#define MAXHOSTNAMELEN 256
101
102
struct host_poop {
103
  char name[MAXHOSTNAMELEN];	/* dns name */
104
  char addrs[8][24];		/* ascii-format IP addresses */
105
  struct in_addr iaddrs[8];	/* real addresses: in_addr.s_addr: ulong */
106
};
107
#define HINF struct host_poop
108
109
struct port_poop {
110
  char name [64];		/* name in /etc/services */
111
  char anum [8];		/* ascii-format number */
112
  USHORT num;			/* real host-order number */
113
};
114
#define PINF struct port_poop
115
116
/* globals: */
117
jmp_buf jbuf;			/* timer crud */
118
int jval = 0;			/* timer crud */
119
int netfd = -1;
120
int ofd = 0;			/* hexdump output fd */
121
static char unknown[] = "(UNKNOWN)";
122
static char p_tcp[] = "tcp";	/* for getservby* */
123
static char p_udp[] = "udp";
124
#ifdef HAVE_BIND
125
extern int h_errno;
126
/* stolen almost wholesale from bsd herror.c */
127
static char * h_errs[] = {
128
  "Error 0",				/* but we *don't* use this */
129
  "Unknown host",			/* 1 HOST_NOT_FOUND */
130
  "Host name lookup failure",		/* 2 TRY_AGAIN */
131
  "Unknown server error",		/* 3 NO_RECOVERY */
132
  "No address associated with name",	/* 4 NO_ADDRESS */
133
};
134
#else
135
int h_errno;			/* just so we *do* have it available */
136
#endif /* HAVE_BIND */
137
int gatesidx = 0;		/* LSRR hop count */
138
int gatesptr = 4;		/* initial LSRR pointer, settable */
139
USHORT Single = 1;		/* zero if scanning */
140
unsigned int insaved = 0;	/* stdin-buffer size for multi-mode */
141
unsigned int wrote_out = 0;	/* total stdout bytes */
142
unsigned int wrote_net = 0;	/* total net bytes */
143
static char wrote_txt[] = " sent %d, rcvd %d";
144
static char hexnibs[20] = "0123456789abcdef  ";
145
146
/* will malloc up the following globals: */
147
struct timeval * timer1 = NULL;
148
struct timeval * timer2 = NULL;
149
SAI * lclend = NULL;		/* sockaddr_in structs */
150
SAI * remend = NULL;
151
HINF ** gates = NULL;		/* LSRR hop hostpoop */
152
char * optbuf = NULL;		/* LSRR or sockopts */
153
char * bigbuf_in;		/* data buffers */
154
char * bigbuf_net;
155
fd_set * ding1;			/* for select loop */
156
fd_set * ding2;
157
PINF * portpoop = NULL;		/* for getportpoop / getservby* */
158
unsigned char * stage = NULL;	/* hexdump line buffer */
159
160
/* global cmd flags: */
161
USHORT o_alla = 0;
162
unsigned int o_interval = 0;
163
USHORT o_listen = 0;
164
USHORT o_nflag = 0;
165
USHORT o_wfile = 0;
166
USHORT o_random = 0;
167
USHORT o_udpmode = 0;
168
USHORT o_verbose = 0;
169
unsigned int o_wait = 0;
170
USHORT o_zero = 0;
171
/* o_tn in optional section */
172
173
/* Debug macro: squirt whatever message and sleep a bit so we can see it go
174
   by.  need to call like Debug ((stuff)) [with no ; ] so macro args match!
175
   Beware: writes to stdOUT... */
176
#ifdef DEBUG
177
#define Debug(x) printf x; printf ("\n"); fflush (stdout); sleep (1);
178
#else
179
#define Debug(x)	/* nil... */
180
#endif
181
182
183
/* support routines -- the bulk of this thing.  Placed in such an order that
184
   we don't have to forward-declare anything: */
185
186
/* holler :
187
   fake varargs -- need to do this way because we wind up calling through
188
   more levels of indirection than vanilla varargs can handle, and not all
189
   machines have vfprintf/vsyslog/whatever!  6 params oughta be enough. */
190
void holler (str, p1, p2, p3, p4, p5, p6)
191
  char * str;
192
  char * p1, * p2, * p3, * p4, * p5, * p6;
193
{
194
  if (o_verbose) {
195
    fprintf (stderr, str, p1, p2, p3, p4, p5, p6);
196
#ifdef HAVE_BIND
197
    if (h_errno) {		/* if host-lookup variety of error ... */
198
      if (h_errno > 4)		/* oh no you don't, either */
199
	fprintf (stderr, "preposterous h_errno: %d", h_errno);
200
      else
201
	fprintf (stderr, h_errs[h_errno]);	/* handle it here */
202
      h_errno = 0;				/* and reset for next call */
203
    }
204
#endif
205
    if (errno) {		/* this gives funny-looking messages, but */
206
      perror (" ");		/* it's more portable than sys_errlist[]... */
207
    } else			/* xxx: do something better?  */
208
      fprintf (stderr, "\n");
209
    fflush (stderr);
210
  }
211
} /* holler */
212
213
/* bail :
214
   error-exit handler, callable from anywhere */
215
void bail (str, p1, p2, p3, p4, p5, p6)
216
  char * str;
217
  char * p1, * p2, * p3, * p4, * p5, * p6;
218
{
219
  o_verbose = 1;
220
  holler (str, p1, p2, p3, p4, p5, p6);
221
  close (netfd);
222
  sleep (1);
223
  exit (1);
224
} /* bail */
225
226
/* catch :
227
   no-brainer interrupt handler */
228
void catch ()
229
{
230
  errno = 0;
231
  if (o_verbose > 1)		/* normally we don't care */
232
    bail (wrote_txt, wrote_net, wrote_out);
233
  bail (" punt!");
234
}
235
236
/* timeout and other signal handling cruft */
237
void 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 */
248
void 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. */
266
char * 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... */
282
unsigned 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! */
297
Debug (("findline returning %d", x))
298
      return (x);
299
    }
300
    p++;
301
  } /* for */
302
Debug (("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. */
311
int 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. */
336
HINF * 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
      strncpy (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. */
436
USHORT 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
501
gp_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. */
516
USHORT 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... */
552
void 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
571
char * 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!! */
579
doexec (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;
593
Debug (("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. */
606
int 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 */
618
newskt:
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.
685
Option comes after IP-hdr dest addr in packet, padded to *4, and ihl > 5.
686
IHL 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
693
If we want to route A -> B via hops C and D, we must add C, D, *and* B to the
694
options list.  Why?  Because when we hand the kernel A -> B with list C, D, B
695
the "send shuffle" inside the kernel changes it into A -> C with list D, B and
696
the outbound packet gets sent to C.  If B wasn't also in the hops list, the
697
final destination would have been lost at this point.
698
699
When C gets the packet, it changes it to A -> D with list C', B where C' is
700
the interface address that C used to forward the packet.  This "records" the
701
route hop from B's point of view, i.e. which address points "toward" B.  This
702
is to make B better able to return the packets.  The pointer gets bumped by 4,
703
so that D does the right thing instead of trying to forward back to C.
704
705
When B finally gets the packet, it sees that the pointer is at the end of the
706
LSRR list and is thus "completed".  B will then try to use the packet instead
707
of forwarding it, i.e. deliver it up to some application.
708
709
Note that by moving the pointer yourself, you could send the traffic directly
710
to B but have it return via your preconstructed source-route.  Playing with
711
this and watching "tcpdump -v" is the best way to understand what's going on.
712
713
Only works for TCP in BSD-flavor kernels.  UDP is a loss; udp_input calls
714
stripoptions() early on, and the code to save the srcrt is notdef'ed.
715
Linux 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... */
773
int 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);
835
Debug (("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
865
whoisit:
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");
882
Debug (("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 */
896
dol_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
938
dol_tmo:
939
  errno = ETIMEDOUT;			/* fake it */
940
dol_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. */
955
int udptest (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:
990
D 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... */
998
void 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
1080
USHORT 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. */
1087
void 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 */
1116
notiac:
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. */
1125
int 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
    if (rr == 0) {
1185
	if (! FD_ISSET (0, ding1))
1186
	  netretry--;			/* we actually try a coupla times. */
1187
	if (! netretry) {
1188
	  if (o_verbose > 1)		/* normally we don't care */
1189
	    holler ("net timeout");
1190
	  close (fd);
1191
	  return (0);			/* not an error! */
1192
	}
1193
    } /* select timeout */
1194
/* xxx: should we check the exception fds too?  The read fds seem to give
1195
   us the right info, and none of the examples I found bothered. */
1196
1197
/* Ding!!  Something arrived, go check all the incoming hoppers, net first */
1198
    if (FD_ISSET (fd, ding2)) {		/* net: ding! */
1199
	rr = read (fd, bigbuf_net, BIGSIZ);
1200
	if (rr <= 0) {
1201
	  FD_CLR (fd, ding1);		/* net closed, we'll finish up... */
1202
	  rzleft = 0;			/* can't write anymore: broken pipe */
1203
	} else {
1204
	  rnleft = rr;
1205
	  np = bigbuf_net;
1206
#ifdef TELNET
1207
	  if (o_tn)
1208
	    atelnet (np, rr);		/* fake out telnet stuff */
1209
#endif /* TELNET */
1210
	} /* if rr */
1211
Debug (("got %d from the net, errno %d", rr, errno))
1212
    } /* net:ding */
1213
1214
/* if we're in "slowly" mode there's probably still stuff in the stdin
1215
   buffer, so don't read unless we really need MORE INPUT!  MORE INPUT! */
1216
    if (rzleft)
1217
	goto shovel;
1218
1219
/* okay, suck more stdin */
1220
    if (FD_ISSET (0, ding2)) {		/* stdin: ding! */
1221
	rr = read (0, bigbuf_in, BIGSIZ);
1222
/* Considered making reads here smaller for UDP mode, but 8192-byte
1223
   mobygrams are kinda fun and exercise the reassembler. */
1224
	if (rr <= 0) {			/* at end, or fukt, or ... */
1225
	  FD_CLR (0, ding1);		/* disable and close stdin */
1226
	  close (0);
1227
	} else {
1228
	  rzleft = rr;
1229
	  zp = bigbuf_in;
1230
/* special case for multi-mode -- we'll want to send this one buffer to every
1231
   open TCP port or every UDP attempt, so save its size and clean up stdin */
1232
	  if (! Single) {		/* we might be scanning... */
1233
	    insaved = rr;		/* save len */
1234
	    FD_CLR (0, ding1);		/* disable further junk from stdin */
1235
	    close (0);			/* really, I mean it */
1236
	  } /* Single */
1237
	} /* if rr/read */
1238
    } /* stdin:ding */
1239
1240
shovel:
1241
/* now that we've dingdonged all our thingdings, send off the results.
1242
   Geez, why does this look an awful lot like the big loop in "rsh"? ...
1243
   not sure if the order of this matters, but write net -> stdout first. */
1244
1245
/* sanity check.  Works because they're both unsigned... */
1246
    if ((rzleft > 8200) || (rnleft > 8200)) {
1247
	holler ("Bogus buffers: %d, %d", rzleft, rnleft);
1248
	rzleft = rnleft = 0;
1249
    }
1250
/* net write retries sometimes happen on UDP connections */
1251
    if (! wretry) {			/* is something hung? */
1252
	holler ("too many output retries");
1253
	return (1);
1254
    }
1255
    if (rnleft) {
1256
	rr = write (1, np, rnleft);
1257
	if (rr > 0) {
1258
	  if (o_wfile)
1259
	    oprint (1, np, rr);		/* log the stdout */
1260
	  np += rr;			/* fix up ptrs and whatnot */
1261
	  rnleft -= rr;			/* will get sanity-checked above */
1262
	  wrote_out += rr;		/* global count */
1263
	}
1264
Debug (("wrote %d to stdout, errno %d", rr, errno))
1265
    } /* rnleft */
1266
    if (rzleft) {
1267
	if (o_interval)			/* in "slowly" mode ?? */
1268
	  rr = findline (zp, rzleft);
1269
	else
1270
	  rr = rzleft;
1271
	rr = write (fd, zp, rr);	/* one line, or the whole buffer */
1272
	if (rr > 0) {
1273
	  if (o_wfile)
1274
	    oprint (0, zp, rr);		/* log what got sent */
1275
	  zp += rr;
1276
	  rzleft -= rr;
1277
	  wrote_net += rr;		/* global count */
1278
	}
1279
Debug (("wrote %d to net, errno %d", rr, errno))
1280
    } /* rzleft */
1281
    if (o_interval) {			/* cycle between slow lines, or ... */
1282
	sleep (o_interval);
1283
	errno = 0;			/* clear from sleep */
1284
	continue;			/* ...with hairy select loop... */
1285
    }
1286
    if ((rzleft) || (rnleft)) {		/* shovel that shit till they ain't */
1287
	wretry--;			/* none left, and get another load */
1288
	goto shovel;
1289
    }
1290
  } /* while ding1:netfd is open */
1291
1292
/* XXX: maybe want a more graceful shutdown() here, or screw around with
1293
   linger times??  I suspect that I don't need to since I'm always doing
1294
   blocking reads and writes and my own manual "last ditch" efforts to read
1295
   the net again after a timeout.  I haven't seen any screwups yet, but it's
1296
   not like my test network is particularly busy... */
1297
  close (fd);
1298
  return (0);
1299
} /* readwrite */
1300
1301
/* main :
1302
   now we pull it all together... */
1303
int main (argc, argv)
1304
  int argc;
1305
  char ** argv;
1306
{
1307
#ifndef HAVE_GETOPT
1308
  extern char * optarg;
1309
  extern int optind, optopt;
1310
#endif
1311
  register int x;
1312
  register char *cp;
1313
  HINF * gp;
1314
  HINF * whereto = NULL;
1315
  HINF * wherefrom = NULL;
1316
  IA * ouraddr = NULL;
1317
  IA * themaddr = NULL;
1318
  USHORT o_lport = 0;
1319
  USHORT ourport = 0;
1320
  USHORT loport = 0;		/* for scanning stuff */
1321
  USHORT hiport = 0;
1322
  USHORT curport = 0;
1323
  char * randports = NULL;
1324
1325
#ifdef HAVE_BIND
1326
/* can *you* say "cc -yaddayadda netcat.c -lresolv -l44bsd" on SunLOSs? */
1327
  res_init();
1328
#endif
1329
/* I was in this barbershop quartet in Skokie IL ... */
1330
/* round up the usual suspects, i.e. malloc up all the stuff we need */
1331
  lclend = (SAI *) Hmalloc (sizeof (SA));
1332
  remend = (SAI *) Hmalloc (sizeof (SA));
1333
  bigbuf_in = Hmalloc (BIGSIZ);
1334
  bigbuf_net = Hmalloc (BIGSIZ);
1335
  ding1 = (fd_set *) Hmalloc (sizeof (fd_set));
1336
  ding2 = (fd_set *) Hmalloc (sizeof (fd_set));
1337
  portpoop = (PINF *) Hmalloc (sizeof (PINF));
1338
1339
  errno = 0;
1340
  gatesptr = 4;
1341
  h_errno = 0;
1342
1343
/* catch a signal or two for cleanup */
1344
  signal (SIGINT, catch);
1345
  signal (SIGQUIT, catch);
1346
  signal (SIGTERM, catch);
1347
/* and suppress others... */
1348
#ifdef SIGURG
1349
  signal (SIGURG, SIG_IGN);
1350
#endif
1351
#ifdef SIGPIPE
1352
  signal (SIGPIPE, SIG_IGN);		/* important! */
1353
#endif
1354
1355
/* if no args given at all, get 'em from stdin, construct an argv, and hand
1356
   anything left over to readwrite(). */
1357
  if (argc == 1) {
1358
    cp = argv[0];
1359
    argv = (char **) Hmalloc (128 * sizeof (char *));	/* XXX: 128? */
1360
    argv[0] = cp;			/* leave old prog name intact */
1361
    cp = Hmalloc (BIGSIZ);
1362
    argv[1] = cp;			/* head of new arg block */
1363
    fprintf (stderr, "Cmd line: ");
1364
    fflush (stderr);		/* I dont care if it's unbuffered or not! */
1365
    insaved = read (0, cp, BIGSIZ);	/* we're gonna fake fgets() here */
1366
    if (insaved <= 0)
1367
      bail ("wrong");
1368
    x = findline (cp, insaved);
1369
    if (x)
1370
      insaved -= x;		/* remaining chunk size to be sent */
1371
    if (insaved)		/* which might be zero... */
1372
      memcpy (bigbuf_in, &cp[x], insaved);
1373
    cp = strchr (argv[1], '\n');
1374
    if (cp)
1375
      *cp = '\0';
1376
    cp = strchr (argv[1], '\r');	/* look for ^M too */
1377
    if (cp)
1378
      *cp = '\0';
1379
1380
/* find and stash pointers to remaining new "args" */
1381
    cp = argv[1];
1382
    cp++;				/* skip past first char */
1383
    x = 2;				/* we know argv 0 and 1 already */
1384
    for (; *cp != '\0'; cp++) {
1385
      if (*cp == ' ') {
1386
	*cp = '\0';			/* smash all spaces */
1387
	continue;
1388
      } else {
1389
	if (*(cp-1) == '\0') {
1390
	  argv[x] = cp;
1391
	  x++;
1392
	}
1393
      } /* if space */
1394
    } /* for cp */
1395
    argc = x;
1396
  } /* if no args given */
1397
1398
/* If your shitbox doesn't have getopt, step into the nineties already. */
1399
/* optarg, optind = next-argv-component [i.e. flag arg]; optopt = last-char */
1400
  while ((x = getopt (argc, argv, "ae:g:G:hi:lno:p:rs:tuvw:z")) != EOF) {
1401
/* Debug (("in go: x now %c, optarg %x optind %d", x, optarg, optind)) */
1402
    switch (x) {
1403
      case 'a':
1404
	bail ("all-A-records NIY");
1405
	o_alla++; break;
1406
#ifdef GAPING_SECURITY_HOLE
1407
      case 'e':				/* prog to exec */
1408
	pr00gie = optarg;
1409
	break;
1410
#endif
1411
      case 'G':				/* srcrt gateways pointer val */
1412
	x = atoi (optarg);
1413
	if ((x) && (x == (x & 0x1c)))	/* mask off bits of fukt values */
1414
	  gatesptr = x;
1415
	else
1416
	  bail ("invalid hop pointer %d, must be multiple of 4 <= 28", x);
1417
	break;
1418
      case 'g':				/* srcroute hop[s] */
1419
	if (gatesidx > 8)
1420
	  bail ("too many -g hops");
1421
	if (gates == NULL)		/* eat this, Billy-boy */
1422
	  gates = (HINF **) Hmalloc (sizeof (HINF *) * 10);
1423
	gp = gethostpoop (optarg, o_nflag);
1424
	if (gp)
1425
	  gates[gatesidx] = gp;
1426
	gatesidx++;
1427
	break;
1428
      case 'h':
1429
	errno = 0;
1430
#ifdef HAVE_HELP
1431
	helpme();			/* exits by itself */
1432
#else
1433
	bail ("no help available, dork -- RTFS");
1434
#endif
1435
      case 'i':				/* line-interval time */
1436
	o_interval = atoi (optarg) & 0xffff;
1437
	if (! o_interval)
1438
	  bail ("invalid interval time %s", optarg);
1439
	break;
1440
      case 'l':				/* listen mode */
1441
	o_listen++; break;
1442
      case 'n':				/* numeric-only, no DNS lookups */
1443
	o_nflag++; break;
1444
      case 'o':				/* hexdump log */
1445
	stage = (unsigned char *) optarg;
1446
	o_wfile++; break;
1447
      case 'p':				/* local source port */
1448
	o_lport = getportpoop (optarg, 0);
1449
	if (o_lport == 0)
1450
	  bail ("invalid local port %s", optarg);
1451
	break;
1452
      case 'r':				/* randomize various things */
1453
	o_random++; break;
1454
      case 's':				/* local source address */
1455
/* do a full lookup [since everything else goes through the same mill],
1456
   unless -n was previously specified.  In fact, careful placement of -n can
1457
   be useful, so we'll still pass o_nflag here instead of forcing numeric.  */
1458
	wherefrom = gethostpoop (optarg, o_nflag);
1459
	ouraddr = &wherefrom->iaddrs[0];
1460
	break;
1461
#ifdef TELNET
1462
      case 't':				/* do telnet fakeout */
1463
	o_tn++; break;
1464
#endif /* TELNET */
1465
      case 'u':				/* use UDP */
1466
	o_udpmode++; break;
1467
      case 'v':				/* verbose */
1468
	o_verbose++; break;
1469
      case 'w':				/* wait time */
1470
	o_wait = atoi (optarg);
1471
	if (o_wait <= 0)
1472
	  bail ("invalid wait-time %s", optarg);
1473
	timer1 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1474
	timer2 = (struct timeval *) Hmalloc (sizeof (struct timeval));
1475
	timer1->tv_sec = o_wait;	/* we need two.  see readwrite()... */
1476
	break;
1477
      case 'z':				/* little or no data xfer */
1478
	o_zero++;
1479
	break;
1480
      default:
1481
	errno = 0;
1482
	bail ("nc -h for help");
1483
    } /* switch x */
1484
  } /* while getopt */
1485
1486
/* other misc initialization */
1487
Debug (("fd_set size %d", sizeof (*ding1)))	/* how big *is* it? */
1488
  FD_SET (0, ding1);			/* stdin *is* initially open */
1489
  if (o_random) {
1490
    SRAND (time (0));
1491
    randports = Hmalloc (65536);	/* big flag array for ports */
1492
  }
1493
#ifdef GAPING_SECURITY_HOLE
1494
  if (pr00gie) {
1495
    close (0);				/* won't need stdin */
1496
    o_wfile = 0;			/* -o with -e is meaningless! */
1497
    ofd = 0;
1498
  }
1499
#endif /* G_S_H */
1500
  if (o_wfile) {
1501
    ofd = open (stage, O_WRONLY | O_CREAT | O_TRUNC, 0664);
1502
    if (ofd <= 0)			/* must be > extant 0/1/2 */
1503
      bail ("can't open %s", stage);
1504
    stage = (unsigned char *) Hmalloc (100);
1505
  }
1506
1507
/* optind is now index of first non -x arg */
1508
Debug (("after go: x now %c, optarg %x optind %d", x, optarg, optind))
1509
/* Debug (("optind up to %d at host-arg %s", optind, argv[optind])) */
1510
/* gonna only use first addr of host-list, like our IQ was normal; if you wanna
1511
   get fancy with addresses, look up the list yourself and plug 'em in for now.
1512
   unless we finally implement -a, that is. */
1513
  if (argv[optind])
1514
    whereto = gethostpoop (argv[optind], o_nflag);
1515
  if (whereto && whereto->iaddrs)
1516
    themaddr = &whereto->iaddrs[0];
1517
  if (themaddr)
1518
    optind++;				/* skip past valid host lookup */
1519
  errno = 0;
1520
  h_errno = 0;
1521
1522
/* Handle listen mode here, and exit afterward.  Only does one connect;
1523
   this is arguably the right thing to do.  A "persistent listen-and-fork"
1524
   mode a la inetd has been thought about, but not implemented.  A tiny
1525
   wrapper script can handle such things... */
1526
  if (o_listen) {
1527
    curport = 0;			/* rem port *can* be zero here... */
1528
    if (argv[optind]) {			/* any rem-port-arg? */
1529
      curport = getportpoop (argv[optind], 0);
1530
      if (curport == 0)			/* if given, demand correctness */
1531
	bail ("invalid port %s", argv[optind]);
1532
    } /* if port-arg */
1533
    netfd = dolisten (themaddr, curport, ouraddr, o_lport);
1534
/* dolisten does its own connect reporting, so we don't holler anything here */
1535
    if (netfd > 0) {
1536
#ifdef GAPING_SECURITY_HOLE
1537
      if (pr00gie)			/* -e given? */
1538
	doexec (netfd);
1539
#endif /* GAPING_SECURITY_HOLE */
1540
      x = readwrite (netfd);		/* it even works with UDP! */
1541
      if (o_verbose > 1)		/* normally we don't care */
1542
	holler (wrote_txt, wrote_net, wrote_out);
1543
      exit (x);				/* "pack out yer trash" */
1544
    } else /* if no netfd */
1545
      bail ("no connection");
1546
  } /* o_listen */
1547
1548
/* fall thru to outbound connects.  Now we're more picky about args... */
1549
  if (! themaddr)
1550
    bail ("no destination");
1551
  if (argv[optind] == NULL)
1552
    bail ("no port[s] to connect to");
1553
  if (argv[optind + 1])		/* look ahead: any more port args given? */
1554
    Single = 0;				/* multi-mode, case A */
1555
  ourport = o_lport;			/* which can be 0 */
1556
1557
/* everything from here down is treated as as ports and/or ranges thereof, so
1558
   it's all enclosed in this big ol' argv-parsin' loop.  Any randomization is
1559
   done within each given *range*, but in separate chunks per each succeeding
1560
   argument, so we can control the pattern somewhat. */
1561
  while (argv[optind]) {
1562
    hiport = loport = 0;
1563
    cp = strchr (argv[optind], '-');	/* nn-mm range? */
1564
    if (cp) {
1565
      *cp = '\0';
1566
      cp++;
1567
      hiport = getportpoop (cp, 0);
1568
      if (hiport == 0)
1569
	bail ("invalid port %s", cp);
1570
    } /* if found a dash */
1571
    loport = getportpoop (argv[optind], 0);
1572
    if (loport == 0)
1573
      bail ("invalid port %s", argv[optind]);
1574
    if (hiport > loport) {		/* was it genuinely a range? */
1575
      Single = 0;			/* multi-mode, case B */
1576
      curport = hiport;			/* start high by default */
1577
      if (o_random) {			/* maybe populate the random array */
1578
	loadports (randports, loport, hiport);
1579
	curport = nextport (randports);
1580
      }
1581
    } else			/* not a range, including args like "25-25" */
1582
      curport = loport;
1583
Debug (("Single %d, curport %d", Single, curport))
1584
1585
/* Now start connecting to these things.  curport is already preloaded. */
1586
    while (loport <= curport) {
1587
      if ((! o_lport) && (o_random)) {	/* -p overrides random local-port */
1588
	ourport = (RAND() & 0xffff);	/* random local-bind -- well above */
1589
	if (ourport < 8192)		/* resv and any likely listeners??? */
1590
	  ourport += 8192;		/* if it *still* conflicts, use -s. */
1591
      }
1592
      curport = getportpoop (NULL, curport);
1593
      netfd = doconnect (themaddr, curport, ouraddr, ourport);
1594
Debug (("netfd %d from port %d to port %d", netfd, ourport, curport))
1595
      if (netfd > 0)
1596
	if (o_zero && o_udpmode)	/* if UDP scanning... */
1597
	  netfd = udptest (netfd, themaddr);
1598
      if (netfd > 0) {			/* Yow, are we OPEN YET?! */
1599
	x = 0;				/* pre-exit status */
1600
	holler ("%s [%s] %d (%s) open",
1601
	  whereto->name, whereto->addrs[0], curport, portpoop->name);
1602
#ifdef GAPING_SECURITY_HOLE
1603
	if (pr00gie)			/* exec is valid for outbound, too */
1604
	  doexec (netfd);
1605
#endif /* GAPING_SECURITY_HOLE */
1606
	if (! o_zero)
1607
	  x = readwrite (netfd);	/* go shovel shit */
1608
      } else { /* no netfd... */
1609
	x = 1;				/* preload exit status for later */
1610
/* if we're scanning at a "one -v" verbosity level, don't print refusals.
1611
   Give it another -v if you want to see everything. */
1612
	if ((Single || (o_verbose > 1)) || (errno != ECONNREFUSED))
1613
	  holler ("%s [%s] %d (%s)",
1614
	    whereto->name, whereto->addrs[0], curport, portpoop->name);
1615
      } /* if netfd */
1616
      close (netfd);			/* just in case we didn't already */
1617
      if (o_interval)
1618
	sleep (o_interval);		/* if -i, delay between ports too */
1619
      if (o_random)
1620
	curport = nextport (randports);
1621
      else
1622
	curport--;			/* just decrement... */
1623
    } /* while curport within current range */
1624
    optind++;
1625
  } /* while remaining port-args -- end of big argv-ports loop*/
1626
1627
  errno = 0;
1628
  if (o_verbose > 1)		/* normally we don't care */
1629
    holler (wrote_txt, wrote_net, wrote_out);
1630
  if (Single)
1631
    exit (x);			/* give us status on one connection */
1632
  exit (0);			/* otherwise, we're just done */
1633
} /* main */
1634
1635
#ifdef HAVE_HELP		/* unless we wanna be *really* cryptic */
1636
/* helpme :
1637
   the obvious */
1638
void
1639
helpme()
1640
{
1641
  o_verbose = 1;
1642
  holler ("[v1.10]\n\
1643
connect to somewhere:	nc [-options] hostname port[s] [ports] ... \n\
1644
listen for inbound:	nc -l -p port [-options] [hostname] [port]\n\
1645
options:");
1646
/* sigh, this necessarily gets messy.  And the trailing \ characters may be
1647
   interpreted oddly by some compilers, generating or not generating extra
1648
   newlines as they bloody please.  u-fix... */
1649
#ifdef GAPING_SECURITY_HOLE	/* needs to be separate holler() */
1650
  holler ("\
1651
	-e prog			program to exec after connect [dangerous!!]");
1652
#endif
1653
  holler ("\
1654
	-g gateway		source-routing hop point[s], up to 8\n\
1655
	-G num			source-routing pointer: 4, 8, 12, ...\n\
1656
	-h			this cruft\n\
1657
	-i secs			delay interval for lines sent, ports scanned\n\
1658
	-l			listen mode, for inbound connects\n\
1659
	-n			numeric-only IP addresses, no DNS\n\
1660
	-o file			hex dump of traffic\n\
1661
	-p port			local port number\n\
1662
	-r			randomize local and remote ports\n\
1663
	-s addr			local source address");
1664
#ifdef TELNET
1665
  holler ("\
1666
	-t			answer TELNET negotiation");
1667
#endif
1668
  holler ("\
1669
	-u			UDP mode\n\
1670
	-v			verbose [use twice to be more verbose]\n\
1671
	-w secs			timeout for connects and final net reads\n\
1672
	-z			zero-I/O mode [used for scanning]");
1673
  bail ("port numbers can be individual or ranges: lo-hi [inclusive]");
1674
} /* helpme */
1675
#endif /* HAVE_HELP */
1676
1677
/* None genuine without this seal!  _H*/