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