summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r--src/usr.bin/nc/netcat.c786
1 files changed, 786 insertions, 0 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
new file mode 100644
index 0000000000..ee151972e8
--- /dev/null
+++ b/src/usr.bin/nc/netcat.c
@@ -0,0 +1,786 @@
1/* $OpenBSD: netcat.c,v 1.72 2004/03/12 10:10:00 jmc 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 Sflag; /* TCP MD5 signature option */
77
78int timeout = -1;
79int family = AF_UNSPEC;
80char *portlist[PORT_MAX+1];
81
82ssize_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
83void atelnet(int, unsigned char *, unsigned int);
84void build_ports(char *);
85void help(void);
86int local_listen(char *, char *, struct addrinfo);
87void readwrite(int);
88int remote_connect(char *, char *, struct addrinfo);
89int socks_connect(char *, char *, struct addrinfo, char *, char *,
90 struct addrinfo, int);
91int udptest(int);
92int unix_connect(char *);
93int unix_listen(char *);
94void usage(int);
95
96int
97main(int argc, char *argv[])
98{
99 int ch, s, ret, socksv;
100 char *host, *uport, *endp;
101 struct addrinfo hints;
102 struct servent *sv;
103 socklen_t len;
104 struct sockaddr *cliaddr;
105 char *proxy;
106 char *proxyhost = "", *proxyport = NULL;
107 struct addrinfo proxyhints;
108
109 ret = 1;
110 s = 0;
111 socksv = 5;
112 host = NULL;
113 uport = NULL;
114 endp = NULL;
115 sv = NULL;
116
117 while ((ch = getopt(argc, argv, "46UX:dhi:klnp:rs:tuvw:x:zS")) != -1) {
118 switch (ch) {
119 case '4':
120 family = AF_INET;
121 break;
122 case '6':
123 family = AF_INET6;
124 break;
125 case 'U':
126 family = AF_UNIX;
127 break;
128 case 'X':
129 socksv = (int)strtoul(optarg, &endp, 10);
130 if ((socksv != 4 && socksv != 5) || *endp != '\0')
131 errx(1, "only SOCKS version 4 and 5 supported");
132 break;
133 case 'd':
134 dflag = 1;
135 break;
136 case 'h':
137 help();
138 break;
139 case 'i':
140 iflag = (int)strtoul(optarg, &endp, 10);
141 if (iflag < 0 || *endp != '\0')
142 errx(1, "interval cannot be negative");
143 break;
144 case 'k':
145 kflag = 1;
146 break;
147 case 'l':
148 lflag = 1;
149 break;
150 case 'n':
151 nflag = 1;
152 break;
153 case 'p':
154 pflag = optarg;
155 break;
156 case 'r':
157 rflag = 1;
158 break;
159 case 's':
160 sflag = optarg;
161 break;
162 case 't':
163 tflag = 1;
164 break;
165 case 'u':
166 uflag = 1;
167 break;
168 case 'v':
169 vflag = 1;
170 break;
171 case 'w':
172 timeout = (int)strtoul(optarg, &endp, 10);
173 if (timeout < 0 || *endp != '\0')
174 errx(1, "timeout cannot be negative");
175 if (timeout >= (INT_MAX / 1000))
176 errx(1, "timeout too large");
177 timeout *= 1000;
178 break;
179 case 'x':
180 xflag = 1;
181 if ((proxy = strdup(optarg)) == NULL)
182 err(1, NULL);
183 break;
184 case 'z':
185 zflag = 1;
186 break;
187 case 'S':
188 Sflag = 1;
189 break;
190 default:
191 usage(1);
192 }
193 }
194 argc -= optind;
195 argv += optind;
196
197 /* Cruft to make sure options are clean, and used properly. */
198 if (argv[0] && !argv[1] && family == AF_UNIX) {
199 if (uflag)
200 errx(1, "cannot use -u and -U");
201 host = argv[0];
202 uport = NULL;
203 } else if (argv[0] && !argv[1]) {
204 if (!lflag)
205 usage(1);
206 uport = argv[0];
207 host = NULL;
208 } else if (argv[0] && argv[1]) {
209 host = argv[0];
210 uport = argv[1];
211 } else
212 usage(1);
213
214 if (lflag && sflag)
215 errx(1, "cannot use -s and -l");
216 if (lflag && pflag)
217 errx(1, "cannot use -p and -l");
218 if (lflag && zflag)
219 errx(1, "cannot use -z and -l");
220 if (!lflag && kflag)
221 errx(1, "must use -l with -k");
222
223 /* Initialize addrinfo structure. */
224 if (family != AF_UNIX) {
225 memset(&hints, 0, sizeof(struct addrinfo));
226 hints.ai_family = family;
227 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
228 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
229 if (nflag)
230 hints.ai_flags |= AI_NUMERICHOST;
231 }
232
233 if (xflag) {
234 if (uflag)
235 errx(1, "no proxy support for UDP mode");
236
237 if (lflag)
238 errx(1, "no proxy support for listen");
239
240 if (family == AF_UNIX)
241 errx(1, "no proxy support for unix sockets");
242
243 /* XXX IPv6 transport to proxy would probably work */
244 if (family == AF_INET6)
245 errx(1, "no proxy support for IPv6");
246
247 if (sflag)
248 errx(1, "no proxy support for local source address");
249
250 proxyhost = strsep(&proxy, ":");
251 proxyport = proxy;
252
253 memset(&proxyhints, 0, sizeof(struct addrinfo));
254 proxyhints.ai_family = family;
255 proxyhints.ai_socktype = SOCK_STREAM;
256 proxyhints.ai_protocol = IPPROTO_TCP;
257 if (nflag)
258 proxyhints.ai_flags |= AI_NUMERICHOST;
259 }
260
261 if (lflag) {
262 int connfd;
263 ret = 0;
264
265 if (family == AF_UNIX)
266 s = unix_listen(host);
267
268 /* Allow only one connection at a time, but stay alive. */
269 for (;;) {
270 if (family != AF_UNIX)
271 s = local_listen(host, uport, hints);
272 if (s < 0)
273 err(1, NULL);
274 /*
275 * For UDP, we will use recvfrom() initially
276 * to wait for a caller, then use the regular
277 * functions to talk to the caller.
278 */
279 if (uflag) {
280 int rv;
281 char buf[1024];
282 struct sockaddr_storage z;
283
284 len = sizeof(z);
285 rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
286 (struct sockaddr *)&z, &len);
287 if (rv < 0)
288 err(1, "recvfrom");
289
290 rv = connect(s, (struct sockaddr *)&z, len);
291 if (rv < 0)
292 err(1, "connect");
293
294 connfd = s;
295 } else {
296 connfd = accept(s, (struct sockaddr *)&cliaddr,
297 &len);
298 }
299
300 readwrite(connfd);
301 close(connfd);
302 if (family != AF_UNIX)
303 close(s);
304
305 if (!kflag)
306 break;
307 }
308 } else if (family == AF_UNIX) {
309 ret = 0;
310
311 if ((s = unix_connect(host)) > 0 && !zflag) {
312 readwrite(s);
313 close(s);
314 } else
315 ret = 1;
316
317 exit(ret);
318
319 } else {
320 int i = 0;
321
322 /* Construct the portlist[] array. */
323 build_ports(uport);
324
325 /* Cycle through portlist, connecting to each port. */
326 for (i = 0; portlist[i] != NULL; i++) {
327 if (s)
328 close(s);
329
330 if (xflag)
331 s = socks_connect(host, portlist[i], hints,
332 proxyhost, proxyport, proxyhints, socksv);
333 else
334 s = remote_connect(host, portlist[i], hints);
335
336 if (s < 0)
337 continue;
338
339 ret = 0;
340 if (vflag || zflag) {
341 /* For UDP, make sure we are connected. */
342 if (uflag) {
343 if (udptest(s) == -1) {
344 ret = 1;
345 continue;
346 }
347 }
348
349 /* Don't look up port if -n. */
350 if (nflag)
351 sv = NULL;
352 else {
353 sv = getservbyport(
354 ntohs(atoi(portlist[i])),
355 uflag ? "udp" : "tcp");
356 }
357
358 printf("Connection to %s %s port [%s/%s] succeeded!\n",
359 host, portlist[i], uflag ? "udp" : "tcp",
360 sv ? sv->s_name : "*");
361 }
362 if (!zflag)
363 readwrite(s);
364 }
365 }
366
367 if (s)
368 close(s);
369
370 exit(ret);
371}
372
373/*
374 * unix_connect()
375 * Returns a socket connected to a local unix socket. Returns -1 on failure.
376 */
377int
378unix_connect(char *path)
379{
380 struct sockaddr_un sun;
381 int s;
382
383 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
384 return (-1);
385 (void)fcntl(s, F_SETFD, 1);
386
387 memset(&sun, 0, sizeof(struct sockaddr_un));
388 sun.sun_family = AF_UNIX;
389
390 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
391 sizeof(sun.sun_path)) {
392 close(s);
393 errno = ENAMETOOLONG;
394 return (-1);
395 }
396 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
397 close(s);
398 return (-1);
399 }
400 return (s);
401
402}
403
404/*
405 * unix_listen()
406 * Create a unix domain socket, and listen on it.
407 */
408int
409unix_listen(char *path)
410{
411 struct sockaddr_un sun;
412 int s;
413
414 /* Create unix domain socket. */
415 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
416 return (-1);
417
418 memset(&sun, 0, sizeof(struct sockaddr_un));
419 sun.sun_family = AF_UNIX;
420
421 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
422 sizeof(sun.sun_path)) {
423 close(s);
424 errno = ENAMETOOLONG;
425 return (-1);
426 }
427
428 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
429 close(s);
430 return (-1);
431 }
432
433 if (listen(s, 5) < 0) {
434 close(s);
435 return (-1);
436 }
437 return (s);
438}
439
440/*
441 * remote_connect()
442 * Returns a socket connected to a remote host. Properly binds to a local
443 * port or source address if needed. Returns -1 on failure.
444 */
445int
446remote_connect(char *host, char *port, struct addrinfo hints)
447{
448 struct addrinfo *res, *res0;
449 int s, error, x = 1;
450
451 if ((error = getaddrinfo(host, port, &hints, &res)))
452 errx(1, "getaddrinfo: %s", gai_strerror(error));
453
454 res0 = res;
455 do {
456 if ((s = socket(res0->ai_family, res0->ai_socktype,
457 res0->ai_protocol)) < 0)
458 continue;
459
460 /* Bind to a local port or source address if specified. */
461 if (sflag || pflag) {
462 struct addrinfo ahints, *ares;
463
464 if (!(sflag && pflag)) {
465 if (!sflag)
466 sflag = NULL;
467 else
468 pflag = NULL;
469 }
470
471 memset(&ahints, 0, sizeof(struct addrinfo));
472 ahints.ai_family = res0->ai_family;
473 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
474 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
475 ahints.ai_flags = AI_PASSIVE;
476 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
477 errx(1, "getaddrinfo: %s", gai_strerror(error));
478
479 if (bind(s, (struct sockaddr *)ares->ai_addr,
480 ares->ai_addrlen) < 0)
481 errx(1, "bind failed: %s", strerror(errno));
482 freeaddrinfo(ares);
483 }
484 if (Sflag) {
485 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
486 &x, sizeof(x)) == -1)
487 err(1, NULL);
488 }
489
490 if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
491 break;
492 else if (vflag)
493 warn("connect to %s port %s (%s) failed", host, port,
494 uflag ? "udp" : "tcp");
495
496 close(s);
497 s = -1;
498 } while ((res0 = res0->ai_next) != NULL);
499
500 freeaddrinfo(res);
501
502 return (s);
503}
504
505/*
506 * local_listen()
507 * Returns a socket listening on a local port, binds to specified source
508 * address. Returns -1 on failure.
509 */
510int
511local_listen(char *host, char *port, struct addrinfo hints)
512{
513 struct addrinfo *res, *res0;
514 int s, ret, x = 1;
515 int error;
516
517 /* Allow nodename to be null. */
518 hints.ai_flags |= AI_PASSIVE;
519
520 /*
521 * In the case of binding to a wildcard address
522 * default to binding to an ipv4 address.
523 */
524 if (host == NULL && hints.ai_family == AF_UNSPEC)
525 hints.ai_family = AF_INET;
526
527 if ((error = getaddrinfo(host, port, &hints, &res)))
528 errx(1, "getaddrinfo: %s", gai_strerror(error));
529
530 res0 = res;
531 do {
532 if ((s = socket(res0->ai_family, res0->ai_socktype,
533 res0->ai_protocol)) == 0)
534 continue;
535
536 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
537 if (ret == -1)
538 err(1, NULL);
539 if (Sflag) {
540 ret = setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
541 &x, sizeof(x));
542 if (ret == -1)
543 err(1, NULL);
544 }
545
546 if (bind(s, (struct sockaddr *)res0->ai_addr,
547 res0->ai_addrlen) == 0)
548 break;
549
550 close(s);
551 s = -1;
552 } while ((res0 = res0->ai_next) != NULL);
553
554 if (!uflag && s != -1) {
555 if (listen(s, 1) < 0)
556 err(1, "listen");
557 }
558
559 freeaddrinfo(res);
560
561 return (s);
562}
563
564/*
565 * readwrite()
566 * Loop that polls on the network file descriptor and stdin.
567 */
568void
569readwrite(int nfd)
570{
571 struct pollfd pfd[2];
572 char buf[BUFSIZ];
573 int wfd = fileno(stdin), n, ret;
574 int lfd = fileno(stdout);
575
576 /* Setup Network FD */
577 pfd[0].fd = nfd;
578 pfd[0].events = POLLIN;
579
580 /* Set up STDIN FD. */
581 pfd[1].fd = wfd;
582 pfd[1].events = POLLIN;
583
584 while (pfd[0].fd != -1) {
585 if (iflag)
586 sleep(iflag);
587
588 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
589 close(nfd);
590 err(1, "Polling Error");
591 }
592
593 if (n == 0)
594 return;
595
596 if (pfd[0].revents & POLLIN) {
597 if ((n = read(nfd, buf, sizeof(buf))) < 0)
598 return;
599 else if (n == 0) {
600 shutdown(nfd, SHUT_RD);
601 pfd[0].fd = -1;
602 pfd[0].events = 0;
603 } else {
604 if (tflag)
605 atelnet(nfd, buf, n);
606 if ((ret = atomicio(
607 (ssize_t (*)(int, void *, size_t))write,
608 lfd, buf, n)) != n)
609 return;
610 }
611 }
612
613 if (!dflag && pfd[1].revents & POLLIN) {
614 if ((n = read(wfd, buf, sizeof(buf))) < 0)
615 return;
616 else if (n == 0) {
617 shutdown(nfd, SHUT_WR);
618 pfd[1].fd = -1;
619 pfd[1].events = 0;
620 } else {
621 if ((ret = atomicio(
622 (ssize_t (*)(int, void *, size_t))write,
623 nfd, buf, n)) != n)
624 return;
625 }
626 }
627 }
628}
629
630/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
631void
632atelnet(int nfd, unsigned char *buf, unsigned int size)
633{
634 int ret;
635 unsigned char *p, *end;
636 unsigned char obuf[4];
637
638 end = buf + size;
639 obuf[0] = '\0';
640
641 for (p = buf; p < end; p++) {
642 if (*p != IAC)
643 break;
644
645 obuf[0] = IAC;
646 p++;
647 if ((*p == WILL) || (*p == WONT))
648 obuf[1] = DONT;
649 if ((*p == DO) || (*p == DONT))
650 obuf[1] = WONT;
651 if (obuf) {
652 p++;
653 obuf[2] = *p;
654 obuf[3] = '\0';
655 if ((ret = atomicio(
656 (ssize_t (*)(int, void *, size_t))write,
657 nfd, obuf, 3)) != 3)
658 warnx("Write Error!");
659 obuf[0] = '\0';
660 }
661 }
662}
663
664/*
665 * build_ports()
666 * Build an array or ports in portlist[], listing each port
667 * that we should try to connect to.
668 */
669void
670build_ports(char *p)
671{
672 char *n, *endp;
673 int hi, lo, cp;
674 int x = 0;
675
676 if ((n = strchr(p, '-')) != NULL) {
677 if (lflag)
678 errx(1, "Cannot use -l with multiple ports!");
679
680 *n = '\0';
681 n++;
682
683 /* Make sure the ports are in order: lowest->highest. */
684 hi = (int)strtoul(n, &endp, 10);
685 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
686 errx(1, "port range not valid");
687 lo = (int)strtoul(p, &endp, 10);
688 if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
689 errx(1, "port range not valid");
690
691 if (lo > hi) {
692 cp = hi;
693 hi = lo;
694 lo = cp;
695 }
696
697 /* Load ports sequentially. */
698 for (cp = lo; cp <= hi; cp++) {
699 portlist[x] = calloc(1, PORT_MAX_LEN);
700 if (portlist[x] == NULL)
701 err(1, NULL);
702 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
703 x++;
704 }
705
706 /* Randomly swap ports. */
707 if (rflag) {
708 int y;
709 char *c;
710
711 for (x = 0; x <= (hi - lo); x++) {
712 y = (arc4random() & 0xFFFF) % (hi - lo);
713 c = portlist[x];
714 portlist[x] = portlist[y];
715 portlist[y] = c;
716 }
717 }
718 } else {
719 hi = (int)strtoul(p, &endp, 10);
720 if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
721 errx(1, "port range not valid");
722 portlist[0] = calloc(1, PORT_MAX_LEN);
723 if (portlist[0] == NULL)
724 err(1, NULL);
725 portlist[0] = p;
726 }
727}
728
729/*
730 * udptest()
731 * Do a few writes to see if the UDP port is there.
732 * XXX - Better way of doing this? Doesn't work for IPv6.
733 * Also fails after around 100 ports checked.
734 */
735int
736udptest(int s)
737{
738 int i, rv, ret;
739
740 for (i = 0; i <= 3; i++) {
741 if ((rv = write(s, "X", 1)) == 1)
742 ret = 1;
743 else
744 ret = -1;
745 }
746 return (ret);
747}
748
749void
750help(void)
751{
752 usage(0);
753 fprintf(stderr, "\tCommand Summary:\n\
754 \t-4 Use IPv4\n\
755 \t-6 Use IPv6\n\
756 \t-d Detach from stdin\n\
757 \t-h This help text\n\
758 \t-i secs\t Delay interval for lines sent, ports scanned\n\
759 \t-k Keep inbound sockets open for multiple connects\n\
760 \t-l Listen mode, for inbound connects\n\
761 \t-n Suppress name/port resolutions\n\
762 \t-p port\t Specify local port for remote connects\n\
763 \t-r Randomize remote ports\n\
764 \t-S Enable the TCP MD5 signature option\n\
765 \t-s addr\t Local source address\n\
766 \t-t Answer TELNET negotiation\n\
767 \t-U Use UNIX domain socket\n\
768 \t-u UDP mode\n\
769 \t-v Verbose\n\
770 \t-w secs\t Timeout for connects and final net reads\n\
771 \t-X vers\t SOCKS version (4 or 5)\n\
772 \t-x addr[:port]\tSpecify socks proxy address and port\n\
773 \t-z Zero-I/O mode [used for scanning]\n\
774 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
775 exit(1);
776}
777
778void
779usage(int ret)
780{
781 fprintf(stderr, "usage: nc [-46dhklnrStUuvz] [-i interval] [-p source_port]\n");
782 fprintf(stderr, "\t [-s source_ip_address] [-w timeout] [-X socks_version]\n");
783 fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
784 if (ret)
785 exit(1);
786}