netcat.c revision 141262
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