1294288Sdelphij/* $OpenBSD: netcat.c,v 1.130 2015/07/26 19:12:28 chl 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: releng/10.3/contrib/netcat/netcat.c 294288 2016-01-18 19:42:05Z 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>
41264911Sdelphij#include <sys/uio.h>
42141261Sdelphij#include <sys/un.h>
43141261Sdelphij
44141261Sdelphij#include <netinet/in.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>
55294288Sdelphij#include <fcntl.h>
56294288Sdelphij#include <limits.h>
57141261Sdelphij#include <netdb.h>
58141261Sdelphij#include <poll.h>
59294288Sdelphij#include <signal.h>
60141261Sdelphij#include <stdarg.h>
61141261Sdelphij#include <stdio.h>
62141261Sdelphij#include <stdlib.h>
63141261Sdelphij#include <string.h>
64141261Sdelphij#include <unistd.h>
65158798Sdelphij#include "atomicio.h"
66141261Sdelphij
67141261Sdelphij#ifndef SUN_LEN
68141261Sdelphij#define SUN_LEN(su) \
69141261Sdelphij	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
70141261Sdelphij#endif
71141261Sdelphij
72141261Sdelphij#define PORT_MAX	65535
73141261Sdelphij#define PORT_MAX_LEN	6
74221793Sdelphij#define UNIX_DG_TMP_SOCKET_SIZE	19
75141261Sdelphij
76283270Sdelphij#define POLL_STDIN 0
77283270Sdelphij#define POLL_NETOUT 1
78283270Sdelphij#define POLL_NETIN 2
79283270Sdelphij#define POLL_STDOUT 3
80283270Sdelphij#define BUFSIZE 16384
81283270Sdelphij
82141261Sdelphij/* Command Line Options */
83141261Sdelphijint	dflag;					/* detached, no stdin */
84264911Sdelphijint	Fflag;					/* fdpass sock to stdout */
85167964Sdelphijunsigned int iflag;				/* Interval Flag */
86141261Sdelphijint	kflag;					/* More than one connect */
87141261Sdelphijint	lflag;					/* Bind to local port */
88249499Sdelphijint	Nflag;					/* shutdown() network socket */
89141261Sdelphijint	nflag;					/* Don't do name look up */
90186343Sdelphijint	FreeBSD_Oflag;				/* Do not use TCP options */
91158798Sdelphijchar   *Pflag;					/* Proxy username */
92141261Sdelphijchar   *pflag;					/* Localport flag */
93141261Sdelphijint	rflag;					/* Random ports flag */
94141261Sdelphijchar   *sflag;					/* Source Address */
95141261Sdelphijint	tflag;					/* Telnet Emulation */
96141261Sdelphijint	uflag;					/* UDP - Default to TCP */
97141261Sdelphijint	vflag;					/* Verbosity */
98141261Sdelphijint	xflag;					/* Socks proxy */
99141261Sdelphijint	zflag;					/* Port Scan Flag */
100141261Sdelphijint	Dflag;					/* sodebug */
101186343Sdelphijint	Iflag;					/* TCP receive buffer size */
102186343Sdelphijint	Oflag;					/* TCP send buffer size */
103141261Sdelphijint	Sflag;					/* TCP MD5 signature option */
104158798Sdelphijint	Tflag = -1;				/* IP Type of Service */
105264911Sdelphijint	rtableid = -1;
106141261Sdelphij
107141261Sdelphijint timeout = -1;
108141261Sdelphijint family = AF_UNSPEC;
109141261Sdelphijchar *portlist[PORT_MAX+1];
110221793Sdelphijchar *unix_dg_tmp_socket;
111141261Sdelphij
112141261Sdelphijvoid	atelnet(int, unsigned char *, unsigned int);
113141261Sdelphijvoid	build_ports(char *);
114141261Sdelphijvoid	help(void);
115141261Sdelphijint	local_listen(char *, char *, struct addrinfo);
116141261Sdelphijvoid	readwrite(int);
117264911Sdelphijvoid	fdpass(int nfd) __attribute__((noreturn));
118158798Sdelphijint	remote_connect(const char *, const char *, struct addrinfo);
119235037Sdelphijint	timeout_connect(int, const struct sockaddr *, socklen_t);
120158798Sdelphijint	socks_connect(const char *, const char *, struct addrinfo,
121158798Sdelphij	    const char *, const char *, struct addrinfo, int, const char *);
122141261Sdelphijint	udptest(int);
123221793Sdelphijint	unix_bind(char *);
124141261Sdelphijint	unix_connect(char *);
125141261Sdelphijint	unix_listen(char *);
126283270Sdelphijvoid	set_common_sockopts(int, int);
127235037Sdelphijint	map_tos(char *, int *);
128241906Sdelphijvoid	report_connect(const struct sockaddr *, socklen_t);
129141261Sdelphijvoid	usage(int);
130283270Sdelphijssize_t drainbuf(int, unsigned char *, size_t *);
131283270Sdelphijssize_t fillbuf(int, unsigned char *, size_t *);
132141261Sdelphij
133141394Sdelphij#ifdef IPSEC
134141394Sdelphijvoid	add_ipsec_policy(int, char *);
135141394Sdelphij
136141394Sdelphijchar	*ipsec_policy[2];
137141394Sdelphij#endif
138141394Sdelphij
139141261Sdelphijint
140141261Sdelphijmain(int argc, char *argv[])
141141261Sdelphij{
142141394Sdelphij	int ch, s, ret, socksv, ipsec_count;
143202640Sdelphij	int numfibs;
144202640Sdelphij	size_t intsize = sizeof(int);
145167964Sdelphij	char *host, *uport;
146141261Sdelphij	struct addrinfo hints;
147141261Sdelphij	struct servent *sv;
148141261Sdelphij	socklen_t len;
149141261Sdelphij	struct sockaddr_storage cliaddr;
150141261Sdelphij	char *proxy;
151167964Sdelphij	const char *errstr, *proxyhost = "", *proxyport = NULL;
152141261Sdelphij	struct addrinfo proxyhints;
153221793Sdelphij	char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
154186343Sdelphij	struct option longopts[] = {
155186343Sdelphij		{ "no-tcpopt",	no_argument,	&FreeBSD_Oflag,	1 },
156186343Sdelphij		{ NULL,		0,		NULL,		0 }
157186343Sdelphij	};
158141261Sdelphij
159141261Sdelphij	ret = 1;
160141394Sdelphij	ipsec_count = 0;
161141261Sdelphij	s = 0;
162141261Sdelphij	socksv = 5;
163141261Sdelphij	host = NULL;
164141261Sdelphij	uport = NULL;
165141261Sdelphij	sv = NULL;
166141261Sdelphij
167294288Sdelphij	signal(SIGPIPE, SIG_IGN);
168294288Sdelphij
169186343Sdelphij	while ((ch = getopt_long(argc, argv,
170264911Sdelphij	    "46DdEe:FhI:i:klNnoO:P:p:rSs:tT:UuV:vw:X:x:z",
171186343Sdelphij	    longopts, NULL)) != -1) {
172141261Sdelphij		switch (ch) {
173141261Sdelphij		case '4':
174141261Sdelphij			family = AF_INET;
175141261Sdelphij			break;
176141261Sdelphij		case '6':
177141261Sdelphij			family = AF_INET6;
178141261Sdelphij			break;
179141261Sdelphij		case 'U':
180141261Sdelphij			family = AF_UNIX;
181141261Sdelphij			break;
182141261Sdelphij		case 'X':
183141261Sdelphij			if (strcasecmp(optarg, "connect") == 0)
184141261Sdelphij				socksv = -1; /* HTTP proxy CONNECT */
185141261Sdelphij			else if (strcmp(optarg, "4") == 0)
186141261Sdelphij				socksv = 4; /* SOCKS v.4 */
187141261Sdelphij			else if (strcmp(optarg, "5") == 0)
188141261Sdelphij				socksv = 5; /* SOCKS v.5 */
189141261Sdelphij			else
190141261Sdelphij				errx(1, "unsupported proxy protocol");
191141261Sdelphij			break;
192141261Sdelphij		case 'd':
193141261Sdelphij			dflag = 1;
194141261Sdelphij			break;
195141394Sdelphij		case 'e':
196141394Sdelphij#ifdef IPSEC
197141394Sdelphij			ipsec_policy[ipsec_count++ % 2] = optarg;
198141394Sdelphij#else
199141394Sdelphij			errx(1, "IPsec support unavailable.");
200141394Sdelphij#endif
201141394Sdelphij			break;
202141394Sdelphij		case 'E':
203141394Sdelphij#ifdef IPSEC
204141394Sdelphij			ipsec_policy[0] = "in  ipsec esp/transport//require";
205141394Sdelphij			ipsec_policy[1] = "out ipsec esp/transport//require";
206141394Sdelphij#else
207141394Sdelphij			errx(1, "IPsec support unavailable.");
208141394Sdelphij#endif
209141394Sdelphij			break;
210264911Sdelphij		case 'F':
211264911Sdelphij			Fflag = 1;
212264911Sdelphij			break;
213141261Sdelphij		case 'h':
214141261Sdelphij			help();
215141261Sdelphij			break;
216141261Sdelphij		case 'i':
217167964Sdelphij			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
218167964Sdelphij			if (errstr)
219167964Sdelphij				errx(1, "interval %s: %s", errstr, optarg);
220141261Sdelphij			break;
221141261Sdelphij		case 'k':
222141261Sdelphij			kflag = 1;
223141261Sdelphij			break;
224141261Sdelphij		case 'l':
225141261Sdelphij			lflag = 1;
226141261Sdelphij			break;
227249499Sdelphij		case 'N':
228249499Sdelphij			Nflag = 1;
229249499Sdelphij			break;
230141261Sdelphij		case 'n':
231141261Sdelphij			nflag = 1;
232141261Sdelphij			break;
233141394Sdelphij		case 'o':
234206675Sdelphij			fprintf(stderr, "option -o is deprecated.\n");
235141394Sdelphij			break;
236158798Sdelphij		case 'P':
237158798Sdelphij			Pflag = optarg;
238158798Sdelphij			break;
239141261Sdelphij		case 'p':
240141261Sdelphij			pflag = optarg;
241141261Sdelphij			break;
242141261Sdelphij		case 'r':
243141261Sdelphij			rflag = 1;
244141261Sdelphij			break;
245141261Sdelphij		case 's':
246141261Sdelphij			sflag = optarg;
247141261Sdelphij			break;
248141261Sdelphij		case 't':
249141261Sdelphij			tflag = 1;
250141261Sdelphij			break;
251141261Sdelphij		case 'u':
252141261Sdelphij			uflag = 1;
253141261Sdelphij			break;
254202640Sdelphij		case 'V':
255202640Sdelphij			if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
256202640Sdelphij				errx(1, "Multiple FIBS not supported");
257264911Sdelphij			rtableid = (int)strtonum(optarg, 0,
258202640Sdelphij			    numfibs - 1, &errstr);
259202640Sdelphij			if (errstr)
260214047Sdelphij				errx(1, "rtable %s: %s", errstr, optarg);
261202640Sdelphij			break;
262141261Sdelphij		case 'v':
263141261Sdelphij			vflag = 1;
264141261Sdelphij			break;
265141261Sdelphij		case 'w':
266167964Sdelphij			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
267167964Sdelphij			if (errstr)
268167964Sdelphij				errx(1, "timeout %s: %s", errstr, optarg);
269141261Sdelphij			timeout *= 1000;
270141261Sdelphij			break;
271141261Sdelphij		case 'x':
272141261Sdelphij			xflag = 1;
273141261Sdelphij			if ((proxy = strdup(optarg)) == NULL)
274141261Sdelphij				err(1, NULL);
275141261Sdelphij			break;
276141261Sdelphij		case 'z':
277141261Sdelphij			zflag = 1;
278141261Sdelphij			break;
279141261Sdelphij		case 'D':
280141261Sdelphij			Dflag = 1;
281141261Sdelphij			break;
282186343Sdelphij		case 'I':
283186343Sdelphij			Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
284186343Sdelphij			if (errstr != NULL)
285186343Sdelphij				errx(1, "TCP receive window %s: %s",
286186343Sdelphij				    errstr, optarg);
287186343Sdelphij			break;
288186343Sdelphij		case 'O':
289186343Sdelphij			Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
290186343Sdelphij			if (errstr != NULL) {
291186343Sdelphij			    if (strcmp(errstr, "invalid") != 0)
292186343Sdelphij				errx(1, "TCP send window %s: %s",
293186343Sdelphij				    errstr, optarg);
294186343Sdelphij			}
295186343Sdelphij			break;
296141261Sdelphij		case 'S':
297141261Sdelphij			Sflag = 1;
298141261Sdelphij			break;
299158798Sdelphij		case 'T':
300235037Sdelphij			errstr = NULL;
301235037Sdelphij			errno = 0;
302235037Sdelphij			if (map_tos(optarg, &Tflag))
303235037Sdelphij				break;
304235037Sdelphij			if (strlen(optarg) > 1 && optarg[0] == '0' &&
305235037Sdelphij			    optarg[1] == 'x')
306235037Sdelphij				Tflag = (int)strtol(optarg, NULL, 16);
307235037Sdelphij			else
308235037Sdelphij				Tflag = (int)strtonum(optarg, 0, 255,
309235037Sdelphij				    &errstr);
310235037Sdelphij			if (Tflag < 0 || Tflag > 255 || errstr || errno)
311235037Sdelphij				errx(1, "illegal tos value %s", optarg);
312158798Sdelphij			break;
313141261Sdelphij		default:
314141261Sdelphij			usage(1);
315141261Sdelphij		}
316141261Sdelphij	}
317141261Sdelphij	argc -= optind;
318141261Sdelphij	argv += optind;
319141261Sdelphij
320141261Sdelphij	/* Cruft to make sure options are clean, and used properly. */
321141261Sdelphij	if (argv[0] && !argv[1] && family == AF_UNIX) {
322141261Sdelphij		host = argv[0];
323141261Sdelphij		uport = NULL;
324141261Sdelphij	} else if (argv[0] && !argv[1]) {
325141261Sdelphij		if  (!lflag)
326141261Sdelphij			usage(1);
327141261Sdelphij		uport = argv[0];
328141261Sdelphij		host = NULL;
329141261Sdelphij	} else if (argv[0] && argv[1]) {
330141261Sdelphij		host = argv[0];
331141261Sdelphij		uport = argv[1];
332141261Sdelphij	} else
333141261Sdelphij		usage(1);
334141261Sdelphij
335141261Sdelphij	if (lflag && sflag)
336141261Sdelphij		errx(1, "cannot use -s and -l");
337141261Sdelphij	if (lflag && pflag)
338141261Sdelphij		errx(1, "cannot use -p and -l");
339141261Sdelphij	if (lflag && zflag)
340141261Sdelphij		errx(1, "cannot use -z and -l");
341141261Sdelphij	if (!lflag && kflag)
342141261Sdelphij		errx(1, "must use -l with -k");
343141261Sdelphij
344221793Sdelphij	/* Get name of temporary socket for unix datagram client */
345221793Sdelphij	if ((family == AF_UNIX) && uflag && !lflag) {
346221793Sdelphij		if (sflag) {
347221793Sdelphij			unix_dg_tmp_socket = sflag;
348221793Sdelphij		} else {
349221793Sdelphij			strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
350221793Sdelphij				UNIX_DG_TMP_SOCKET_SIZE);
351221793Sdelphij			if (mktemp(unix_dg_tmp_socket_buf) == NULL)
352221793Sdelphij				err(1, "mktemp");
353221793Sdelphij			unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
354221793Sdelphij		}
355221793Sdelphij	}
356221793Sdelphij
357141261Sdelphij	/* Initialize addrinfo structure. */
358141261Sdelphij	if (family != AF_UNIX) {
359141261Sdelphij		memset(&hints, 0, sizeof(struct addrinfo));
360141261Sdelphij		hints.ai_family = family;
361141261Sdelphij		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
362141261Sdelphij		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
363141261Sdelphij		if (nflag)
364141261Sdelphij			hints.ai_flags |= AI_NUMERICHOST;
365141261Sdelphij	}
366141261Sdelphij
367141261Sdelphij	if (xflag) {
368141261Sdelphij		if (uflag)
369141261Sdelphij			errx(1, "no proxy support for UDP mode");
370141261Sdelphij
371141261Sdelphij		if (lflag)
372141261Sdelphij			errx(1, "no proxy support for listen");
373141261Sdelphij
374141261Sdelphij		if (family == AF_UNIX)
375141261Sdelphij			errx(1, "no proxy support for unix sockets");
376141261Sdelphij
377141261Sdelphij		/* XXX IPv6 transport to proxy would probably work */
378141261Sdelphij		if (family == AF_INET6)
379141261Sdelphij			errx(1, "no proxy support for IPv6");
380141261Sdelphij
381141261Sdelphij		if (sflag)
382141261Sdelphij			errx(1, "no proxy support for local source address");
383141261Sdelphij
384141261Sdelphij		proxyhost = strsep(&proxy, ":");
385141261Sdelphij		proxyport = proxy;
386141261Sdelphij
387141261Sdelphij		memset(&proxyhints, 0, sizeof(struct addrinfo));
388141261Sdelphij		proxyhints.ai_family = family;
389141261Sdelphij		proxyhints.ai_socktype = SOCK_STREAM;
390141261Sdelphij		proxyhints.ai_protocol = IPPROTO_TCP;
391141261Sdelphij		if (nflag)
392141261Sdelphij			proxyhints.ai_flags |= AI_NUMERICHOST;
393141261Sdelphij	}
394141261Sdelphij
395141261Sdelphij	if (lflag) {
396141261Sdelphij		int connfd;
397141261Sdelphij		ret = 0;
398141261Sdelphij
399221793Sdelphij		if (family == AF_UNIX) {
400221793Sdelphij			if (uflag)
401221793Sdelphij				s = unix_bind(host);
402221793Sdelphij			else
403221793Sdelphij				s = unix_listen(host);
404221793Sdelphij		}
405141261Sdelphij
406141261Sdelphij		/* Allow only one connection at a time, but stay alive. */
407141261Sdelphij		for (;;) {
408141261Sdelphij			if (family != AF_UNIX)
409141261Sdelphij				s = local_listen(host, uport, hints);
410141261Sdelphij			if (s < 0)
411141261Sdelphij				err(1, NULL);
412141261Sdelphij			/*
413241906Sdelphij			 * For UDP and -k, don't connect the socket, let it
414241906Sdelphij			 * receive datagrams from multiple socket pairs.
415141261Sdelphij			 */
416241906Sdelphij			if (uflag && kflag)
417241906Sdelphij				readwrite(s);
418241906Sdelphij			/*
419241906Sdelphij			 * For UDP and not -k, we will use recvfrom() initially
420241906Sdelphij			 * to wait for a caller, then use the regular functions
421241906Sdelphij			 * to talk to the caller.
422241906Sdelphij			 */
423241906Sdelphij			else if (uflag && !kflag) {
424158798Sdelphij				int rv, plen;
425214047Sdelphij				char buf[16384];
426141261Sdelphij				struct sockaddr_storage z;
427141261Sdelphij
428141261Sdelphij				len = sizeof(z);
429241906Sdelphij				plen = 2048;
430158798Sdelphij				rv = recvfrom(s, buf, plen, MSG_PEEK,
431141261Sdelphij				    (struct sockaddr *)&z, &len);
432141261Sdelphij				if (rv < 0)
433141261Sdelphij					err(1, "recvfrom");
434141261Sdelphij
435141261Sdelphij				rv = connect(s, (struct sockaddr *)&z, len);
436141261Sdelphij				if (rv < 0)
437141261Sdelphij					err(1, "connect");
438141261Sdelphij
439241906Sdelphij				if (vflag)
440241906Sdelphij					report_connect((struct sockaddr *)&z, len);
441241906Sdelphij
442221793Sdelphij				readwrite(s);
443141261Sdelphij			} else {
444158798Sdelphij				len = sizeof(cliaddr);
445141261Sdelphij				connfd = accept(s, (struct sockaddr *)&cliaddr,
446141261Sdelphij				    &len);
447249499Sdelphij				if (connfd == -1) {
448249499Sdelphij					/* For now, all errnos are fatal */
449283270Sdelphij					err(1, "accept");
450249499Sdelphij				}
451241906Sdelphij				if (vflag)
452241906Sdelphij					report_connect((struct sockaddr *)&cliaddr, len);
453241906Sdelphij
454221793Sdelphij				readwrite(connfd);
455221793Sdelphij				close(connfd);
456141261Sdelphij			}
457141261Sdelphij
458141261Sdelphij			if (family != AF_UNIX)
459141261Sdelphij				close(s);
460221793Sdelphij			else if (uflag) {
461221793Sdelphij				if (connect(s, NULL, 0) < 0)
462221793Sdelphij					err(1, "connect");
463221793Sdelphij			}
464141261Sdelphij
465141261Sdelphij			if (!kflag)
466141261Sdelphij				break;
467141261Sdelphij		}
468141261Sdelphij	} else if (family == AF_UNIX) {
469141261Sdelphij		ret = 0;
470141261Sdelphij
471141261Sdelphij		if ((s = unix_connect(host)) > 0 && !zflag) {
472141261Sdelphij			readwrite(s);
473141261Sdelphij			close(s);
474141261Sdelphij		} else
475141261Sdelphij			ret = 1;
476141261Sdelphij
477221793Sdelphij		if (uflag)
478221793Sdelphij			unlink(unix_dg_tmp_socket);
479141261Sdelphij		exit(ret);
480141261Sdelphij
481141261Sdelphij	} else {
482141261Sdelphij		int i = 0;
483141261Sdelphij
484141261Sdelphij		/* Construct the portlist[] array. */
485141261Sdelphij		build_ports(uport);
486141261Sdelphij
487141261Sdelphij		/* Cycle through portlist, connecting to each port. */
488141261Sdelphij		for (i = 0; portlist[i] != NULL; i++) {
489141261Sdelphij			if (s)
490141261Sdelphij				close(s);
491141261Sdelphij
492141261Sdelphij			if (xflag)
493141261Sdelphij				s = socks_connect(host, portlist[i], hints,
494158798Sdelphij				    proxyhost, proxyport, proxyhints, socksv,
495158798Sdelphij				    Pflag);
496141261Sdelphij			else
497141261Sdelphij				s = remote_connect(host, portlist[i], hints);
498141261Sdelphij
499141261Sdelphij			if (s < 0)
500141261Sdelphij				continue;
501141261Sdelphij
502141261Sdelphij			ret = 0;
503141261Sdelphij			if (vflag || zflag) {
504141261Sdelphij				/* For UDP, make sure we are connected. */
505141261Sdelphij				if (uflag) {
506141261Sdelphij					if (udptest(s) == -1) {
507141261Sdelphij						ret = 1;
508141261Sdelphij						continue;
509141261Sdelphij					}
510141261Sdelphij				}
511141261Sdelphij
512141261Sdelphij				/* Don't look up port if -n. */
513141261Sdelphij				if (nflag)
514141261Sdelphij					sv = NULL;
515141261Sdelphij				else {
516141261Sdelphij					sv = getservbyport(
517141261Sdelphij					    ntohs(atoi(portlist[i])),
518141261Sdelphij					    uflag ? "udp" : "tcp");
519141261Sdelphij				}
520141261Sdelphij
521205561Sdelphij				fprintf(stderr,
522205561Sdelphij				    "Connection to %s %s port [%s/%s] "
523205561Sdelphij				    "succeeded!\n", host, portlist[i],
524205561Sdelphij				    uflag ? "udp" : "tcp",
525141261Sdelphij				    sv ? sv->s_name : "*");
526141261Sdelphij			}
527264911Sdelphij			if (Fflag)
528264911Sdelphij				fdpass(s);
529264911Sdelphij			else if (!zflag)
530141261Sdelphij				readwrite(s);
531141261Sdelphij		}
532141261Sdelphij	}
533141261Sdelphij
534141261Sdelphij	if (s)
535141261Sdelphij		close(s);
536141261Sdelphij
537141261Sdelphij	exit(ret);
538141261Sdelphij}
539141261Sdelphij
540141261Sdelphij/*
541221793Sdelphij * unix_bind()
542221793Sdelphij * Returns a unix socket bound to the given path
543141261Sdelphij */
544141261Sdelphijint
545221793Sdelphijunix_bind(char *path)
546141261Sdelphij{
547141261Sdelphij	struct sockaddr_un sun;
548141261Sdelphij	int s;
549141261Sdelphij
550221793Sdelphij	/* Create unix domain socket. */
551221793Sdelphij	if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
552221793Sdelphij	     0)) < 0)
553141261Sdelphij		return (-1);
554141261Sdelphij
555141261Sdelphij	memset(&sun, 0, sizeof(struct sockaddr_un));
556141261Sdelphij	sun.sun_family = AF_UNIX;
557141261Sdelphij
558141261Sdelphij	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
559141261Sdelphij	    sizeof(sun.sun_path)) {
560141261Sdelphij		close(s);
561141261Sdelphij		errno = ENAMETOOLONG;
562141261Sdelphij		return (-1);
563141261Sdelphij	}
564221793Sdelphij
565221793Sdelphij	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
566141261Sdelphij		close(s);
567141261Sdelphij		return (-1);
568141261Sdelphij	}
569141261Sdelphij	return (s);
570141261Sdelphij}
571141261Sdelphij
572141261Sdelphij/*
573221793Sdelphij * unix_connect()
574221793Sdelphij * Returns a socket connected to a local unix socket. Returns -1 on failure.
575141261Sdelphij */
576141261Sdelphijint
577221793Sdelphijunix_connect(char *path)
578141261Sdelphij{
579141261Sdelphij	struct sockaddr_un sun;
580141261Sdelphij	int s;
581141261Sdelphij
582221793Sdelphij	if (uflag) {
583221793Sdelphij		if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
584221793Sdelphij			return (-1);
585221793Sdelphij	} else {
586221793Sdelphij		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
587221793Sdelphij			return (-1);
588221793Sdelphij	}
589264911Sdelphij	(void)fcntl(s, F_SETFD, FD_CLOEXEC);
590141261Sdelphij
591141261Sdelphij	memset(&sun, 0, sizeof(struct sockaddr_un));
592141261Sdelphij	sun.sun_family = AF_UNIX;
593141261Sdelphij
594141261Sdelphij	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
595141261Sdelphij	    sizeof(sun.sun_path)) {
596141261Sdelphij		close(s);
597141261Sdelphij		errno = ENAMETOOLONG;
598141261Sdelphij		return (-1);
599141261Sdelphij	}
600221793Sdelphij	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
601141261Sdelphij		close(s);
602141261Sdelphij		return (-1);
603141261Sdelphij	}
604221793Sdelphij	return (s);
605141261Sdelphij
606221793Sdelphij}
607221793Sdelphij
608221793Sdelphij/*
609221793Sdelphij * unix_listen()
610221793Sdelphij * Create a unix domain socket, and listen on it.
611221793Sdelphij */
612221793Sdelphijint
613221793Sdelphijunix_listen(char *path)
614221793Sdelphij{
615221793Sdelphij	int s;
616221793Sdelphij	if ((s = unix_bind(path)) < 0)
617221793Sdelphij		return (-1);
618221793Sdelphij
619141261Sdelphij	if (listen(s, 5) < 0) {
620141261Sdelphij		close(s);
621141261Sdelphij		return (-1);
622141261Sdelphij	}
623141261Sdelphij	return (s);
624141261Sdelphij}
625141261Sdelphij
626141261Sdelphij/*
627141261Sdelphij * remote_connect()
628141261Sdelphij * Returns a socket connected to a remote host. Properly binds to a local
629141261Sdelphij * port or source address if needed. Returns -1 on failure.
630141261Sdelphij */
631141261Sdelphijint
632158798Sdelphijremote_connect(const char *host, const char *port, struct addrinfo hints)
633141261Sdelphij{
634141261Sdelphij	struct addrinfo *res, *res0;
635186343Sdelphij	int s, error, on = 1;
636141261Sdelphij
637141261Sdelphij	if ((error = getaddrinfo(host, port, &hints, &res)))
638141261Sdelphij		errx(1, "getaddrinfo: %s", gai_strerror(error));
639141261Sdelphij
640141261Sdelphij	res0 = res;
641141261Sdelphij	do {
642141261Sdelphij		if ((s = socket(res0->ai_family, res0->ai_socktype,
643141261Sdelphij		    res0->ai_protocol)) < 0)
644141261Sdelphij			continue;
645141394Sdelphij#ifdef IPSEC
646141394Sdelphij		if (ipsec_policy[0] != NULL)
647141394Sdelphij			add_ipsec_policy(s, ipsec_policy[0]);
648141394Sdelphij		if (ipsec_policy[1] != NULL)
649141394Sdelphij			add_ipsec_policy(s, ipsec_policy[1]);
650141394Sdelphij#endif
651141261Sdelphij
652264911Sdelphij		if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_SETFIB,
653264911Sdelphij		    &rtableid, sizeof(rtableid)) == -1))
654264911Sdelphij			err(1, "setsockopt SO_SETFIB");
655202640Sdelphij
656141261Sdelphij		/* Bind to a local port or source address if specified. */
657141261Sdelphij		if (sflag || pflag) {
658141261Sdelphij			struct addrinfo ahints, *ares;
659141261Sdelphij
660206689Sdelphij			/* try IP_BINDANY, but don't insist */
661206689Sdelphij			setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on));
662141261Sdelphij			memset(&ahints, 0, sizeof(struct addrinfo));
663141261Sdelphij			ahints.ai_family = res0->ai_family;
664141261Sdelphij			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
665141261Sdelphij			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
666141261Sdelphij			ahints.ai_flags = AI_PASSIVE;
667141261Sdelphij			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
668141261Sdelphij				errx(1, "getaddrinfo: %s", gai_strerror(error));
669141261Sdelphij
670141261Sdelphij			if (bind(s, (struct sockaddr *)ares->ai_addr,
671141261Sdelphij			    ares->ai_addrlen) < 0)
672274263Sdelphij				err(1, "bind failed");
673141261Sdelphij			freeaddrinfo(ares);
674141261Sdelphij		}
675141261Sdelphij
676283270Sdelphij		set_common_sockopts(s, res0->ai_family);
677158798Sdelphij
678235037Sdelphij		if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
679141261Sdelphij			break;
680141261Sdelphij		else if (vflag)
681141261Sdelphij			warn("connect to %s port %s (%s) failed", host, port,
682141261Sdelphij			    uflag ? "udp" : "tcp");
683141261Sdelphij
684141261Sdelphij		close(s);
685141261Sdelphij		s = -1;
686141261Sdelphij	} while ((res0 = res0->ai_next) != NULL);
687141261Sdelphij
688141261Sdelphij	freeaddrinfo(res);
689141261Sdelphij
690141261Sdelphij	return (s);
691141261Sdelphij}
692141261Sdelphij
693235037Sdelphijint
694235037Sdelphijtimeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
695235037Sdelphij{
696235037Sdelphij	struct pollfd pfd;
697235037Sdelphij	socklen_t optlen;
698235037Sdelphij	int flags, optval;
699235037Sdelphij	int ret;
700235037Sdelphij
701235037Sdelphij	if (timeout != -1) {
702235037Sdelphij		flags = fcntl(s, F_GETFL, 0);
703235037Sdelphij		if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
704235037Sdelphij			err(1, "set non-blocking mode");
705235037Sdelphij	}
706235037Sdelphij
707235037Sdelphij	if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
708235037Sdelphij		pfd.fd = s;
709235037Sdelphij		pfd.events = POLLOUT;
710235037Sdelphij		if ((ret = poll(&pfd, 1, timeout)) == 1) {
711235037Sdelphij			optlen = sizeof(optval);
712235037Sdelphij			if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
713235037Sdelphij			    &optval, &optlen)) == 0) {
714235037Sdelphij				errno = optval;
715235037Sdelphij				ret = optval == 0 ? 0 : -1;
716235037Sdelphij			}
717235037Sdelphij		} else if (ret == 0) {
718235037Sdelphij			errno = ETIMEDOUT;
719235037Sdelphij			ret = -1;
720235037Sdelphij		} else
721235037Sdelphij			err(1, "poll failed");
722235037Sdelphij	}
723235037Sdelphij
724235037Sdelphij	if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
725235037Sdelphij		err(1, "restoring flags");
726235037Sdelphij
727235037Sdelphij	return (ret);
728235037Sdelphij}
729235037Sdelphij
730141261Sdelphij/*
731141261Sdelphij * local_listen()
732141261Sdelphij * Returns a socket listening on a local port, binds to specified source
733141261Sdelphij * address. Returns -1 on failure.
734141261Sdelphij */
735141261Sdelphijint
736141261Sdelphijlocal_listen(char *host, char *port, struct addrinfo hints)
737141261Sdelphij{
738141261Sdelphij	struct addrinfo *res, *res0;
739141261Sdelphij	int s, ret, x = 1;
740141261Sdelphij	int error;
741141261Sdelphij
742141261Sdelphij	/* Allow nodename to be null. */
743141261Sdelphij	hints.ai_flags |= AI_PASSIVE;
744141261Sdelphij
745141261Sdelphij	/*
746141261Sdelphij	 * In the case of binding to a wildcard address
747141261Sdelphij	 * default to binding to an ipv4 address.
748141261Sdelphij	 */
749141261Sdelphij	if (host == NULL && hints.ai_family == AF_UNSPEC)
750141261Sdelphij		hints.ai_family = AF_INET;
751141261Sdelphij
752141261Sdelphij	if ((error = getaddrinfo(host, port, &hints, &res)))
753141261Sdelphij		errx(1, "getaddrinfo: %s", gai_strerror(error));
754141261Sdelphij
755141261Sdelphij	res0 = res;
756141261Sdelphij	do {
757141261Sdelphij		if ((s = socket(res0->ai_family, res0->ai_socktype,
758158798Sdelphij		    res0->ai_protocol)) < 0)
759141261Sdelphij			continue;
760141261Sdelphij
761274263Sdelphij		if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_SETFIB,
762264911Sdelphij		    &rtableid, sizeof(rtableid)) == -1))
763264911Sdelphij			err(1, "setsockopt SO_SETFIB");
764202640Sdelphij
765141261Sdelphij		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
766141261Sdelphij		if (ret == -1)
767141261Sdelphij			err(1, NULL);
768141394Sdelphij#ifdef IPSEC
769141394Sdelphij		if (ipsec_policy[0] != NULL)
770141394Sdelphij			add_ipsec_policy(s, ipsec_policy[0]);
771141394Sdelphij		if (ipsec_policy[1] != NULL)
772141394Sdelphij			add_ipsec_policy(s, ipsec_policy[1]);
773141394Sdelphij#endif
774186343Sdelphij		if (FreeBSD_Oflag) {
775177837Sbms			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
776186343Sdelphij			    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
777177837Sbms				err(1, "disable TCP options");
778177837Sbms		}
779141261Sdelphij
780283270Sdelphij		set_common_sockopts(s, res0->ai_family);
781283270Sdelphij
782141261Sdelphij		if (bind(s, (struct sockaddr *)res0->ai_addr,
783141261Sdelphij		    res0->ai_addrlen) == 0)
784141261Sdelphij			break;
785141261Sdelphij
786141261Sdelphij		close(s);
787141261Sdelphij		s = -1;
788141261Sdelphij	} while ((res0 = res0->ai_next) != NULL);
789141261Sdelphij
790141261Sdelphij	if (!uflag && s != -1) {
791141261Sdelphij		if (listen(s, 1) < 0)
792141261Sdelphij			err(1, "listen");
793141261Sdelphij	}
794141261Sdelphij
795141261Sdelphij	freeaddrinfo(res);
796141261Sdelphij
797141261Sdelphij	return (s);
798141261Sdelphij}
799141261Sdelphij
800141261Sdelphij/*
801141261Sdelphij * readwrite()
802141261Sdelphij * Loop that polls on the network file descriptor and stdin.
803141261Sdelphij */
804141261Sdelphijvoid
805283270Sdelphijreadwrite(int net_fd)
806141261Sdelphij{
807283270Sdelphij	struct pollfd pfd[4];
808283270Sdelphij	int stdin_fd = STDIN_FILENO;
809283270Sdelphij	int stdout_fd = STDOUT_FILENO;
810283270Sdelphij	unsigned char netinbuf[BUFSIZE];
811283270Sdelphij	size_t netinbufpos = 0;
812283270Sdelphij	unsigned char stdinbuf[BUFSIZE];
813283270Sdelphij	size_t stdinbufpos = 0;
814283270Sdelphij	int n, num_fds;
815283270Sdelphij	ssize_t ret;
816141261Sdelphij
817283270Sdelphij	/* don't read from stdin if requested */
818283270Sdelphij	if (dflag)
819283270Sdelphij		stdin_fd = -1;
820158798Sdelphij
821283270Sdelphij	/* stdin */
822283270Sdelphij	pfd[POLL_STDIN].fd = stdin_fd;
823283270Sdelphij	pfd[POLL_STDIN].events = POLLIN;
824141261Sdelphij
825283270Sdelphij	/* network out */
826283270Sdelphij	pfd[POLL_NETOUT].fd = net_fd;
827283270Sdelphij	pfd[POLL_NETOUT].events = 0;
828141261Sdelphij
829283270Sdelphij	/* network in */
830283270Sdelphij	pfd[POLL_NETIN].fd = net_fd;
831283270Sdelphij	pfd[POLL_NETIN].events = POLLIN;
832283270Sdelphij
833283270Sdelphij	/* stdout */
834283270Sdelphij	pfd[POLL_STDOUT].fd = stdout_fd;
835283270Sdelphij	pfd[POLL_STDOUT].events = 0;
836283270Sdelphij
837283270Sdelphij	while (1) {
838283270Sdelphij		/* both inputs are gone, buffers are empty, we are done */
839283270Sdelphij		if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
840283270Sdelphij		    && stdinbufpos == 0 && netinbufpos == 0) {
841283270Sdelphij			close(net_fd);
842283270Sdelphij			return;
843283270Sdelphij		}
844283270Sdelphij		/* both outputs are gone, we can't continue */
845283270Sdelphij		if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
846283270Sdelphij			close(net_fd);
847283270Sdelphij			return;
848283270Sdelphij		}
849283270Sdelphij		/* listen and net in gone, queues empty, done */
850283270Sdelphij		if (lflag && pfd[POLL_NETIN].fd == -1
851283270Sdelphij		    && stdinbufpos == 0 && netinbufpos == 0) {
852283270Sdelphij			close(net_fd);
853283270Sdelphij			return;
854283270Sdelphij		}
855283270Sdelphij
856283270Sdelphij		/* help says -i is for "wait between lines sent". We read and
857283270Sdelphij		 * write arbitrary amounts of data, and we don't want to start
858283270Sdelphij		 * scanning for newlines, so this is as good as it gets */
859141261Sdelphij		if (iflag)
860141261Sdelphij			sleep(iflag);
861141261Sdelphij
862283270Sdelphij		/* poll */
863283270Sdelphij		num_fds = poll(pfd, 4, timeout);
864283270Sdelphij
865283270Sdelphij		/* treat poll errors */
866283270Sdelphij		if (num_fds == -1) {
867283270Sdelphij			close(net_fd);
868283270Sdelphij			err(1, "polling error");
869141261Sdelphij		}
870141261Sdelphij
871283270Sdelphij		/* timeout happened */
872283270Sdelphij		if (num_fds == 0)
873141261Sdelphij			return;
874141261Sdelphij
875283270Sdelphij		/* treat socket error conditions */
876283270Sdelphij		for (n = 0; n < 4; n++) {
877283270Sdelphij			if (pfd[n].revents & (POLLERR|POLLNVAL)) {
878283270Sdelphij				pfd[n].fd = -1;
879141261Sdelphij			}
880141261Sdelphij		}
881283270Sdelphij		/* reading is possible after HUP */
882283270Sdelphij		if (pfd[POLL_STDIN].events & POLLIN &&
883283270Sdelphij		    pfd[POLL_STDIN].revents & POLLHUP &&
884283270Sdelphij		    ! (pfd[POLL_STDIN].revents & POLLIN))
885283270Sdelphij				pfd[POLL_STDIN].fd = -1;
886141261Sdelphij
887283270Sdelphij		if (pfd[POLL_NETIN].events & POLLIN &&
888283270Sdelphij		    pfd[POLL_NETIN].revents & POLLHUP &&
889283270Sdelphij		    ! (pfd[POLL_NETIN].revents & POLLIN))
890283270Sdelphij				pfd[POLL_NETIN].fd = -1;
891283270Sdelphij
892283270Sdelphij		if (pfd[POLL_NETOUT].revents & POLLHUP) {
893283270Sdelphij			if (Nflag)
894283270Sdelphij				shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
895283270Sdelphij			pfd[POLL_NETOUT].fd = -1;
896283270Sdelphij		}
897283270Sdelphij		/* if HUP, stop watching stdout */
898283270Sdelphij		if (pfd[POLL_STDOUT].revents & POLLHUP)
899283270Sdelphij			pfd[POLL_STDOUT].fd = -1;
900283270Sdelphij		/* if no net out, stop watching stdin */
901283270Sdelphij		if (pfd[POLL_NETOUT].fd == -1)
902283270Sdelphij			pfd[POLL_STDIN].fd = -1;
903283270Sdelphij		/* if no stdout, stop watching net in */
904283270Sdelphij		if (pfd[POLL_STDOUT].fd == -1) {
905283270Sdelphij			if (pfd[POLL_NETIN].fd != -1)
906283270Sdelphij				shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
907283270Sdelphij			pfd[POLL_NETIN].fd = -1;
908283270Sdelphij		}
909283270Sdelphij
910283270Sdelphij		/* try to read from stdin */
911283270Sdelphij		if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
912283270Sdelphij			ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
913283270Sdelphij			    &stdinbufpos);
914283270Sdelphij			/* error or eof on stdin - remove from pfd */
915283270Sdelphij			if (ret == 0 || ret == -1)
916283270Sdelphij				pfd[POLL_STDIN].fd = -1;
917283270Sdelphij			/* read something - poll net out */
918283270Sdelphij			if (stdinbufpos > 0)
919283270Sdelphij				pfd[POLL_NETOUT].events = POLLOUT;
920283270Sdelphij			/* filled buffer - remove self from polling */
921283270Sdelphij			if (stdinbufpos == BUFSIZE)
922283270Sdelphij				pfd[POLL_STDIN].events = 0;
923283270Sdelphij		}
924283270Sdelphij		/* try to write to network */
925283270Sdelphij		if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
926283270Sdelphij			ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
927283270Sdelphij			    &stdinbufpos);
928283270Sdelphij			if (ret == -1)
929283270Sdelphij				pfd[POLL_NETOUT].fd = -1;
930283270Sdelphij			/* buffer empty - remove self from polling */
931283270Sdelphij			if (stdinbufpos == 0)
932283270Sdelphij				pfd[POLL_NETOUT].events = 0;
933283270Sdelphij			/* buffer no longer full - poll stdin again */
934283270Sdelphij			if (stdinbufpos < BUFSIZE)
935283270Sdelphij				pfd[POLL_STDIN].events = POLLIN;
936283270Sdelphij		}
937283270Sdelphij		/* try to read from network */
938283270Sdelphij		if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
939283270Sdelphij			ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
940283270Sdelphij			    &netinbufpos);
941283270Sdelphij			if (ret == -1)
942283270Sdelphij				pfd[POLL_NETIN].fd = -1;
943283270Sdelphij			/* eof on net in - remove from pfd */
944283270Sdelphij			if (ret == 0) {
945283270Sdelphij				shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
946283270Sdelphij				pfd[POLL_NETIN].fd = -1;
947141261Sdelphij			}
948283270Sdelphij			/* read something - poll stdout */
949283270Sdelphij			if (netinbufpos > 0)
950283270Sdelphij				pfd[POLL_STDOUT].events = POLLOUT;
951283270Sdelphij			/* filled buffer - remove self from polling */
952283270Sdelphij			if (netinbufpos == BUFSIZE)
953283270Sdelphij				pfd[POLL_NETIN].events = 0;
954283270Sdelphij			/* handle telnet */
955283270Sdelphij			if (tflag)
956283270Sdelphij				atelnet(pfd[POLL_NETIN].fd, netinbuf,
957283270Sdelphij				    netinbufpos);
958141261Sdelphij		}
959283270Sdelphij		/* try to write to stdout */
960283270Sdelphij		if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
961283270Sdelphij			ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
962283270Sdelphij			    &netinbufpos);
963283270Sdelphij			if (ret == -1)
964283270Sdelphij				pfd[POLL_STDOUT].fd = -1;
965283270Sdelphij			/* buffer empty - remove self from polling */
966283270Sdelphij			if (netinbufpos == 0)
967283270Sdelphij				pfd[POLL_STDOUT].events = 0;
968283270Sdelphij			/* buffer no longer full - poll net in again */
969283270Sdelphij			if (netinbufpos < BUFSIZE)
970283270Sdelphij				pfd[POLL_NETIN].events = POLLIN;
971283270Sdelphij		}
972283270Sdelphij
973283270Sdelphij		/* stdin gone and queue empty? */
974283270Sdelphij		if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
975283270Sdelphij			if (pfd[POLL_NETOUT].fd != -1 && Nflag)
976283270Sdelphij				shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
977283270Sdelphij			pfd[POLL_NETOUT].fd = -1;
978283270Sdelphij		}
979283270Sdelphij		/* net in gone and queue empty? */
980283270Sdelphij		if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
981283270Sdelphij			pfd[POLL_STDOUT].fd = -1;
982283270Sdelphij		}
983141261Sdelphij	}
984141261Sdelphij}
985141261Sdelphij
986283270Sdelphijssize_t
987283270Sdelphijdrainbuf(int fd, unsigned char *buf, size_t *bufpos)
988283270Sdelphij{
989283270Sdelphij	ssize_t n;
990283270Sdelphij	ssize_t adjust;
991283270Sdelphij
992283270Sdelphij	n = write(fd, buf, *bufpos);
993283270Sdelphij	/* don't treat EAGAIN, EINTR as error */
994283270Sdelphij	if (n == -1 && (errno == EAGAIN || errno == EINTR))
995283270Sdelphij		n = -2;
996283270Sdelphij	if (n <= 0)
997283270Sdelphij		return n;
998283270Sdelphij	/* adjust buffer */
999283270Sdelphij	adjust = *bufpos - n;
1000283270Sdelphij	if (adjust > 0)
1001283270Sdelphij		memmove(buf, buf + n, adjust);
1002283270Sdelphij	*bufpos -= n;
1003283270Sdelphij	return n;
1004283270Sdelphij}
1005283270Sdelphij
1006283270Sdelphij
1007283270Sdelphijssize_t
1008283270Sdelphijfillbuf(int fd, unsigned char *buf, size_t *bufpos)
1009283270Sdelphij{
1010283270Sdelphij	size_t num = BUFSIZE - *bufpos;
1011283270Sdelphij	ssize_t n;
1012283270Sdelphij
1013283270Sdelphij	n = read(fd, buf + *bufpos, num);
1014283270Sdelphij	/* don't treat EAGAIN, EINTR as error */
1015283270Sdelphij	if (n == -1 && (errno == EAGAIN || errno == EINTR))
1016283270Sdelphij		n = -2;
1017283270Sdelphij	if (n <= 0)
1018283270Sdelphij		return n;
1019283270Sdelphij	*bufpos += n;
1020283270Sdelphij	return n;
1021283270Sdelphij}
1022283270Sdelphij
1023264911Sdelphij/*
1024264911Sdelphij * fdpass()
1025264911Sdelphij * Pass the connected file descriptor to stdout and exit.
1026264911Sdelphij */
1027264911Sdelphijvoid
1028264911Sdelphijfdpass(int nfd)
1029264911Sdelphij{
1030264911Sdelphij	struct msghdr mh;
1031264911Sdelphij	union {
1032264911Sdelphij		struct cmsghdr hdr;
1033264911Sdelphij		char buf[CMSG_SPACE(sizeof(int))];
1034264911Sdelphij	} cmsgbuf;
1035264911Sdelphij	struct cmsghdr *cmsg;
1036264911Sdelphij	struct iovec iov;
1037264911Sdelphij	char c = '\0';
1038264911Sdelphij	ssize_t r;
1039264911Sdelphij	struct pollfd pfd;
1040264911Sdelphij
1041264911Sdelphij	/* Avoid obvious stupidity */
1042264911Sdelphij	if (isatty(STDOUT_FILENO))
1043264911Sdelphij		errx(1, "Cannot pass file descriptor to tty");
1044264911Sdelphij
1045264911Sdelphij	bzero(&mh, sizeof(mh));
1046264911Sdelphij	bzero(&cmsgbuf, sizeof(cmsgbuf));
1047264911Sdelphij	bzero(&iov, sizeof(iov));
1048264911Sdelphij
1049264911Sdelphij	mh.msg_control = (caddr_t)&cmsgbuf.buf;
1050264911Sdelphij	mh.msg_controllen = sizeof(cmsgbuf.buf);
1051264911Sdelphij	cmsg = CMSG_FIRSTHDR(&mh);
1052264911Sdelphij	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1053264911Sdelphij	cmsg->cmsg_level = SOL_SOCKET;
1054264911Sdelphij	cmsg->cmsg_type = SCM_RIGHTS;
1055264911Sdelphij	*(int *)CMSG_DATA(cmsg) = nfd;
1056264911Sdelphij
1057264911Sdelphij	iov.iov_base = &c;
1058264911Sdelphij	iov.iov_len = 1;
1059264911Sdelphij	mh.msg_iov = &iov;
1060264911Sdelphij	mh.msg_iovlen = 1;
1061264911Sdelphij
1062264911Sdelphij	bzero(&pfd, sizeof(pfd));
1063264911Sdelphij	pfd.fd = STDOUT_FILENO;
1064294288Sdelphij	pfd.events = POLLOUT;
1065264911Sdelphij	for (;;) {
1066264911Sdelphij		r = sendmsg(STDOUT_FILENO, &mh, 0);
1067264911Sdelphij		if (r == -1) {
1068264911Sdelphij			if (errno == EAGAIN || errno == EINTR) {
1069264911Sdelphij				if (poll(&pfd, 1, -1) == -1)
1070264911Sdelphij					err(1, "poll");
1071264911Sdelphij				continue;
1072264911Sdelphij			}
1073264911Sdelphij			err(1, "sendmsg");
1074294288Sdelphij		} else if (r != 1)
1075264911Sdelphij			errx(1, "sendmsg: unexpected return value %zd", r);
1076264911Sdelphij		else
1077264911Sdelphij			break;
1078264911Sdelphij	}
1079264911Sdelphij	exit(0);
1080264911Sdelphij}
1081264911Sdelphij
1082141261Sdelphij/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
1083141261Sdelphijvoid
1084141261Sdelphijatelnet(int nfd, unsigned char *buf, unsigned int size)
1085141261Sdelphij{
1086141261Sdelphij	unsigned char *p, *end;
1087141261Sdelphij	unsigned char obuf[4];
1088141261Sdelphij
1089205561Sdelphij	if (size < 3)
1090205561Sdelphij		return;
1091205561Sdelphij	end = buf + size - 2;
1092141261Sdelphij
1093141261Sdelphij	for (p = buf; p < end; p++) {
1094141261Sdelphij		if (*p != IAC)
1095205561Sdelphij			continue;
1096141261Sdelphij
1097141261Sdelphij		obuf[0] = IAC;
1098141261Sdelphij		p++;
1099141261Sdelphij		if ((*p == WILL) || (*p == WONT))
1100141261Sdelphij			obuf[1] = DONT;
1101205561Sdelphij		else if ((*p == DO) || (*p == DONT))
1102141261Sdelphij			obuf[1] = WONT;
1103205561Sdelphij		else
1104205561Sdelphij			continue;
1105205561Sdelphij
1106205561Sdelphij		p++;
1107205561Sdelphij		obuf[2] = *p;
1108205561Sdelphij		if (atomicio(vwrite, nfd, obuf, 3) != 3)
1109205561Sdelphij			warn("Write Error!");
1110141261Sdelphij	}
1111141261Sdelphij}
1112141261Sdelphij
1113141261Sdelphij/*
1114141261Sdelphij * build_ports()
1115235037Sdelphij * Build an array of ports in portlist[], listing each port
1116141261Sdelphij * that we should try to connect to.
1117141261Sdelphij */
1118141261Sdelphijvoid
1119141261Sdelphijbuild_ports(char *p)
1120141261Sdelphij{
1121167964Sdelphij	const char *errstr;
1122167964Sdelphij	char *n;
1123141261Sdelphij	int hi, lo, cp;
1124141261Sdelphij	int x = 0;
1125141261Sdelphij
1126141261Sdelphij	if ((n = strchr(p, '-')) != NULL) {
1127141261Sdelphij		*n = '\0';
1128141261Sdelphij		n++;
1129141261Sdelphij
1130141261Sdelphij		/* Make sure the ports are in order: lowest->highest. */
1131167964Sdelphij		hi = strtonum(n, 1, PORT_MAX, &errstr);
1132167964Sdelphij		if (errstr)
1133167964Sdelphij			errx(1, "port number %s: %s", errstr, n);
1134167964Sdelphij		lo = strtonum(p, 1, PORT_MAX, &errstr);
1135167964Sdelphij		if (errstr)
1136167964Sdelphij			errx(1, "port number %s: %s", errstr, p);
1137141261Sdelphij
1138141261Sdelphij		if (lo > hi) {
1139141261Sdelphij			cp = hi;
1140141261Sdelphij			hi = lo;
1141141261Sdelphij			lo = cp;
1142141261Sdelphij		}
1143141261Sdelphij
1144141261Sdelphij		/* Load ports sequentially. */
1145141261Sdelphij		for (cp = lo; cp <= hi; cp++) {
1146141261Sdelphij			portlist[x] = calloc(1, PORT_MAX_LEN);
1147141261Sdelphij			if (portlist[x] == NULL)
1148141261Sdelphij				err(1, NULL);
1149141261Sdelphij			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
1150141261Sdelphij			x++;
1151141261Sdelphij		}
1152141261Sdelphij
1153141261Sdelphij		/* Randomly swap ports. */
1154141261Sdelphij		if (rflag) {
1155141261Sdelphij			int y;
1156141261Sdelphij			char *c;
1157141261Sdelphij
1158141261Sdelphij			for (x = 0; x <= (hi - lo); x++) {
1159141261Sdelphij				y = (arc4random() & 0xFFFF) % (hi - lo);
1160141261Sdelphij				c = portlist[x];
1161141261Sdelphij				portlist[x] = portlist[y];
1162141261Sdelphij				portlist[y] = c;
1163141261Sdelphij			}
1164141261Sdelphij		}
1165141261Sdelphij	} else {
1166167964Sdelphij		hi = strtonum(p, 1, PORT_MAX, &errstr);
1167167964Sdelphij		if (errstr)
1168167964Sdelphij			errx(1, "port number %s: %s", errstr, p);
1169214047Sdelphij		portlist[0] = strdup(p);
1170141261Sdelphij		if (portlist[0] == NULL)
1171141261Sdelphij			err(1, NULL);
1172141261Sdelphij	}
1173141261Sdelphij}
1174141261Sdelphij
1175141261Sdelphij/*
1176141261Sdelphij * udptest()
1177141261Sdelphij * Do a few writes to see if the UDP port is there.
1178235037Sdelphij * Fails once PF state table is full.
1179141261Sdelphij */
1180141261Sdelphijint
1181141261Sdelphijudptest(int s)
1182141261Sdelphij{
1183141261Sdelphij	int i, ret;
1184141261Sdelphij
1185141261Sdelphij	for (i = 0; i <= 3; i++) {
1186141261Sdelphij		if (write(s, "X", 1) == 1)
1187141261Sdelphij			ret = 1;
1188141261Sdelphij		else
1189141261Sdelphij			ret = -1;
1190141261Sdelphij	}
1191141261Sdelphij	return (ret);
1192141261Sdelphij}
1193141261Sdelphij
1194141261Sdelphijvoid
1195283270Sdelphijset_common_sockopts(int s, int af)
1196158798Sdelphij{
1197158798Sdelphij	int x = 1;
1198158798Sdelphij
1199158798Sdelphij	if (Sflag) {
1200158798Sdelphij		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
1201158798Sdelphij			&x, sizeof(x)) == -1)
1202158798Sdelphij			err(1, NULL);
1203158798Sdelphij	}
1204158798Sdelphij	if (Dflag) {
1205158798Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
1206158798Sdelphij			&x, sizeof(x)) == -1)
1207158798Sdelphij			err(1, NULL);
1208158798Sdelphij	}
1209158798Sdelphij	if (Tflag != -1) {
1210283270Sdelphij		int proto, option;
1211283270Sdelphij
1212283270Sdelphij		if (af == AF_INET6) {
1213283270Sdelphij			proto = IPPROTO_IPV6;
1214283270Sdelphij			option = IPV6_TCLASS;
1215283270Sdelphij		} else {
1216283270Sdelphij			proto = IPPROTO_IP;
1217283270Sdelphij			option = IP_TOS;
1218283270Sdelphij		}
1219283270Sdelphij
1220283270Sdelphij		if (setsockopt(s, proto, option, &Tflag, sizeof(Tflag)) == -1)
1221158798Sdelphij			err(1, "set IP ToS");
1222158798Sdelphij	}
1223186343Sdelphij	if (Iflag) {
1224186343Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
1225186343Sdelphij		    &Iflag, sizeof(Iflag)) == -1)
1226186343Sdelphij			err(1, "set TCP receive buffer size");
1227186343Sdelphij	}
1228177837Sbms	if (Oflag) {
1229186343Sdelphij		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1230186343Sdelphij		    &Oflag, sizeof(Oflag)) == -1)
1231186343Sdelphij			err(1, "set TCP send buffer size");
1232186343Sdelphij	}
1233186343Sdelphij	if (FreeBSD_Oflag) {
1234177837Sbms		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
1235186343Sdelphij		    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
1236177837Sbms			err(1, "disable TCP options");
1237177837Sbms	}
1238158798Sdelphij}
1239158798Sdelphij
1240158798Sdelphijint
1241235037Sdelphijmap_tos(char *s, int *val)
1242158798Sdelphij{
1243235037Sdelphij	/* DiffServ Codepoints and other TOS mappings */
1244235037Sdelphij	const struct toskeywords {
1245235037Sdelphij		const char	*keyword;
1246235037Sdelphij		int		 val;
1247235037Sdelphij	} *t, toskeywords[] = {
1248235037Sdelphij		{ "af11",		IPTOS_DSCP_AF11 },
1249235037Sdelphij		{ "af12",		IPTOS_DSCP_AF12 },
1250235037Sdelphij		{ "af13",		IPTOS_DSCP_AF13 },
1251235037Sdelphij		{ "af21",		IPTOS_DSCP_AF21 },
1252235037Sdelphij		{ "af22",		IPTOS_DSCP_AF22 },
1253235037Sdelphij		{ "af23",		IPTOS_DSCP_AF23 },
1254235037Sdelphij		{ "af31",		IPTOS_DSCP_AF31 },
1255235037Sdelphij		{ "af32",		IPTOS_DSCP_AF32 },
1256235037Sdelphij		{ "af33",		IPTOS_DSCP_AF33 },
1257235037Sdelphij		{ "af41",		IPTOS_DSCP_AF41 },
1258235037Sdelphij		{ "af42",		IPTOS_DSCP_AF42 },
1259235037Sdelphij		{ "af43",		IPTOS_DSCP_AF43 },
1260235037Sdelphij		{ "critical",		IPTOS_PREC_CRITIC_ECP },
1261235037Sdelphij		{ "cs0",		IPTOS_DSCP_CS0 },
1262235037Sdelphij		{ "cs1",		IPTOS_DSCP_CS1 },
1263235037Sdelphij		{ "cs2",		IPTOS_DSCP_CS2 },
1264235037Sdelphij		{ "cs3",		IPTOS_DSCP_CS3 },
1265235037Sdelphij		{ "cs4",		IPTOS_DSCP_CS4 },
1266235037Sdelphij		{ "cs5",		IPTOS_DSCP_CS5 },
1267235037Sdelphij		{ "cs6",		IPTOS_DSCP_CS6 },
1268235037Sdelphij		{ "cs7",		IPTOS_DSCP_CS7 },
1269235037Sdelphij		{ "ef",			IPTOS_DSCP_EF },
1270235037Sdelphij		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
1271235037Sdelphij		{ "lowdelay",		IPTOS_LOWDELAY },
1272235037Sdelphij		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
1273235037Sdelphij		{ "reliability",	IPTOS_RELIABILITY },
1274235037Sdelphij		{ "throughput",		IPTOS_THROUGHPUT },
1275235037Sdelphij		{ NULL, 		-1 },
1276235037Sdelphij	};
1277158798Sdelphij
1278235037Sdelphij	for (t = toskeywords; t->keyword != NULL; t++) {
1279235037Sdelphij		if (strcmp(s, t->keyword) == 0) {
1280235037Sdelphij			*val = t->val;
1281235037Sdelphij			return (1);
1282235037Sdelphij		}
1283235037Sdelphij	}
1284158798Sdelphij
1285235037Sdelphij	return (0);
1286158798Sdelphij}
1287158798Sdelphij
1288158798Sdelphijvoid
1289241906Sdelphijreport_connect(const struct sockaddr *sa, socklen_t salen)
1290241906Sdelphij{
1291241906Sdelphij	char remote_host[NI_MAXHOST];
1292241906Sdelphij	char remote_port[NI_MAXSERV];
1293241906Sdelphij	int herr;
1294241906Sdelphij	int flags = NI_NUMERICSERV;
1295241906Sdelphij
1296241906Sdelphij	if (nflag)
1297241906Sdelphij		flags |= NI_NUMERICHOST;
1298241906Sdelphij
1299241906Sdelphij	if ((herr = getnameinfo(sa, salen,
1300241906Sdelphij	    remote_host, sizeof(remote_host),
1301241906Sdelphij	    remote_port, sizeof(remote_port),
1302241906Sdelphij	    flags)) != 0) {
1303241906Sdelphij		if (herr == EAI_SYSTEM)
1304241906Sdelphij			err(1, "getnameinfo");
1305241906Sdelphij		else
1306241906Sdelphij			errx(1, "getnameinfo: %s", gai_strerror(herr));
1307241906Sdelphij	}
1308241906Sdelphij
1309241906Sdelphij	fprintf(stderr,
1310241906Sdelphij	    "Connection from %s %s "
1311241906Sdelphij	    "received!\n", remote_host, remote_port);
1312241906Sdelphij}
1313241906Sdelphij
1314241906Sdelphijvoid
1315141261Sdelphijhelp(void)
1316141261Sdelphij{
1317141261Sdelphij	usage(0);
1318141261Sdelphij	fprintf(stderr, "\tCommand Summary:\n\
1319141261Sdelphij	\t-4		Use IPv4\n\
1320178927Santoine	\t-6		Use IPv6\n\
1321178927Santoine	\t-D		Enable the debug socket option\n\
1322178927Santoine	\t-d		Detach from stdin\n");
1323141394Sdelphij#ifdef IPSEC
1324141394Sdelphij	fprintf(stderr, "\
1325178927Santoine	\t-E		Use IPsec ESP\n\
1326178927Santoine	\t-e policy	Use specified IPsec policy\n");
1327141394Sdelphij#endif
1328141394Sdelphij	fprintf(stderr, "\
1329264911Sdelphij	\t-F		Pass socket fd\n\
1330141261Sdelphij	\t-h		This help text\n\
1331186343Sdelphij	\t-I length	TCP receive buffer length\n\
1332141261Sdelphij	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
1333141261Sdelphij	\t-k		Keep inbound sockets open for multiple connects\n\
1334141261Sdelphij	\t-l		Listen mode, for inbound connects\n\
1335249499Sdelphij	\t-N		Shutdown the network socket after EOF on stdin\n\
1336141261Sdelphij	\t-n		Suppress name/port resolutions\n\
1337186343Sdelphij	\t--no-tcpopt	Disable TCP options\n\
1338186343Sdelphij	\t-O length	TCP send buffer length\n\
1339158798Sdelphij	\t-P proxyuser\tUsername for proxy authentication\n\
1340141261Sdelphij	\t-p port\t	Specify local port for remote connects\n\
1341141261Sdelphij	\t-r		Randomize remote ports\n\
1342141261Sdelphij	\t-S		Enable the TCP MD5 signature option\n\
1343141261Sdelphij	\t-s addr\t	Local source address\n\
1344235037Sdelphij	\t-T toskeyword\tSet IP Type of Service\n\
1345141261Sdelphij	\t-t		Answer TELNET negotiation\n\
1346141261Sdelphij	\t-U		Use UNIX domain socket\n\
1347141261Sdelphij	\t-u		UDP mode\n\
1348214047Sdelphij	\t-V rtable	Specify alternate routing table\n\
1349141261Sdelphij	\t-v		Verbose\n\
1350141261Sdelphij	\t-w secs\t	Timeout for connects and final net reads\n\
1351141261Sdelphij	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1352141261Sdelphij	\t-x addr[:port]\tSpecify proxy address and port\n\
1353141261Sdelphij	\t-z		Zero-I/O mode [used for scanning]\n\
1354141261Sdelphij	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1355141394Sdelphij#ifdef IPSEC
1356141394Sdelphij	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
1357141394Sdelphij#endif
1358141261Sdelphij	exit(1);
1359141261Sdelphij}
1360141261Sdelphij
1361141394Sdelphij#ifdef IPSEC
1362141261Sdelphijvoid
1363141394Sdelphijadd_ipsec_policy(int s, char *policy)
1364141394Sdelphij{
1365141394Sdelphij	char *raw;
1366141394Sdelphij	int e;
1367141394Sdelphij
1368141394Sdelphij	raw = ipsec_set_policy(policy, strlen(policy));
1369141394Sdelphij	if (raw == NULL)
1370141394Sdelphij		errx(1, "ipsec_set_policy `%s': %s", policy,
1371141394Sdelphij		     ipsec_strerror());
1372141394Sdelphij	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
1373141394Sdelphij			ipsec_get_policylen(raw));
1374141394Sdelphij	if (e < 0)
1375141394Sdelphij		err(1, "ipsec policy cannot be configured");
1376141394Sdelphij	free(raw);
1377141394Sdelphij	if (vflag)
1378141394Sdelphij		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
1379141394Sdelphij	return;
1380141394Sdelphij}
1381141394Sdelphij#endif /* IPSEC */
1382141394Sdelphij
1383141394Sdelphijvoid
1384141261Sdelphijusage(int ret)
1385141261Sdelphij{
1386193008Sdelphij	fprintf(stderr,
1387141394Sdelphij#ifdef IPSEC
1388264911Sdelphij	    "usage: nc [-46DdEFhklNnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
1389141394Sdelphij#else
1390264911Sdelphij	    "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
1391141394Sdelphij#endif
1392221793Sdelphij	    "\t  [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1393214047Sdelphij	    "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1394221793Sdelphij	    "\t  [-x proxy_address[:port]] [destination] [port]\n");
1395141261Sdelphij	if (ret)
1396141261Sdelphij		exit(1);
1397141261Sdelphij}
1398