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