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