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