netcat.c revision 141261
1/* $OpenBSD: netcat.c,v 1.76 2004/12/10 16:51:31 hshoexer Exp $ */ 2/* 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* 30 * Re-written nc(1) for OpenBSD. Original implementation by 31 * *Hobbit* <hobbit@avian.org>. 32 */ 33 34#include <sys/types.h> 35#include <sys/socket.h> 36#include <sys/time.h> 37#include <sys/un.h> 38 39#include <netinet/in.h> 40#include <netinet/tcp.h> 41#include <arpa/telnet.h> 42 43#include <err.h> 44#include <errno.h> 45#include <netdb.h> 46#include <poll.h> 47#include <stdarg.h> 48#include <stdio.h> 49#include <stdlib.h> 50#include <string.h> 51#include <unistd.h> 52#include <fcntl.h> 53 54#ifndef SUN_LEN 55#define SUN_LEN(su) \ 56 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)) 57#endif 58 59#define PORT_MAX 65535 60#define PORT_MAX_LEN 6 61 62/* Command Line Options */ 63int dflag; /* detached, no stdin */ 64int iflag; /* Interval Flag */ 65int kflag; /* More than one connect */ 66int lflag; /* Bind to local port */ 67int nflag; /* Don't do name look up */ 68char *pflag; /* Localport flag */ 69int rflag; /* Random ports flag */ 70char *sflag; /* Source Address */ 71int tflag; /* Telnet Emulation */ 72int uflag; /* UDP - Default to TCP */ 73int vflag; /* Verbosity */ 74int xflag; /* Socks proxy */ 75int zflag; /* Port Scan Flag */ 76int Dflag; /* sodebug */ 77int Sflag; /* TCP MD5 signature option */ 78 79int timeout = -1; 80int family = AF_UNSPEC; 81char *portlist[PORT_MAX+1]; 82 83ssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); 84void atelnet(int, unsigned char *, unsigned int); 85void build_ports(char *); 86void help(void); 87int local_listen(char *, char *, struct addrinfo); 88void readwrite(int); 89int remote_connect(char *, char *, struct addrinfo); 90int socks_connect(char *, char *, struct addrinfo, char *, char *, 91 struct addrinfo, int); 92int udptest(int); 93int unix_connect(char *); 94int unix_listen(char *); 95void usage(int); 96 97int 98main(int argc, char *argv[]) 99{ 100 int ch, s, ret, socksv; 101 char *host, *uport, *endp; 102 struct addrinfo hints; 103 struct servent *sv; 104 socklen_t len; 105 struct sockaddr_storage cliaddr; 106 char *proxy; 107 char *proxyhost = "", *proxyport = NULL; 108 struct addrinfo proxyhints; 109 110 ret = 1; 111 s = 0; 112 socksv = 5; 113 host = NULL; 114 uport = NULL; 115 endp = NULL; 116 sv = NULL; 117 118 while ((ch = getopt(argc, argv, "46Ddhi:klnp:rSs:tUuvw:X:x:z")) != -1) { 119 switch (ch) { 120 case '4': 121 family = AF_INET; 122 break; 123 case '6': 124 family = AF_INET6; 125 break; 126 case 'U': 127 family = AF_UNIX; 128 break; 129 case 'X': 130 if (strcasecmp(optarg, "connect") == 0) 131 socksv = -1; /* HTTP proxy CONNECT */ 132 else if (strcmp(optarg, "4") == 0) 133 socksv = 4; /* SOCKS v.4 */ 134 else if (strcmp(optarg, "5") == 0) 135 socksv = 5; /* SOCKS v.5 */ 136 else 137 errx(1, "unsupported proxy protocol"); 138 break; 139 case 'd': 140 dflag = 1; 141 break; 142 case 'h': 143 help(); 144 break; 145 case 'i': 146 iflag = (int)strtoul(optarg, &endp, 10); 147 if (iflag < 0 || *endp != '\0') 148 errx(1, "interval cannot be negative"); 149 break; 150 case 'k': 151 kflag = 1; 152 break; 153 case 'l': 154 lflag = 1; 155 break; 156 case 'n': 157 nflag = 1; 158 break; 159 case 'p': 160 pflag = optarg; 161 break; 162 case 'r': 163 rflag = 1; 164 break; 165 case 's': 166 sflag = optarg; 167 break; 168 case 't': 169 tflag = 1; 170 break; 171 case 'u': 172 uflag = 1; 173 break; 174 case 'v': 175 vflag = 1; 176 break; 177 case 'w': 178 timeout = (int)strtoul(optarg, &endp, 10); 179 if (timeout < 0 || *endp != '\0') 180 errx(1, "timeout cannot be negative"); 181 if (timeout >= (INT_MAX / 1000)) 182 errx(1, "timeout too large"); 183 timeout *= 1000; 184 break; 185 case 'x': 186 xflag = 1; 187 if ((proxy = strdup(optarg)) == NULL) 188 err(1, NULL); 189 break; 190 case 'z': 191 zflag = 1; 192 break; 193 case 'D': 194 Dflag = 1; 195 break; 196 case 'S': 197 Sflag = 1; 198 break; 199 default: 200 usage(1); 201 } 202 } 203 argc -= optind; 204 argv += optind; 205 206 /* Cruft to make sure options are clean, and used properly. */ 207 if (argv[0] && !argv[1] && family == AF_UNIX) { 208 if (uflag) 209 errx(1, "cannot use -u and -U"); 210 host = argv[0]; 211 uport = NULL; 212 } else if (argv[0] && !argv[1]) { 213 if (!lflag) 214 usage(1); 215 uport = argv[0]; 216 host = NULL; 217 } else if (argv[0] && argv[1]) { 218 host = argv[0]; 219 uport = argv[1]; 220 } else 221 usage(1); 222 223 if (lflag && sflag) 224 errx(1, "cannot use -s and -l"); 225 if (lflag && pflag) 226 errx(1, "cannot use -p and -l"); 227 if (lflag && zflag) 228 errx(1, "cannot use -z and -l"); 229 if (!lflag && kflag) 230 errx(1, "must use -l with -k"); 231 232 /* Initialize addrinfo structure. */ 233 if (family != AF_UNIX) { 234 memset(&hints, 0, sizeof(struct addrinfo)); 235 hints.ai_family = family; 236 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 237 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 238 if (nflag) 239 hints.ai_flags |= AI_NUMERICHOST; 240 } 241 242 if (xflag) { 243 if (uflag) 244 errx(1, "no proxy support for UDP mode"); 245 246 if (lflag) 247 errx(1, "no proxy support for listen"); 248 249 if (family == AF_UNIX) 250 errx(1, "no proxy support for unix sockets"); 251 252 /* XXX IPv6 transport to proxy would probably work */ 253 if (family == AF_INET6) 254 errx(1, "no proxy support for IPv6"); 255 256 if (sflag) 257 errx(1, "no proxy support for local source address"); 258 259 proxyhost = strsep(&proxy, ":"); 260 proxyport = proxy; 261 262 memset(&proxyhints, 0, sizeof(struct addrinfo)); 263 proxyhints.ai_family = family; 264 proxyhints.ai_socktype = SOCK_STREAM; 265 proxyhints.ai_protocol = IPPROTO_TCP; 266 if (nflag) 267 proxyhints.ai_flags |= AI_NUMERICHOST; 268 } 269 270 if (lflag) { 271 int connfd; 272 ret = 0; 273 274 if (family == AF_UNIX) 275 s = unix_listen(host); 276 277 /* Allow only one connection at a time, but stay alive. */ 278 for (;;) { 279 if (family != AF_UNIX) 280 s = local_listen(host, uport, hints); 281 if (s < 0) 282 err(1, NULL); 283 /* 284 * For UDP, we will use recvfrom() initially 285 * to wait for a caller, then use the regular 286 * functions to talk to the caller. 287 */ 288 if (uflag) { 289 int rv; 290 char buf[1024]; 291 struct sockaddr_storage z; 292 293 len = sizeof(z); 294 rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, 295 (struct sockaddr *)&z, &len); 296 if (rv < 0) 297 err(1, "recvfrom"); 298 299 rv = connect(s, (struct sockaddr *)&z, len); 300 if (rv < 0) 301 err(1, "connect"); 302 303 connfd = s; 304 } else { 305 connfd = accept(s, (struct sockaddr *)&cliaddr, 306 &len); 307 } 308 309 readwrite(connfd); 310 close(connfd); 311 if (family != AF_UNIX) 312 close(s); 313 314 if (!kflag) 315 break; 316 } 317 } else if (family == AF_UNIX) { 318 ret = 0; 319 320 if ((s = unix_connect(host)) > 0 && !zflag) { 321 readwrite(s); 322 close(s); 323 } else 324 ret = 1; 325 326 exit(ret); 327 328 } else { 329 int i = 0; 330 331 /* Construct the portlist[] array. */ 332 build_ports(uport); 333 334 /* Cycle through portlist, connecting to each port. */ 335 for (i = 0; portlist[i] != NULL; i++) { 336 if (s) 337 close(s); 338 339 if (xflag) 340 s = socks_connect(host, portlist[i], hints, 341 proxyhost, proxyport, proxyhints, socksv); 342 else 343 s = remote_connect(host, portlist[i], hints); 344 345 if (s < 0) 346 continue; 347 348 ret = 0; 349 if (vflag || zflag) { 350 /* For UDP, make sure we are connected. */ 351 if (uflag) { 352 if (udptest(s) == -1) { 353 ret = 1; 354 continue; 355 } 356 } 357 358 /* Don't look up port if -n. */ 359 if (nflag) 360 sv = NULL; 361 else { 362 sv = getservbyport( 363 ntohs(atoi(portlist[i])), 364 uflag ? "udp" : "tcp"); 365 } 366 367 printf("Connection to %s %s port [%s/%s] succeeded!\n", 368 host, portlist[i], uflag ? "udp" : "tcp", 369 sv ? sv->s_name : "*"); 370 } 371 if (!zflag) 372 readwrite(s); 373 } 374 } 375 376 if (s) 377 close(s); 378 379 exit(ret); 380} 381 382/* 383 * unix_connect() 384 * Returns a socket connected to a local unix socket. Returns -1 on failure. 385 */ 386int 387unix_connect(char *path) 388{ 389 struct sockaddr_un sun; 390 int s; 391 392 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 393 return (-1); 394 (void)fcntl(s, F_SETFD, 1); 395 396 memset(&sun, 0, sizeof(struct sockaddr_un)); 397 sun.sun_family = AF_UNIX; 398 399 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 400 sizeof(sun.sun_path)) { 401 close(s); 402 errno = ENAMETOOLONG; 403 return (-1); 404 } 405 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 406 close(s); 407 return (-1); 408 } 409 return (s); 410 411} 412 413/* 414 * unix_listen() 415 * Create a unix domain socket, and listen on it. 416 */ 417int 418unix_listen(char *path) 419{ 420 struct sockaddr_un sun; 421 int s; 422 423 /* Create unix domain socket. */ 424 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 425 return (-1); 426 427 memset(&sun, 0, sizeof(struct sockaddr_un)); 428 sun.sun_family = AF_UNIX; 429 430 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 431 sizeof(sun.sun_path)) { 432 close(s); 433 errno = ENAMETOOLONG; 434 return (-1); 435 } 436 437 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) { 438 close(s); 439 return (-1); 440 } 441 442 if (listen(s, 5) < 0) { 443 close(s); 444 return (-1); 445 } 446 return (s); 447} 448 449/* 450 * remote_connect() 451 * Returns a socket connected to a remote host. Properly binds to a local 452 * port or source address if needed. Returns -1 on failure. 453 */ 454int 455remote_connect(char *host, char *port, struct addrinfo hints) 456{ 457 struct addrinfo *res, *res0; 458 int s, error, x = 1; 459 460 if ((error = getaddrinfo(host, port, &hints, &res))) 461 errx(1, "getaddrinfo: %s", gai_strerror(error)); 462 463 res0 = res; 464 do { 465 if ((s = socket(res0->ai_family, res0->ai_socktype, 466 res0->ai_protocol)) < 0) 467 continue; 468 469 /* Bind to a local port or source address if specified. */ 470 if (sflag || pflag) { 471 struct addrinfo ahints, *ares; 472 473 if (!(sflag && pflag)) { 474 if (!sflag) 475 sflag = NULL; 476 else 477 pflag = NULL; 478 } 479 480 memset(&ahints, 0, sizeof(struct addrinfo)); 481 ahints.ai_family = res0->ai_family; 482 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; 483 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; 484 ahints.ai_flags = AI_PASSIVE; 485 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) 486 errx(1, "getaddrinfo: %s", gai_strerror(error)); 487 488 if (bind(s, (struct sockaddr *)ares->ai_addr, 489 ares->ai_addrlen) < 0) 490 errx(1, "bind failed: %s", strerror(errno)); 491 freeaddrinfo(ares); 492 } 493 if (Sflag) { 494 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, 495 &x, sizeof(x)) == -1) 496 err(1, NULL); 497 } 498 if (Dflag) { 499 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 500 &x, sizeof(x)) == -1) 501 err(1, NULL); 502 } 503 504 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) 505 break; 506 else if (vflag) 507 warn("connect to %s port %s (%s) failed", host, port, 508 uflag ? "udp" : "tcp"); 509 510 close(s); 511 s = -1; 512 } while ((res0 = res0->ai_next) != NULL); 513 514 freeaddrinfo(res); 515 516 return (s); 517} 518 519/* 520 * local_listen() 521 * Returns a socket listening on a local port, binds to specified source 522 * address. Returns -1 on failure. 523 */ 524int 525local_listen(char *host, char *port, struct addrinfo hints) 526{ 527 struct addrinfo *res, *res0; 528 int s, ret, x = 1; 529 int error; 530 531 /* Allow nodename to be null. */ 532 hints.ai_flags |= AI_PASSIVE; 533 534 /* 535 * In the case of binding to a wildcard address 536 * default to binding to an ipv4 address. 537 */ 538 if (host == NULL && hints.ai_family == AF_UNSPEC) 539 hints.ai_family = AF_INET; 540 541 if ((error = getaddrinfo(host, port, &hints, &res))) 542 errx(1, "getaddrinfo: %s", gai_strerror(error)); 543 544 res0 = res; 545 do { 546 if ((s = socket(res0->ai_family, res0->ai_socktype, 547 res0->ai_protocol)) == 0) 548 continue; 549 550 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); 551 if (ret == -1) 552 err(1, NULL); 553 if (Sflag) { 554 ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, 555 &x, sizeof(x)); 556 if (ret == -1) 557 err(1, NULL); 558 } 559 if (Dflag) { 560 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, 561 &x, sizeof(x)) == -1) 562 err(1, NULL); 563 } 564 565 if (bind(s, (struct sockaddr *)res0->ai_addr, 566 res0->ai_addrlen) == 0) 567 break; 568 569 close(s); 570 s = -1; 571 } while ((res0 = res0->ai_next) != NULL); 572 573 if (!uflag && s != -1) { 574 if (listen(s, 1) < 0) 575 err(1, "listen"); 576 } 577 578 freeaddrinfo(res); 579 580 return (s); 581} 582 583/* 584 * readwrite() 585 * Loop that polls on the network file descriptor and stdin. 586 */ 587void 588readwrite(int nfd) 589{ 590 struct pollfd pfd[2]; 591 unsigned char buf[BUFSIZ]; 592 int wfd = fileno(stdin), n; 593 int lfd = fileno(stdout); 594 595 /* Setup Network FD */ 596 pfd[0].fd = nfd; 597 pfd[0].events = POLLIN; 598 599 /* Set up STDIN FD. */ 600 pfd[1].fd = wfd; 601 pfd[1].events = POLLIN; 602 603 while (pfd[0].fd != -1) { 604 if (iflag) 605 sleep(iflag); 606 607 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) { 608 close(nfd); 609 err(1, "Polling Error"); 610 } 611 612 if (n == 0) 613 return; 614 615 if (pfd[0].revents & POLLIN) { 616 if ((n = read(nfd, buf, sizeof(buf))) < 0) 617 return; 618 else if (n == 0) { 619 shutdown(nfd, SHUT_RD); 620 pfd[0].fd = -1; 621 pfd[0].events = 0; 622 } else { 623 if (tflag) 624 atelnet(nfd, buf, n); 625 if (atomicio((ssize_t (*)(int, void *, size_t))write, 626 lfd, buf, n) != n) 627 return; 628 } 629 } 630 631 if (!dflag && pfd[1].revents & POLLIN) { 632 if ((n = read(wfd, buf, sizeof(buf))) < 0) 633 return; 634 else if (n == 0) { 635 shutdown(nfd, SHUT_WR); 636 pfd[1].fd = -1; 637 pfd[1].events = 0; 638 } else { 639 if (atomicio((ssize_t (*)(int, void *, size_t))write, 640 nfd, buf, n) != n) 641 return; 642 } 643 } 644 } 645} 646 647/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ 648void 649atelnet(int nfd, unsigned char *buf, unsigned int size) 650{ 651 unsigned char *p, *end; 652 unsigned char obuf[4]; 653 654 end = buf + size; 655 obuf[0] = '\0'; 656 657 for (p = buf; p < end; p++) { 658 if (*p != IAC) 659 break; 660 661 obuf[0] = IAC; 662 p++; 663 if ((*p == WILL) || (*p == WONT)) 664 obuf[1] = DONT; 665 if ((*p == DO) || (*p == DONT)) 666 obuf[1] = WONT; 667 if (obuf) { 668 p++; 669 obuf[2] = *p; 670 obuf[3] = '\0'; 671 if (atomicio((ssize_t (*)(int, void *, size_t))write, 672 nfd, obuf, 3) != 3) 673 warnx("Write Error!"); 674 obuf[0] = '\0'; 675 } 676 } 677} 678 679/* 680 * build_ports() 681 * Build an array or ports in portlist[], listing each port 682 * that we should try to connect to. 683 */ 684void 685build_ports(char *p) 686{ 687 char *n, *endp; 688 int hi, lo, cp; 689 int x = 0; 690 691 if ((n = strchr(p, '-')) != NULL) { 692 if (lflag) 693 errx(1, "Cannot use -l with multiple ports!"); 694 695 *n = '\0'; 696 n++; 697 698 /* Make sure the ports are in order: lowest->highest. */ 699 hi = (int)strtoul(n, &endp, 10); 700 if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 701 errx(1, "port range not valid"); 702 lo = (int)strtoul(p, &endp, 10); 703 if (lo <= 0 || lo > PORT_MAX || *endp != '\0') 704 errx(1, "port range not valid"); 705 706 if (lo > hi) { 707 cp = hi; 708 hi = lo; 709 lo = cp; 710 } 711 712 /* Load ports sequentially. */ 713 for (cp = lo; cp <= hi; cp++) { 714 portlist[x] = calloc(1, PORT_MAX_LEN); 715 if (portlist[x] == NULL) 716 err(1, NULL); 717 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp); 718 x++; 719 } 720 721 /* Randomly swap ports. */ 722 if (rflag) { 723 int y; 724 char *c; 725 726 for (x = 0; x <= (hi - lo); x++) { 727 y = (arc4random() & 0xFFFF) % (hi - lo); 728 c = portlist[x]; 729 portlist[x] = portlist[y]; 730 portlist[y] = c; 731 } 732 } 733 } else { 734 hi = (int)strtoul(p, &endp, 10); 735 if (hi <= 0 || hi > PORT_MAX || *endp != '\0') 736 errx(1, "port range not valid"); 737 portlist[0] = calloc(1, PORT_MAX_LEN); 738 if (portlist[0] == NULL) 739 err(1, NULL); 740 portlist[0] = p; 741 } 742} 743 744/* 745 * udptest() 746 * Do a few writes to see if the UDP port is there. 747 * XXX - Better way of doing this? Doesn't work for IPv6. 748 * Also fails after around 100 ports checked. 749 */ 750int 751udptest(int s) 752{ 753 int i, ret; 754 755 for (i = 0; i <= 3; i++) { 756 if (write(s, "X", 1) == 1) 757 ret = 1; 758 else 759 ret = -1; 760 } 761 return (ret); 762} 763 764void 765help(void) 766{ 767 usage(0); 768 fprintf(stderr, "\tCommand Summary:\n\ 769 \t-4 Use IPv4\n\ 770 \t-6 Use IPv6\n\ 771 \t-D Enable the debug socket option\n\ 772 \t-d Detach from stdin\n\ 773 \t-h This help text\n\ 774 \t-i secs\t Delay interval for lines sent, ports scanned\n\ 775 \t-k Keep inbound sockets open for multiple connects\n\ 776 \t-l Listen mode, for inbound connects\n\ 777 \t-n Suppress name/port resolutions\n\ 778 \t-p port\t Specify local port for remote connects\n\ 779 \t-r Randomize remote ports\n\ 780 \t-S Enable the TCP MD5 signature option\n\ 781 \t-s addr\t Local source address\n\ 782 \t-t Answer TELNET negotiation\n\ 783 \t-U Use UNIX domain socket\n\ 784 \t-u UDP mode\n\ 785 \t-v Verbose\n\ 786 \t-w secs\t Timeout for connects and final net reads\n\ 787 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ 788 \t-x addr[:port]\tSpecify proxy address and port\n\ 789 \t-z Zero-I/O mode [used for scanning]\n\ 790 Port numbers can be individual or ranges: lo-hi [inclusive]\n"); 791 exit(1); 792} 793 794void 795usage(int ret) 796{ 797 fprintf(stderr, "usage: nc [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); 798 fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X proxy_version]\n"); 799 fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n"); 800 if (ret) 801 exit(1); 802} 803