netcat.c revision 214047
1214047Sdelphij/* $OpenBSD: netcat.c,v 1.98 2010/07/03 04:44:51 guenther Exp $ */
2141261Sdelphij/*
3141261Sdelphij * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4141261Sdelphij *
5141261Sdelphij * Redistribution and use in source and binary forms, with or without
6141261Sdelphij * modification, are permitted provided that the following conditions
7141261Sdelphij * are met:
8141261Sdelphij *
9141261Sdelphij * 1. Redistributions of source code must retain the above copyright
10141261Sdelphij *   notice, this list of conditions and the following disclaimer.
11141261Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
12141261Sdelphij *   notice, this list of conditions and the following disclaimer in the
13141261Sdelphij *   documentation and/or other materials provided with the distribution.
14141261Sdelphij * 3. The name of the author may not be used to endorse or promote products
15141261Sdelphij *   derived from this software without specific prior written permission.
16141261Sdelphij *
17141261Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18141261Sdelphij * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19141261Sdelphij * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20141261Sdelphij * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21141261Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22141261Sdelphij * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23141261Sdelphij * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24141261Sdelphij * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25141261Sdelphij * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26141261Sdelphij * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27141394Sdelphij *
28141394Sdelphij * $FreeBSD: head/contrib/netcat/netcat.c 214047 2010-10-19 00:01:53Z delphij $
29141261Sdelphij */
30141261Sdelphij
31141261Sdelphij/*
32141261Sdelphij * Re-written nc(1) for OpenBSD. Original implementation by
33141261Sdelphij * *Hobbit* <hobbit@avian.org>.
34141261Sdelphij */
35141261Sdelphij
36141394Sdelphij#include <sys/limits.h>
37141261Sdelphij#include <sys/types.h>
38141261Sdelphij#include <sys/socket.h>
39202640Sdelphij#include <sys/sysctl.h>
40141261Sdelphij#include <sys/time.h>
41141261Sdelphij#include <sys/un.h>
42141261Sdelphij
43141261Sdelphij#include <netinet/in.h>
44158798Sdelphij#include <netinet/in_systm.h>
45141394Sdelphij#ifdef IPSEC
46171135Sgnn#include <netipsec/ipsec.h>
47141394Sdelphij#endif
48141261Sdelphij#include <netinet/tcp.h>
49158798Sdelphij#include <netinet/ip.h>
50141261Sdelphij#include <arpa/telnet.h>
51141261Sdelphij
52141261Sdelphij#include <err.h>
53141261Sdelphij#include <errno.h>
54186343Sdelphij#include <getopt.h>
55141261Sdelphij#include <netdb.h>
56141261Sdelphij#include <poll.h>
57141261Sdelphij#include <stdarg.h>
58141261Sdelphij#include <stdio.h>
59141261Sdelphij#include <stdlib.h>
60141261Sdelphij#include <string.h>
61141261Sdelphij#include <unistd.h>
62141261Sdelphij#include <fcntl.h>
63158798Sdelphij#include <limits.h>
64158798Sdelphij#include "atomicio.h"
65141261Sdelphij
66141261Sdelphij#ifndef SUN_LEN
67141261Sdelphij#define SUN_LEN(su) \
68141261Sdelphij	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
69141261Sdelphij#endif
70141261Sdelphij
71141261Sdelphij#define PORT_MAX	65535
72141261Sdelphij#define PORT_MAX_LEN	6
73141261Sdelphij
74141261Sdelphij/* Command Line Options */
75141261Sdelphijint	dflag;					/* detached, no stdin */
76167964Sdelphijunsigned int iflag;				/* Interval Flag */
77158798Sdelphijint	jflag;					/* use jumbo frames if we can */
78141261Sdelphijint	kflag;					/* More than one connect */
79141261Sdelphijint	lflag;					/* Bind to local port */
80141261Sdelphijint	nflag;					/* Don't do name look up */
81186343Sdelphijint	FreeBSD_Oflag;				/* Do not use TCP options */
82158798Sdelphijchar   *Pflag;					/* Proxy username */
83141261Sdelphijchar   *pflag;					/* Localport flag */
84141261Sdelphijint	rflag;					/* Random ports flag */
85141261Sdelphijchar   *sflag;					/* Source Address */
86141261Sdelphijint	tflag;					/* Telnet Emulation */
87141261Sdelphijint	uflag;					/* UDP - Default to TCP */
88141261Sdelphijint	vflag;					/* Verbosity */
89141261Sdelphijint	xflag;					/* Socks proxy */
90141261Sdelphijint	zflag;					/* Port Scan Flag */
91141261Sdelphijint	Dflag;					/* sodebug */
92186343Sdelphijint	Iflag;					/* TCP receive buffer size */
93186343Sdelphijint	Oflag;					/* TCP send buffer size */
94141261Sdelphijint	Sflag;					/* TCP MD5 signature option */
95158798Sdelphijint	Tflag = -1;				/* IP Type of Service */
96214047Sdelphiju_int	rtableid;
97141261Sdelphij
98141261Sdelphijint timeout = -1;
99141261Sdelphijint family = AF_UNSPEC;
100141261Sdelphijchar *portlist[PORT_MAX+1];
101141261Sdelphij
102141261Sdelphijvoid	atelnet(int, unsigned char *, unsigned int);
103141261Sdelphijvoid	build_ports(char *);
104141261Sdelphijvoid	help(void);
105141261Sdelphijint	local_listen(char *, char *, struct addrinfo);
106141261Sdelphijvoid	readwrite(int);
107158798Sdelphijint	remote_connect(const char *, const char *, struct addrinfo);
108158798Sdelphijint	socks_connect(const char *, const char *, struct addrinfo,
109158798Sdelphij	    const char *, const char *, struct addrinfo, int, const char *);
110141261Sdelphijint	udptest(int);
111141261Sdelphijint	unix_connect(char *);
112141261Sdelphijint	unix_listen(char *);
113158798Sdelphijvoid	set_common_sockopts(int);
114158798Sdelphijint	parse_iptos(char *);
115141261Sdelphijvoid	usage(int);
116141261Sdelphij
117141394Sdelphij#ifdef IPSEC
118141394Sdelphijvoid	add_ipsec_policy(int, char *);
119141394Sdelphij
120141394Sdelphijchar	*ipsec_policy[2];
121141394Sdelphij#endif
122141394Sdelphij
123141261Sdelphijint
124141261Sdelphijmain(int argc, char *argv[])
125141261Sdelphij{
126141394Sdelphij	int ch, s, ret, socksv, ipsec_count;
127202640Sdelphij	int numfibs;
128202640Sdelphij	size_t intsize = sizeof(int);
129167964Sdelphij	char *host, *uport;
130141261Sdelphij	struct addrinfo hints;
131141261Sdelphij	struct servent *sv;
132141261Sdelphij	socklen_t len;
133141261Sdelphij	struct sockaddr_storage cliaddr;
134141261Sdelphij	char *proxy;
135167964Sdelphij	const char *errstr, *proxyhost = "", *proxyport = NULL;
136141261Sdelphij	struct addrinfo proxyhints;
137186343Sdelphij	struct option longopts[] = {
138186343Sdelphij		{ "no-tcpopt",	no_argument,	&FreeBSD_Oflag,	1 },
139186343Sdelphij		{ NULL,		0,		NULL,		0 }
140186343Sdelphij	};
141141261Sdelphij
142141261Sdelphij	ret = 1;
143141394Sdelphij	ipsec_count = 0;
144141261Sdelphij	s = 0;
145141261Sdelphij	socksv = 5;
146141261Sdelphij	host = NULL;
147141261Sdelphij	uport = NULL;
148141261Sdelphij	sv = NULL;
149141261Sdelphij
150186343Sdelphij	while ((ch = getopt_long(argc, argv,
151206675Sdelphij	    "46DdEe:hI:i:jklnoO:P:p:rSs:tT:UuV:vw:X:x:z",
152186343Sdelphij	    longopts, NULL)) != -1) {
153141261Sdelphij		switch (ch) {
154141261Sdelphij		case '4':
155141261Sdelphij			family = AF_INET;
156141261Sdelphij			break;
157141261Sdelphij		case '6':
158141261Sdelphij			family = AF_INET6;
159141261Sdelphij			break;
160141261Sdelphij		case 'U':
161141261Sdelphij			family = AF_UNIX;
162141261Sdelphij			break;
163141261Sdelphij		case 'X':
164141261Sdelphij			if (strcasecmp(optarg, "connect") == 0)
165141261Sdelphij				socksv = -1; /* HTTP proxy CONNECT */
166141261Sdelphij			else if (strcmp(optarg, "4") == 0)
167141261Sdelphij				socksv = 4; /* SOCKS v.4 */
168141261Sdelphij			else if (strcmp(optarg, "5") == 0)
169141261Sdelphij				socksv = 5; /* SOCKS v.5 */
170141261Sdelphij			else
171141261Sdelphij				errx(1, "unsupported proxy protocol");
172141261Sdelphij			break;
173141261Sdelphij		case 'd':
174141261Sdelphij			dflag = 1;
175141261Sdelphij			break;
176141394Sdelphij		case 'e':
177141394Sdelphij#ifdef IPSEC
178141394Sdelphij			ipsec_policy[ipsec_count++ % 2] = optarg;
179141394Sdelphij#else
180141394Sdelphij			errx(1, "IPsec support unavailable.");
181141394Sdelphij#endif
182141394Sdelphij			break;
183141394Sdelphij		case 'E':
184141394Sdelphij#ifdef IPSEC
185141394Sdelphij			ipsec_policy[0] = "in  ipsec esp/transport//require";
186141394Sdelphij			ipsec_policy[1] = "out ipsec esp/transport//require";
187141394Sdelphij#else
188141394Sdelphij			errx(1, "IPsec support unavailable.");
189141394Sdelphij#endif
190141394Sdelphij			break;
191141261Sdelphij		case 'h':
192141261Sdelphij			help();
193141261Sdelphij			break;
194141261Sdelphij		case 'i':
195167964Sdelphij			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
196167964Sdelphij			if (errstr)
197167964Sdelphij				errx(1, "interval %s: %s", errstr, optarg);
198141261Sdelphij			break;
199158798Sdelphij#ifdef SO_JUMBO
200158798Sdelphij		case 'j':
201158798Sdelphij			jflag = 1;
202158798Sdelphij			break;
203158798Sdelphij#endif
204141261Sdelphij		case 'k':
205141261Sdelphij			kflag = 1;
206141261Sdelphij			break;
207141261Sdelphij		case 'l':
208141261Sdelphij			lflag = 1;
209141261Sdelphij			break;
210141261Sdelphij		case 'n':
211141261Sdelphij			nflag = 1;
212141261Sdelphij			break;
213141394Sdelphij		case 'o':
214206675Sdelphij			fprintf(stderr, "option -o is deprecated.\n");
215141394Sdelphij			break;
216158798Sdelphij		case 'P':
217158798Sdelphij			Pflag = optarg;
218158798Sdelphij			break;
219141261Sdelphij		case 'p':
220141261Sdelphij			pflag = optarg;
221141261Sdelphij			break;
222141261Sdelphij		case 'r':
223141261Sdelphij			rflag = 1;
224141261Sdelphij			break;
225141261Sdelphij		case 's':
226141261Sdelphij			sflag = optarg;
227141261Sdelphij			break;
228141261Sdelphij		case 't':
229141261Sdelphij			tflag = 1;
230141261Sdelphij			break;
231141261Sdelphij		case 'u':
232141261Sdelphij			uflag = 1;
233141261Sdelphij			break;
234202640Sdelphij		case 'V':
235202640Sdelphij			if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
236202640Sdelphij				errx(1, "Multiple FIBS not supported");
237214047Sdelphij			rtableid = (unsigned int)strtonum(optarg, 0,
238202640Sdelphij			    numfibs - 1, &errstr);
239202640Sdelphij			if (errstr)
240214047Sdelphij				errx(1, "rtable %s: %s", errstr, optarg);
241202640Sdelphij			break;
242141261Sdelphij		case 'v':
243141261Sdelphij			vflag = 1;
244141261Sdelphij			break;
245141261Sdelphij		case 'w':
246167964Sdelphij			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
247167964Sdelphij			if (errstr)
248167964Sdelphij				errx(1, "timeout %s: %s", errstr, optarg);
249141261Sdelphij			timeout *= 1000;
250141261Sdelphij			break;
251141261Sdelphij		case 'x':
252141261Sdelphij			xflag = 1;
253141261Sdelphij			if ((proxy = strdup(optarg)) == NULL)
254141261Sdelphij				err(1, NULL);
255141261Sdelphij			break;
256141261Sdelphij		case 'z':
257141261Sdelphij			zflag = 1;
258141261Sdelphij			break;
259141261Sdelphij		case 'D':
260141261Sdelphij			Dflag = 1;
261141261Sdelphij			break;
262186343Sdelphij		case 'I':
263186343Sdelphij			Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
264186343Sdelphij			if (errstr != NULL)
265186343Sdelphij				errx(1, "TCP receive window %s: %s",
266186343Sdelphij				    errstr, optarg);
267186343Sdelphij			break;
268186343Sdelphij		case 'O':
269186343Sdelphij			Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
270186343Sdelphij			if (errstr != NULL) {
271186343Sdelphij			    if (strcmp(errstr, "invalid") != 0)
272186343Sdelphij				errx(1, "TCP send window %s: %s",
273186343Sdelphij				    errstr, optarg);
274186343Sdelphij			}
275186343Sdelphij			break;
276141261Sdelphij		case 'S':
277141261Sdelphij			Sflag = 1;
278141261Sdelphij			break;
279158798Sdelphij		case 'T':
280158798Sdelphij			Tflag = parse_iptos(optarg);
281158798Sdelphij			break;
282141261Sdelphij		default:
283141261Sdelphij			usage(1);
284141261Sdelphij		}
285141261Sdelphij	}
286141261Sdelphij	argc -= optind;
287141261Sdelphij	argv += optind;
288141261Sdelphij
289141261Sdelphij	/* Cruft to make sure options are clean, and used properly. */
290141261Sdelphij	if (argv[0] && !argv[1] && family == AF_UNIX) {
291141261Sdelphij		if (uflag)
292141261Sdelphij			errx(1, "cannot use -u and -U");
293141261Sdelphij		host = argv[0];
294141261Sdelphij		uport = NULL;
295141261Sdelphij	} else if (argv[0] && !argv[1]) {
296141261Sdelphij		if  (!lflag)
297141261Sdelphij			usage(1);
298141261Sdelphij		uport = argv[0];
299141261Sdelphij		host = NULL;
300141261Sdelphij	} else if (argv[0] && argv[1]) {
301141261Sdelphij		host = argv[0];
302141261Sdelphij		uport = argv[1];
303141261Sdelphij	} else
304141261Sdelphij		usage(1);
305141261Sdelphij
306141261Sdelphij	if (lflag && sflag)
307141261Sdelphij		errx(1, "cannot use -s and -l");
308141261Sdelphij	if (lflag && pflag)
309141261Sdelphij		errx(1, "cannot use -p and -l");
310141261Sdelphij	if (lflag && zflag)
311141261Sdelphij		errx(1, "cannot use -z and -l");
312141261Sdelphij	if (!lflag && kflag)
313141261Sdelphij		errx(1, "must use -l with -k");
314141261Sdelphij
315141261Sdelphij	/* Initialize addrinfo structure. */
316141261Sdelphij	if (family != AF_UNIX) {
317141261Sdelphij		memset(&hints, 0, sizeof(struct addrinfo));
318141261Sdelphij		hints.ai_family = family;
319141261Sdelphij		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
320141261Sdelphij		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
321141261Sdelphij		if (nflag)
322141261Sdelphij			hints.ai_flags |= AI_NUMERICHOST;
323141261Sdelphij	}
324141261Sdelphij
325141261Sdelphij	if (xflag) {
326141261Sdelphij		if (uflag)
327141261Sdelphij			errx(1, "no proxy support for UDP mode");
328141261Sdelphij
329141261Sdelphij		if (lflag)
330141261Sdelphij			errx(1, "no proxy support for listen");
331141261Sdelphij
332141261Sdelphij		if (family == AF_UNIX)
333141261Sdelphij			errx(1, "no proxy support for unix sockets");
334141261Sdelphij
335141261Sdelphij		/* XXX IPv6 transport to proxy would probably work */
336141261Sdelphij		if (family == AF_INET6)
337141261Sdelphij			errx(1, "no proxy support for IPv6");
338141261Sdelphij
339141261Sdelphij		if (sflag)
340141261Sdelphij			errx(1, "no proxy support for local source address");
341141261Sdelphij
342141261Sdelphij		proxyhost = strsep(&proxy, ":");
343141261Sdelphij		proxyport = proxy;
344141261Sdelphij
345141261Sdelphij		memset(&proxyhints, 0, sizeof(struct addrinfo));
346141261Sdelphij		proxyhints.ai_family = family;
347141261Sdelphij		proxyhints.ai_socktype = SOCK_STREAM;
348141261Sdelphij		proxyhints.ai_protocol = IPPROTO_TCP;
349141261Sdelphij		if (nflag)
350141261Sdelphij			proxyhints.ai_flags |= AI_NUMERICHOST;
351141261Sdelphij	}
352141261Sdelphij
353141261Sdelphij	if (lflag) {
354141261Sdelphij		int connfd;
355141261Sdelphij		ret = 0;
356141261Sdelphij
357141261Sdelphij		if (family == AF_UNIX)
358141261Sdelphij			s = unix_listen(host);
359141261Sdelphij
360141261Sdelphij		/* Allow only one connection at a time, but stay alive. */
361141261Sdelphij		for (;;) {
362141261Sdelphij			if (family != AF_UNIX)
363141261Sdelphij				s = local_listen(host, uport, hints);
364141261Sdelphij			if (s < 0)
365141261Sdelphij				err(1, NULL);
366141261Sdelphij			/*
367141261Sdelphij			 * For UDP, we will use recvfrom() initially
368141261Sdelphij			 * to wait for a caller, then use the regular
369141261Sdelphij			 * functions to talk to the caller.
370141261Sdelphij			 */
371141261Sdelphij			if (uflag) {
372158798Sdelphij				int rv, plen;
373214047Sdelphij				char buf[16384];
374141261Sdelphij				struct sockaddr_storage z;
375141261Sdelphij
376141261Sdelphij				len = sizeof(z);
377214047Sdelphij				plen = jflag ? 16384 : 2048;
378158798Sdelphij				rv = recvfrom(s, buf, plen, MSG_PEEK,
379141261Sdelphij				    (struct sockaddr *)&z, &len);
380141261Sdelphij				if (rv < 0)
381141261Sdelphij					err(1, "recvfrom");
382141261Sdelphij
383141261Sdelphij				rv = connect(s, (struct sockaddr *)&z, len);
384141261Sdelphij				if (rv < 0)
385141261Sdelphij					err(1, "connect");
386141261Sdelphij
387141261Sdelphij				connfd = s;
388141261Sdelphij			} else {
389158798Sdelphij				len = sizeof(cliaddr);
390141261Sdelphij				connfd = accept(s, (struct sockaddr *)&cliaddr,
391141261Sdelphij				    &len);
392141261Sdelphij			}
393141261Sdelphij
394141261Sdelphij			readwrite(connfd);
395141261Sdelphij			close(connfd);
396141261Sdelphij			if (family != AF_UNIX)
397141261Sdelphij				close(s);
398141261Sdelphij
399141261Sdelphij			if (!kflag)
400141261Sdelphij				break;
401141261Sdelphij		}
402141261Sdelphij	} else if (family == AF_UNIX) {
403141261Sdelphij		ret = 0;
404141261Sdelphij
405141261Sdelphij		if ((s = unix_connect(host)) > 0 && !zflag) {
406141261Sdelphij			readwrite(s);
407141261Sdelphij			close(s);
408141261Sdelphij		} else
409141261Sdelphij			ret = 1;
410141261Sdelphij
411141261Sdelphij		exit(ret);
412141261Sdelphij
413141261Sdelphij	} else {
414141261Sdelphij		int i = 0;
415141261Sdelphij
416141261Sdelphij		/* Construct the portlist[] array. */
417141261Sdelphij		build_ports(uport);
418141261Sdelphij
419141261Sdelphij		/* Cycle through portlist, connecting to each port. */
420141261Sdelphij		for (i = 0; portlist[i] != NULL; i++) {
421141261Sdelphij			if (s)
422141261Sdelphij				close(s);
423141261Sdelphij
424141261Sdelphij			if (xflag)
425141261Sdelphij				s = socks_connect(host, portlist[i], hints,
426158798Sdelphij				    proxyhost, proxyport, proxyhints, socksv,
427158798Sdelphij				    Pflag);
428141261Sdelphij			else
429141261Sdelphij				s = remote_connect(host, portlist[i], hints);
430141261Sdelphij
431141261Sdelphij			if (s < 0)
432141261Sdelphij				continue;
433141261Sdelphij
434141261Sdelphij			ret = 0;
435141261Sdelphij			if (vflag || zflag) {
436141261Sdelphij				/* For UDP, make sure we are connected. */
437141261Sdelphij				if (uflag) {
438141261Sdelphij					if (udptest(s) == -1) {
439141261Sdelphij						ret = 1;
440141261Sdelphij						continue;
441141261Sdelphij					}
442141261Sdelphij				}
443141261Sdelphij
444141261Sdelphij				/* Don't look up port if -n. */
445141261Sdelphij				if (nflag)
446141261Sdelphij					sv = NULL;
447141261Sdelphij				else {
448141261Sdelphij					sv = getservbyport(
449141261Sdelphij					    ntohs(atoi(portlist[i])),
450141261Sdelphij					    uflag ? "udp" : "tcp");
451141261Sdelphij				}
452141261Sdelphij
453205561Sdelphij				fprintf(stderr,
454205561Sdelphij				    "Connection to %s %s port [%s/%s] "
455205561Sdelphij				    "succeeded!\n", host, portlist[i],
456205561Sdelphij				    uflag ? "udp" : "tcp",
457141261Sdelphij				    sv ? sv->s_name : "*");
458141261Sdelphij			}
459141261Sdelphij			if (!zflag)
460141261Sdelphij				readwrite(s);
461141261Sdelphij		}
462141261Sdelphij	}
463141261Sdelphij
464141261Sdelphij	if (s)
465141261Sdelphij		close(s);
466141261Sdelphij
467141261Sdelphij	exit(ret);
468141261Sdelphij}
469141261Sdelphij
470141261Sdelphij/*
471141261Sdelphij * unix_connect()
472141261Sdelphij * Returns a socket connected to a local unix socket. Returns -1 on failure.
473141261Sdelphij */
474141261Sdelphijint
475141261Sdelphijunix_connect(char *path)
476141261Sdelphij{
477141261Sdelphij	struct sockaddr_un sun;
478141261Sdelphij	int s;
479141261Sdelphij
480141261Sdelphij	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
481141261Sdelphij		return (-1);
482141261Sdelphij	(void)fcntl(s, F_SETFD, 1);
483141261Sdelphij
484141261Sdelphij	memset(&sun, 0, sizeof(struct sockaddr_un));
485141261Sdelphij	sun.sun_family = AF_UNIX;
486141261Sdelphij
487141261Sdelphij	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
488141261Sdelphij	    sizeof(sun.sun_path)) {
489141261Sdelphij		close(s);
490141261Sdelphij		errno = ENAMETOOLONG;
491141261Sdelphij		return (-1);
492141261Sdelphij	}
493141261Sdelphij	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
494141261Sdelphij		close(s);
495141261Sdelphij		return (-1);
496141261Sdelphij	}
497141261Sdelphij	return (s);
498141261Sdelphij
499141261Sdelphij}
500141261Sdelphij
501141261Sdelphij/*
502141261Sdelphij * unix_listen()
503141261Sdelphij * Create a unix domain socket, and listen on it.
504141261Sdelphij */
505141261Sdelphijint
506141261Sdelphijunix_listen(char *path)
507141261Sdelphij{
508141261Sdelphij	struct sockaddr_un sun;
509141261Sdelphij	int s;
510141261Sdelphij
511141261Sdelphij	/* Create unix domain socket. */
512141261Sdelphij	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
513141261Sdelphij		return (-1);
514141261Sdelphij
515141261Sdelphij	memset(&sun, 0, sizeof(struct sockaddr_un));
516141261Sdelphij	sun.sun_family = AF_UNIX;
517141261Sdelphij
518141261Sdelphij	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
519141261Sdelphij	    sizeof(sun.sun_path)) {
520141261Sdelphij		close(s);
521141261Sdelphij		errno = ENAMETOOLONG;
522141261Sdelphij		return (-1);
523141261Sdelphij	}
524141261Sdelphij
525141261Sdelphij	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
526141261Sdelphij		close(s);
527141261Sdelphij		return (-1);
528141261Sdelphij	}
529141261Sdelphij
530141261Sdelphij	if (listen(s, 5) < 0) {
531141261Sdelphij		close(s);
532141261Sdelphij		return (-1);
533141261Sdelphij	}
534141261Sdelphij	return (s);
535141261Sdelphij}
536141261Sdelphij
537141261Sdelphij/*
538141261Sdelphij * remote_connect()
539141261Sdelphij * Returns a socket connected to a remote host. Properly binds to a local
540141261Sdelphij * port or source address if needed. Returns -1 on failure.
541141261Sdelphij */
542141261Sdelphijint
543158798Sdelphijremote_connect(const char *host, const char *port, struct addrinfo hints)
544141261Sdelphij{
545141261Sdelphij	struct addrinfo *res, *res0;
546186343Sdelphij	int s, error, on = 1;
547141261Sdelphij
548141261Sdelphij	if ((error = getaddrinfo(host, port, &hints, &res)))
549141261Sdelphij		errx(1, "getaddrinfo: %s", gai_strerror(error));
550141261Sdelphij
551141261Sdelphij	res0 = res;
552141261Sdelphij	do {
553141261Sdelphij		if ((s = socket(res0->ai_family, res0->ai_socktype,
554141261Sdelphij		    res0->ai_protocol)) < 0)
555141261Sdelphij			continue;
556141394Sdelphij#ifdef IPSEC
557141394Sdelphij		if (ipsec_policy[0] != NULL)
558141394Sdelphij			add_ipsec_policy(s, ipsec_policy[0]);
559141394Sdelphij		if (ipsec_policy[1] != NULL)
560141394Sdelphij			add_ipsec_policy(s, ipsec_policy[1]);
561141394Sdelphij#endif
562141261Sdelphij
563214047Sdelphij		if (rtableid) {
564214047Sdelphij			if (setfib(rtableid) == -1)
565202640Sdelphij				err(1, "setfib");
566202640Sdelphij		}
567202640Sdelphij
568141261Sdelphij		/* Bind to a local port or source address if specified. */
569141261Sdelphij		if (sflag || pflag) {
570141261Sdelphij			struct addrinfo ahints, *ares;
571141261Sdelphij
572206689Sdelphij			/* try IP_BINDANY, but don't insist */
573206689Sdelphij			setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on));
574141261Sdelphij			memset(&ahints, 0, sizeof(struct addrinfo));
575141261Sdelphij			ahints.ai_family = res0->ai_family;
576141261Sdelphij			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
577141261Sdelphij			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
578141261Sdelphij			ahints.ai_flags = AI_PASSIVE;
579141261Sdelphij			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
580141261Sdelphij				errx(1, "getaddrinfo: %s", gai_strerror(error));
581141261Sdelphij
582141261Sdelphij			if (bind(s, (struct sockaddr *)ares->ai_addr,
583141261Sdelphij			    ares->ai_addrlen) < 0)
584141261Sdelphij				errx(1, "bind failed: %s", strerror(errno));
585141261Sdelphij			freeaddrinfo(ares);
586141261Sdelphij		}
587141261Sdelphij
588158798Sdelphij		set_common_sockopts(s);
589158798Sdelphij
590141261Sdelphij		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
591141261Sdelphij			break;
592141261Sdelphij		else if (vflag)
593141261Sdelphij			warn("connect to %s port %s (%s) failed", host, port,
594141261Sdelphij			    uflag ? "udp" : "tcp");
595141261Sdelphij
596141261Sdelphij		close(s);
597141261Sdelphij		s = -1;
598141261Sdelphij	} while ((res0 = res0->ai_next) != NULL);
599141261Sdelphij
600141261Sdelphij	freeaddrinfo(res);
601141261Sdelphij
602141261Sdelphij	return (s);
603141261Sdelphij}
604141261Sdelphij
605141261Sdelphij/*
606141261Sdelphij * local_listen()
607141261Sdelphij * Returns a socket listening on a local port, binds to specified source
608141261Sdelphij * address. Returns -1 on failure.
609141261Sdelphij */
610141261Sdelphijint
611141261Sdelphijlocal_listen(char *host, char *port, struct addrinfo hints)
612141261Sdelphij{
613141261Sdelphij	struct addrinfo *res, *res0;
614141261Sdelphij	int s, ret, x = 1;
615141261Sdelphij	int error;
616141261Sdelphij
617141261Sdelphij	/* Allow nodename to be null. */
618141261Sdelphij	hints.ai_flags |= AI_PASSIVE;
619141261Sdelphij
620141261Sdelphij	/*
621141261Sdelphij	 * In the case of binding to a wildcard address
622141261Sdelphij	 * default to binding to an ipv4 address.
623141261Sdelphij	 */
624141261Sdelphij	if (host == NULL && hints.ai_family == AF_UNSPEC)
625141261Sdelphij		hints.ai_family = AF_INET;
626141261Sdelphij
627141261Sdelphij	if ((error = getaddrinfo(host, port, &hints, &res)))
628141261Sdelphij		errx(1, "getaddrinfo: %s", gai_strerror(error));
629141261Sdelphij
630141261Sdelphij	res0 = res;
631141261Sdelphij	do {
632141261Sdelphij		if ((s = socket(res0->ai_family, res0->ai_socktype,
633158798Sdelphij		    res0->ai_protocol)) < 0)
634141261Sdelphij			continue;
635141261Sdelphij
636214047Sdelphij		if (rtableid) {
637214047Sdelphij			if (setfib(rtableid) == -1)
638202640Sdelphij				err(1, "setfib");
639202640Sdelphij		}
640202640Sdelphij
641141261Sdelphij		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
642141261Sdelphij		if (ret == -1)
643141261Sdelphij			err(1, NULL);
644141394Sdelphij#ifdef IPSEC
645141394Sdelphij		if (ipsec_policy[0] != NULL)
646141394Sdelphij			add_ipsec_policy(s, ipsec_policy[0]);
647141394Sdelphij		if (ipsec_policy[1] != NULL)
648141394Sdelphij			add_ipsec_policy(s, ipsec_policy[1]);
649141394Sdelphij#endif
650186343Sdelphij		if (FreeBSD_Oflag) {
651177837Sbms			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
652186343Sdelphij			    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
653177837Sbms				err(1, "disable TCP options");
654177837Sbms		}
655141261Sdelphij
656141261Sdelphij		if (bind(s, (struct sockaddr *)res0->ai_addr,
657141261Sdelphij		    res0->ai_addrlen) == 0)
658141261Sdelphij			break;
659141261Sdelphij
660141261Sdelphij		close(s);
661141261Sdelphij		s = -1;
662141261Sdelphij	} while ((res0 = res0->ai_next) != NULL);
663141261Sdelphij
664141261Sdelphij	if (!uflag && s != -1) {
665141261Sdelphij		if (listen(s, 1) < 0)
666141261Sdelphij			err(1, "listen");
667141261Sdelphij	}
668141261Sdelphij
669141261Sdelphij	freeaddrinfo(res);
670141261Sdelphij
671141261Sdelphij	return (s);
672141261Sdelphij}
673141261Sdelphij
674141261Sdelphij/*
675141261Sdelphij * readwrite()
676141261Sdelphij * Loop that polls on the network file descriptor and stdin.
677141261Sdelphij */
678141261Sdelphijvoid
679141261Sdelphijreadwrite(int nfd)
680141261Sdelphij{
681141261Sdelphij	struct pollfd pfd[2];
682214047Sdelphij	unsigned char buf[16384];
683158798Sdelphij	int n, wfd = fileno(stdin);
684141261Sdelphij	int lfd = fileno(stdout);
685158798Sdelphij	int plen;
686141261Sdelphij
687214047Sdelphij	plen = jflag ? 16384 : 2048;
688158798Sdelphij
689141261Sdelphij	/* Setup Network FD */
690141261Sdelphij	pfd[0].fd = nfd;
691141261Sdelphij	pfd[0].events = POLLIN;
692141261Sdelphij
693141261Sdelphij	/* Set up STDIN FD. */
694141261Sdelphij	pfd[1].fd = wfd;
695141261Sdelphij	pfd[1].events = POLLIN;
696141261Sdelphij
697141261Sdelphij	while (pfd[0].fd != -1) {
698141261Sdelphij		if (iflag)
699141261Sdelphij			sleep(iflag);
700141261Sdelphij
701141261Sdelphij		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
702141261Sdelphij			close(nfd);
703141261Sdelphij			err(1, "Polling Error");
704141261Sdelphij		}
705141261Sdelphij
706141261Sdelphij		if (n == 0)
707141261Sdelphij			return;
708141261Sdelphij
709141261Sdelphij		if (pfd[0].revents & POLLIN) {
710158798Sdelphij			if ((n = read(nfd, buf, plen)) < 0)
711141261Sdelphij				return;
712141261Sdelphij			else if (n == 0) {
713141261Sdelphij				shutdown(nfd, SHUT_RD);
714141261Sdelphij				pfd[0].fd = -1;
715141261Sdelphij				pfd[0].events = 0;
716141261Sdelphij			} else {
717141261Sdelphij				if (tflag)
718141261Sdelphij					atelnet(nfd, buf, n);
719158798Sdelphij				if (atomicio(vwrite, lfd, buf, n) != n)
720141261Sdelphij					return;
721141261Sdelphij			}
722141261Sdelphij		}
723141261Sdelphij
724141261Sdelphij		if (!dflag && pfd[1].revents & POLLIN) {
725206675Sdelphij			if ((n = read(wfd, buf, plen)) < 0)
726141261Sdelphij				return;
727206675Sdelphij			else if (n == 0) {
728141261Sdelphij				shutdown(nfd, SHUT_WR);
729141261Sdelphij				pfd[1].fd = -1;
730141261Sdelphij				pfd[1].events = 0;
731141261Sdelphij			} else {
732158798Sdelphij				if (atomicio(vwrite, nfd, buf, n) != n)
733141261Sdelphij					return;
734141261Sdelphij			}
735141261Sdelphij		}
736141261Sdelphij	}
737141261Sdelphij}
738141261Sdelphij
739141261Sdelphij/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
740141261Sdelphijvoid
741141261Sdelphijatelnet(int nfd, unsigned char *buf, unsigned int size)
742141261Sdelphij{
743141261Sdelphij	unsigned char *p, *end;
744141261Sdelphij	unsigned char obuf[4];
745141261Sdelphij
746205561Sdelphij	if (size < 3)
747205561Sdelphij		return;
748205561Sdelphij	end = buf + size - 2;
749141261Sdelphij
750141261Sdelphij	for (p = buf; p < end; p++) {
751141261Sdelphij		if (*p != IAC)
752205561Sdelphij			continue;
753141261Sdelphij
754141261Sdelphij		obuf[0] = IAC;
755141261Sdelphij		p++;
756141261Sdelphij		if ((*p == WILL) || (*p == WONT))
757141261Sdelphij			obuf[1] = DONT;
758205561Sdelphij		else if ((*p == DO) || (*p == DONT))
759141261Sdelphij			obuf[1] = WONT;
760205561Sdelphij		else
761205561Sdelphij			continue;
762205561Sdelphij
763205561Sdelphij		p++;
764205561Sdelphij		obuf[2] = *p;
765205561Sdelphij		if (atomicio(vwrite, nfd, obuf, 3) != 3)
766205561Sdelphij			warn("Write Error!");
767141261Sdelphij	}
768141261Sdelphij}
769141261Sdelphij
770141261Sdelphij/*
771141261Sdelphij * build_ports()
772141261Sdelphij * Build an array or ports in portlist[], listing each port
773141261Sdelphij * that we should try to connect to.
774141261Sdelphij */
775141261Sdelphijvoid
776141261Sdelphijbuild_ports(char *p)
777141261Sdelphij{
778167964Sdelphij	const char *errstr;
779167964Sdelphij	char *n;
780141261Sdelphij	int hi, lo, cp;
781141261Sdelphij	int x = 0;
782141261Sdelphij
783141261Sdelphij	if ((n = strchr(p, '-')) != NULL) {
784141261Sdelphij		if (lflag)
785141261Sdelphij			errx(1, "Cannot use -l with multiple ports!");
786141261Sdelphij
787141261Sdelphij		*n = '\0';
788141261Sdelphij		n++;
789141261Sdelphij
790141261Sdelphij		/* Make sure the ports are in order: lowest->highest. */
791167964Sdelphij		hi = strtonum(n, 1, PORT_MAX, &errstr);
792167964Sdelphij		if (errstr)
793167964Sdelphij			errx(1, "port number %s: %s", errstr, n);
794167964Sdelphij		lo = strtonum(p, 1, PORT_MAX, &errstr);
795167964Sdelphij		if (errstr)
796167964Sdelphij			errx(1, "port number %s: %s", errstr, p);
797141261Sdelphij
798141261Sdelphij		if (lo > hi) {
799141261Sdelphij			cp = hi;
800141261Sdelphij			hi = lo;
801141261Sdelphij			lo = cp;
802141261Sdelphij		}
803141261Sdelphij
804141261Sdelphij		/* Load ports sequentially. */
805141261Sdelphij		for (cp = lo; cp <= hi; cp++) {
806141261Sdelphij			portlist[x] = calloc(1, PORT_MAX_LEN);
807141261Sdelphij			if (portlist[x] == NULL)
808141261Sdelphij				err(1, NULL);
809141261Sdelphij			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
810141261Sdelphij			x++;
811141261Sdelphij		}
812141261Sdelphij
813141261Sdelphij		/* Randomly swap ports. */
814141261Sdelphij		if (rflag) {
815141261Sdelphij			int y;
816141261Sdelphij			char *c;
817141261Sdelphij
818141261Sdelphij			for (x = 0; x <= (hi - lo); x++) {
819141261Sdelphij				y = (arc4random() & 0xFFFF) % (hi - lo);
820141261Sdelphij				c = portlist[x];
821141261Sdelphij				portlist[x] = portlist[y];
822141261Sdelphij				portlist[y] = c;
823141261Sdelphij			}
824141261Sdelphij		}
825141261Sdelphij	} else {
826167964Sdelphij		hi = strtonum(p, 1, PORT_MAX, &errstr);
827167964Sdelphij		if (errstr)
828167964Sdelphij			errx(1, "port number %s: %s", errstr, p);
829214047Sdelphij		portlist[0] = strdup(p);
830141261Sdelphij		if (portlist[0] == NULL)
831141261Sdelphij			err(1, NULL);
832141261Sdelphij	}
833141261Sdelphij}
834141261Sdelphij
835141261Sdelphij/*
836141261Sdelphij * udptest()
837141261Sdelphij * Do a few writes to see if the UDP port is there.
838141261Sdelphij * XXX - Better way of doing this? Doesn't work for IPv6.
839141261Sdelphij * Also fails after around 100 ports checked.
840141261Sdelphij */
841141261Sdelphijint
842141261Sdelphijudptest(int s)
843141261Sdelphij{
844141261Sdelphij	int i, ret;
845141261Sdelphij
846141261Sdelphij	for (i = 0; i <= 3; i++) {
847141261Sdelphij		if (write(s, "X", 1) == 1)
848141261Sdelphij			ret = 1;
849141261Sdelphij		else
850141261Sdelphij			ret = -1;
851141261Sdelphij	}
852141261Sdelphij	return (ret);
853141261Sdelphij}
854141261Sdelphij
855141261Sdelphijvoid
856158798Sdelphijset_common_sockopts(int s)
857158798Sdelphij{
858158798Sdelphij	int x = 1;
859158798Sdelphij
860158798Sdelphij	if (Sflag) {
861158798Sdelphij		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
862158798Sdelphij			&x, sizeof(x)) == -1)
863158798Sdelphij			err(1, NULL);
864158798Sdelphij	}
865158798Sdelphij	if (Dflag) {
866158798Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
867158798Sdelphij			&x, sizeof(x)) == -1)
868158798Sdelphij			err(1, NULL);
869158798Sdelphij	}
870158798Sdelphij#ifdef SO_JUMBO
871158798Sdelphij	if (jflag) {
872158798Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
873158798Sdelphij			&x, sizeof(x)) == -1)
874158798Sdelphij			err(1, NULL);
875158798Sdelphij	}
876158798Sdelphij#endif
877158798Sdelphij	if (Tflag != -1) {
878158798Sdelphij		if (setsockopt(s, IPPROTO_IP, IP_TOS,
879158798Sdelphij		    &Tflag, sizeof(Tflag)) == -1)
880158798Sdelphij			err(1, "set IP ToS");
881158798Sdelphij	}
882186343Sdelphij	if (Iflag) {
883186343Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
884186343Sdelphij		    &Iflag, sizeof(Iflag)) == -1)
885186343Sdelphij			err(1, "set TCP receive buffer size");
886186343Sdelphij	}
887177837Sbms	if (Oflag) {
888186343Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
889186343Sdelphij		    &Oflag, sizeof(Oflag)) == -1)
890186343Sdelphij			err(1, "set TCP send buffer size");
891186343Sdelphij	}
892186343Sdelphij	if (FreeBSD_Oflag) {
893177837Sbms		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
894186343Sdelphij		    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
895177837Sbms			err(1, "disable TCP options");
896177837Sbms	}
897158798Sdelphij}
898158798Sdelphij
899158798Sdelphijint
900158798Sdelphijparse_iptos(char *s)
901158798Sdelphij{
902158798Sdelphij	int tos = -1;
903158798Sdelphij
904158798Sdelphij	if (strcmp(s, "lowdelay") == 0)
905158798Sdelphij		return (IPTOS_LOWDELAY);
906158798Sdelphij	if (strcmp(s, "throughput") == 0)
907158798Sdelphij		return (IPTOS_THROUGHPUT);
908158798Sdelphij	if (strcmp(s, "reliability") == 0)
909158798Sdelphij		return (IPTOS_RELIABILITY);
910158798Sdelphij
911158798Sdelphij	if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
912158798Sdelphij		errx(1, "invalid IP Type of Service");
913158798Sdelphij	return (tos);
914158798Sdelphij}
915158798Sdelphij
916158798Sdelphijvoid
917141261Sdelphijhelp(void)
918141261Sdelphij{
919141261Sdelphij	usage(0);
920141261Sdelphij	fprintf(stderr, "\tCommand Summary:\n\
921141261Sdelphij	\t-4		Use IPv4\n\
922178927Santoine	\t-6		Use IPv6\n\
923178927Santoine	\t-D		Enable the debug socket option\n\
924178927Santoine	\t-d		Detach from stdin\n");
925141394Sdelphij#ifdef IPSEC
926141394Sdelphij	fprintf(stderr, "\
927178927Santoine	\t-E		Use IPsec ESP\n\
928178927Santoine	\t-e policy	Use specified IPsec policy\n");
929141394Sdelphij#endif
930141394Sdelphij	fprintf(stderr, "\
931141261Sdelphij	\t-h		This help text\n\
932186343Sdelphij	\t-I length	TCP receive buffer length\n\
933141261Sdelphij	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
934141261Sdelphij	\t-k		Keep inbound sockets open for multiple connects\n\
935141261Sdelphij	\t-l		Listen mode, for inbound connects\n\
936141261Sdelphij	\t-n		Suppress name/port resolutions\n\
937186343Sdelphij	\t--no-tcpopt	Disable TCP options\n\
938186343Sdelphij	\t-O length	TCP send buffer length\n\
939158798Sdelphij	\t-P proxyuser\tUsername for proxy authentication\n\
940141261Sdelphij	\t-p port\t	Specify local port for remote connects\n\
941141261Sdelphij	\t-r		Randomize remote ports\n\
942141261Sdelphij	\t-S		Enable the TCP MD5 signature option\n\
943141261Sdelphij	\t-s addr\t	Local source address\n\
944158798Sdelphij	\t-T ToS\t	Set IP Type of Service\n\
945141261Sdelphij	\t-t		Answer TELNET negotiation\n\
946141261Sdelphij	\t-U		Use UNIX domain socket\n\
947141261Sdelphij	\t-u		UDP mode\n\
948214047Sdelphij	\t-V rtable	Specify alternate routing table\n\
949141261Sdelphij	\t-v		Verbose\n\
950141261Sdelphij	\t-w secs\t	Timeout for connects and final net reads\n\
951141261Sdelphij	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
952141261Sdelphij	\t-x addr[:port]\tSpecify proxy address and port\n\
953141261Sdelphij	\t-z		Zero-I/O mode [used for scanning]\n\
954141261Sdelphij	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
955141394Sdelphij#ifdef IPSEC
956141394Sdelphij	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
957141394Sdelphij#endif
958141261Sdelphij	exit(1);
959141261Sdelphij}
960141261Sdelphij
961141394Sdelphij#ifdef IPSEC
962141261Sdelphijvoid
963141394Sdelphijadd_ipsec_policy(int s, char *policy)
964141394Sdelphij{
965141394Sdelphij	char *raw;
966141394Sdelphij	int e;
967141394Sdelphij
968141394Sdelphij	raw = ipsec_set_policy(policy, strlen(policy));
969141394Sdelphij	if (raw == NULL)
970141394Sdelphij		errx(1, "ipsec_set_policy `%s': %s", policy,
971141394Sdelphij		     ipsec_strerror());
972141394Sdelphij	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
973141394Sdelphij			ipsec_get_policylen(raw));
974141394Sdelphij	if (e < 0)
975141394Sdelphij		err(1, "ipsec policy cannot be configured");
976141394Sdelphij	free(raw);
977141394Sdelphij	if (vflag)
978141394Sdelphij		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
979141394Sdelphij	return;
980141394Sdelphij}
981141394Sdelphij#endif /* IPSEC */
982141394Sdelphij
983141394Sdelphijvoid
984141261Sdelphijusage(int ret)
985141261Sdelphij{
986193008Sdelphij	fprintf(stderr,
987141394Sdelphij#ifdef IPSEC
988206675Sdelphij	    "usage: nc [-46DdEhklnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
989141394Sdelphij#else
990206675Sdelphij	    "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
991141394Sdelphij#endif
992193008Sdelphij	    "\t  [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n"
993214047Sdelphij	    "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"
994202640Sdelphij	    "\t  [-x proxy_address[:port]] [hostname] [port]\n");
995141261Sdelphij	if (ret)
996141261Sdelphij		exit(1);
997141261Sdelphij}
998