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