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