xref: /freebsd/contrib/netcat/netcat.c (revision c6ec7d31830ab1c80edae95ad5e4b9dba10c47ac)
1 /* $OpenBSD: netcat.c,v 1.109 2012/07/07 15:33:02 haesbaert Exp $ */
2 /*
3  * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *   notice, this list of conditions and the following disclaimer in the
13  *   documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *   derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 /*
32  * Re-written nc(1) for OpenBSD. Original implementation by
33  * *Hobbit* <hobbit@avian.org>.
34  */
35 
36 #include <sys/limits.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/sysctl.h>
40 #include <sys/time.h>
41 #include <sys/un.h>
42 
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 #ifdef IPSEC
46 #include <netipsec/ipsec.h>
47 #endif
48 #include <netinet/tcp.h>
49 #include <netinet/ip.h>
50 #include <arpa/telnet.h>
51 
52 #include <err.h>
53 #include <errno.h>
54 #include <getopt.h>
55 #include <netdb.h>
56 #include <poll.h>
57 #include <stdarg.h>
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <unistd.h>
62 #include <fcntl.h>
63 #include <limits.h>
64 #include "atomicio.h"
65 
66 #ifndef SUN_LEN
67 #define SUN_LEN(su) \
68 	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
69 #endif
70 
71 #define PORT_MAX	65535
72 #define PORT_MAX_LEN	6
73 #define UNIX_DG_TMP_SOCKET_SIZE	19
74 
75 /* Command Line Options */
76 int	dflag;					/* detached, no stdin */
77 unsigned int iflag;				/* Interval Flag */
78 int	kflag;					/* More than one connect */
79 int	lflag;					/* Bind to local port */
80 int	nflag;					/* Don't do name look up */
81 int	FreeBSD_Oflag;				/* Do not use TCP options */
82 char   *Pflag;					/* Proxy username */
83 char   *pflag;					/* Localport flag */
84 int	rflag;					/* Random ports flag */
85 char   *sflag;					/* Source Address */
86 int	tflag;					/* Telnet Emulation */
87 int	uflag;					/* UDP - Default to TCP */
88 int	vflag;					/* Verbosity */
89 int	xflag;					/* Socks proxy */
90 int	zflag;					/* Port Scan Flag */
91 int	Dflag;					/* sodebug */
92 int	Iflag;					/* TCP receive buffer size */
93 int	Oflag;					/* TCP send buffer size */
94 int	Sflag;					/* TCP MD5 signature option */
95 int	Tflag = -1;				/* IP Type of Service */
96 u_int	rtableid;
97 
98 int timeout = -1;
99 int family = AF_UNSPEC;
100 char *portlist[PORT_MAX+1];
101 char *unix_dg_tmp_socket;
102 
103 void	atelnet(int, unsigned char *, unsigned int);
104 void	build_ports(char *);
105 void	help(void);
106 int	local_listen(char *, char *, struct addrinfo);
107 void	readwrite(int);
108 int	remote_connect(const char *, const char *, struct addrinfo);
109 int	timeout_connect(int, const struct sockaddr *, socklen_t);
110 int	socks_connect(const char *, const char *, struct addrinfo,
111 	    const char *, const char *, struct addrinfo, int, const char *);
112 int	udptest(int);
113 int	unix_bind(char *);
114 int	unix_connect(char *);
115 int	unix_listen(char *);
116 void	set_common_sockopts(int);
117 int	map_tos(char *, int *);
118 void	report_connect(const struct sockaddr *, socklen_t);
119 void	usage(int);
120 
121 #ifdef IPSEC
122 void	add_ipsec_policy(int, char *);
123 
124 char	*ipsec_policy[2];
125 #endif
126 
127 int
128 main(int argc, char *argv[])
129 {
130 	int ch, s, ret, socksv, ipsec_count;
131 	int numfibs;
132 	size_t intsize = sizeof(int);
133 	char *host, *uport;
134 	struct addrinfo hints;
135 	struct servent *sv;
136 	socklen_t len;
137 	struct sockaddr_storage cliaddr;
138 	char *proxy;
139 	const char *errstr, *proxyhost = "", *proxyport = NULL;
140 	struct addrinfo proxyhints;
141 	char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
142 	struct option longopts[] = {
143 		{ "no-tcpopt",	no_argument,	&FreeBSD_Oflag,	1 },
144 		{ NULL,		0,		NULL,		0 }
145 	};
146 
147 	ret = 1;
148 	ipsec_count = 0;
149 	s = 0;
150 	socksv = 5;
151 	host = NULL;
152 	uport = NULL;
153 	sv = NULL;
154 
155 	while ((ch = getopt_long(argc, argv,
156 	    "46DdEe:hI:i:klnoO:P:p:rSs:tT:UuV:vw:X:x:z",
157 	    longopts, NULL)) != -1) {
158 		switch (ch) {
159 		case '4':
160 			family = AF_INET;
161 			break;
162 		case '6':
163 			family = AF_INET6;
164 			break;
165 		case 'U':
166 			family = AF_UNIX;
167 			break;
168 		case 'X':
169 			if (strcasecmp(optarg, "connect") == 0)
170 				socksv = -1; /* HTTP proxy CONNECT */
171 			else if (strcmp(optarg, "4") == 0)
172 				socksv = 4; /* SOCKS v.4 */
173 			else if (strcmp(optarg, "5") == 0)
174 				socksv = 5; /* SOCKS v.5 */
175 			else
176 				errx(1, "unsupported proxy protocol");
177 			break;
178 		case 'd':
179 			dflag = 1;
180 			break;
181 		case 'e':
182 #ifdef IPSEC
183 			ipsec_policy[ipsec_count++ % 2] = optarg;
184 #else
185 			errx(1, "IPsec support unavailable.");
186 #endif
187 			break;
188 		case 'E':
189 #ifdef IPSEC
190 			ipsec_policy[0] = "in  ipsec esp/transport//require";
191 			ipsec_policy[1] = "out ipsec esp/transport//require";
192 #else
193 			errx(1, "IPsec support unavailable.");
194 #endif
195 			break;
196 		case 'h':
197 			help();
198 			break;
199 		case 'i':
200 			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
201 			if (errstr)
202 				errx(1, "interval %s: %s", errstr, optarg);
203 			break;
204 		case 'k':
205 			kflag = 1;
206 			break;
207 		case 'l':
208 			lflag = 1;
209 			break;
210 		case 'n':
211 			nflag = 1;
212 			break;
213 		case 'o':
214 			fprintf(stderr, "option -o is deprecated.\n");
215 			break;
216 		case 'P':
217 			Pflag = optarg;
218 			break;
219 		case 'p':
220 			pflag = optarg;
221 			break;
222 		case 'r':
223 			rflag = 1;
224 			break;
225 		case 's':
226 			sflag = optarg;
227 			break;
228 		case 't':
229 			tflag = 1;
230 			break;
231 		case 'u':
232 			uflag = 1;
233 			break;
234 		case 'V':
235 			if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
236 				errx(1, "Multiple FIBS not supported");
237 			rtableid = (unsigned int)strtonum(optarg, 0,
238 			    numfibs - 1, &errstr);
239 			if (errstr)
240 				errx(1, "rtable %s: %s", errstr, optarg);
241 			break;
242 		case 'v':
243 			vflag = 1;
244 			break;
245 		case 'w':
246 			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
247 			if (errstr)
248 				errx(1, "timeout %s: %s", errstr, optarg);
249 			timeout *= 1000;
250 			break;
251 		case 'x':
252 			xflag = 1;
253 			if ((proxy = strdup(optarg)) == NULL)
254 				err(1, NULL);
255 			break;
256 		case 'z':
257 			zflag = 1;
258 			break;
259 		case 'D':
260 			Dflag = 1;
261 			break;
262 		case 'I':
263 			Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
264 			if (errstr != NULL)
265 				errx(1, "TCP receive window %s: %s",
266 				    errstr, optarg);
267 			break;
268 		case 'O':
269 			Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
270 			if (errstr != NULL) {
271 			    if (strcmp(errstr, "invalid") != 0)
272 				errx(1, "TCP send window %s: %s",
273 				    errstr, optarg);
274 			}
275 			break;
276 		case 'S':
277 			Sflag = 1;
278 			break;
279 		case 'T':
280 			errstr = NULL;
281 			errno = 0;
282 			if (map_tos(optarg, &Tflag))
283 				break;
284 			if (strlen(optarg) > 1 && optarg[0] == '0' &&
285 			    optarg[1] == 'x')
286 				Tflag = (int)strtol(optarg, NULL, 16);
287 			else
288 				Tflag = (int)strtonum(optarg, 0, 255,
289 				    &errstr);
290 			if (Tflag < 0 || Tflag > 255 || errstr || errno)
291 				errx(1, "illegal tos value %s", optarg);
292 			break;
293 		default:
294 			usage(1);
295 		}
296 	}
297 	argc -= optind;
298 	argv += optind;
299 
300 	/* Cruft to make sure options are clean, and used properly. */
301 	if (argv[0] && !argv[1] && family == AF_UNIX) {
302 		host = argv[0];
303 		uport = NULL;
304 	} else if (argv[0] && !argv[1]) {
305 		if  (!lflag)
306 			usage(1);
307 		uport = argv[0];
308 		host = NULL;
309 	} else if (argv[0] && argv[1]) {
310 		host = argv[0];
311 		uport = argv[1];
312 	} else
313 		usage(1);
314 
315 	if (lflag && sflag)
316 		errx(1, "cannot use -s and -l");
317 	if (lflag && pflag)
318 		errx(1, "cannot use -p and -l");
319 	if (lflag && zflag)
320 		errx(1, "cannot use -z and -l");
321 	if (!lflag && kflag)
322 		errx(1, "must use -l with -k");
323 
324 	/* Get name of temporary socket for unix datagram client */
325 	if ((family == AF_UNIX) && uflag && !lflag) {
326 		if (sflag) {
327 			unix_dg_tmp_socket = sflag;
328 		} else {
329 			strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
330 				UNIX_DG_TMP_SOCKET_SIZE);
331 			if (mktemp(unix_dg_tmp_socket_buf) == NULL)
332 				err(1, "mktemp");
333 			unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
334 		}
335 	}
336 
337 	/* Initialize addrinfo structure. */
338 	if (family != AF_UNIX) {
339 		memset(&hints, 0, sizeof(struct addrinfo));
340 		hints.ai_family = family;
341 		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
342 		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
343 		if (nflag)
344 			hints.ai_flags |= AI_NUMERICHOST;
345 	}
346 
347 	if (xflag) {
348 		if (uflag)
349 			errx(1, "no proxy support for UDP mode");
350 
351 		if (lflag)
352 			errx(1, "no proxy support for listen");
353 
354 		if (family == AF_UNIX)
355 			errx(1, "no proxy support for unix sockets");
356 
357 		/* XXX IPv6 transport to proxy would probably work */
358 		if (family == AF_INET6)
359 			errx(1, "no proxy support for IPv6");
360 
361 		if (sflag)
362 			errx(1, "no proxy support for local source address");
363 
364 		proxyhost = strsep(&proxy, ":");
365 		proxyport = proxy;
366 
367 		memset(&proxyhints, 0, sizeof(struct addrinfo));
368 		proxyhints.ai_family = family;
369 		proxyhints.ai_socktype = SOCK_STREAM;
370 		proxyhints.ai_protocol = IPPROTO_TCP;
371 		if (nflag)
372 			proxyhints.ai_flags |= AI_NUMERICHOST;
373 	}
374 
375 	if (lflag) {
376 		int connfd;
377 		ret = 0;
378 
379 		if (family == AF_UNIX) {
380 			if (uflag)
381 				s = unix_bind(host);
382 			else
383 				s = unix_listen(host);
384 		}
385 
386 		/* Allow only one connection at a time, but stay alive. */
387 		for (;;) {
388 			if (family != AF_UNIX)
389 				s = local_listen(host, uport, hints);
390 			if (s < 0)
391 				err(1, NULL);
392 			/*
393 			 * For UDP and -k, don't connect the socket, let it
394 			 * receive datagrams from multiple socket pairs.
395 			 */
396 			if (uflag && kflag)
397 				readwrite(s);
398 			/*
399 			 * For UDP and not -k, we will use recvfrom() initially
400 			 * to wait for a caller, then use the regular functions
401 			 * to talk to the caller.
402 			 */
403 			else if (uflag && !kflag) {
404 				int rv, plen;
405 				char buf[16384];
406 				struct sockaddr_storage z;
407 
408 				len = sizeof(z);
409 				plen = 2048;
410 				rv = recvfrom(s, buf, plen, MSG_PEEK,
411 				    (struct sockaddr *)&z, &len);
412 				if (rv < 0)
413 					err(1, "recvfrom");
414 
415 				rv = connect(s, (struct sockaddr *)&z, len);
416 				if (rv < 0)
417 					err(1, "connect");
418 
419 				if (vflag)
420 					report_connect((struct sockaddr *)&z, len);
421 
422 				readwrite(s);
423 			} else {
424 				len = sizeof(cliaddr);
425 				connfd = accept(s, (struct sockaddr *)&cliaddr,
426 				    &len);
427 				if (connfd == -1)
428 					err(1, "accept");
429 
430 				if (vflag)
431 					report_connect((struct sockaddr *)&cliaddr, len);
432 
433 				readwrite(connfd);
434 				close(connfd);
435 			}
436 
437 			if (family != AF_UNIX)
438 				close(s);
439 			else if (uflag) {
440 				if (connect(s, NULL, 0) < 0)
441 					err(1, "connect");
442 			}
443 
444 			if (!kflag)
445 				break;
446 		}
447 	} else if (family == AF_UNIX) {
448 		ret = 0;
449 
450 		if ((s = unix_connect(host)) > 0 && !zflag) {
451 			readwrite(s);
452 			close(s);
453 		} else
454 			ret = 1;
455 
456 		if (uflag)
457 			unlink(unix_dg_tmp_socket);
458 		exit(ret);
459 
460 	} else {
461 		int i = 0;
462 
463 		/* Construct the portlist[] array. */
464 		build_ports(uport);
465 
466 		/* Cycle through portlist, connecting to each port. */
467 		for (i = 0; portlist[i] != NULL; i++) {
468 			if (s)
469 				close(s);
470 
471 			if (xflag)
472 				s = socks_connect(host, portlist[i], hints,
473 				    proxyhost, proxyport, proxyhints, socksv,
474 				    Pflag);
475 			else
476 				s = remote_connect(host, portlist[i], hints);
477 
478 			if (s < 0)
479 				continue;
480 
481 			ret = 0;
482 			if (vflag || zflag) {
483 				/* For UDP, make sure we are connected. */
484 				if (uflag) {
485 					if (udptest(s) == -1) {
486 						ret = 1;
487 						continue;
488 					}
489 				}
490 
491 				/* Don't look up port if -n. */
492 				if (nflag)
493 					sv = NULL;
494 				else {
495 					sv = getservbyport(
496 					    ntohs(atoi(portlist[i])),
497 					    uflag ? "udp" : "tcp");
498 				}
499 
500 				fprintf(stderr,
501 				    "Connection to %s %s port [%s/%s] "
502 				    "succeeded!\n", host, portlist[i],
503 				    uflag ? "udp" : "tcp",
504 				    sv ? sv->s_name : "*");
505 			}
506 			if (!zflag)
507 				readwrite(s);
508 		}
509 	}
510 
511 	if (s)
512 		close(s);
513 
514 	exit(ret);
515 }
516 
517 /*
518  * unix_bind()
519  * Returns a unix socket bound to the given path
520  */
521 int
522 unix_bind(char *path)
523 {
524 	struct sockaddr_un sun;
525 	int s;
526 
527 	/* Create unix domain socket. */
528 	if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
529 	     0)) < 0)
530 		return (-1);
531 
532 	memset(&sun, 0, sizeof(struct sockaddr_un));
533 	sun.sun_family = AF_UNIX;
534 
535 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
536 	    sizeof(sun.sun_path)) {
537 		close(s);
538 		errno = ENAMETOOLONG;
539 		return (-1);
540 	}
541 
542 	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
543 		close(s);
544 		return (-1);
545 	}
546 	return (s);
547 }
548 
549 /*
550  * unix_connect()
551  * Returns a socket connected to a local unix socket. Returns -1 on failure.
552  */
553 int
554 unix_connect(char *path)
555 {
556 	struct sockaddr_un sun;
557 	int s;
558 
559 	if (uflag) {
560 		if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
561 			return (-1);
562 	} else {
563 		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
564 			return (-1);
565 	}
566 	(void)fcntl(s, F_SETFD, 1);
567 
568 	memset(&sun, 0, sizeof(struct sockaddr_un));
569 	sun.sun_family = AF_UNIX;
570 
571 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
572 	    sizeof(sun.sun_path)) {
573 		close(s);
574 		errno = ENAMETOOLONG;
575 		return (-1);
576 	}
577 	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
578 		close(s);
579 		return (-1);
580 	}
581 	return (s);
582 
583 }
584 
585 /*
586  * unix_listen()
587  * Create a unix domain socket, and listen on it.
588  */
589 int
590 unix_listen(char *path)
591 {
592 	int s;
593 	if ((s = unix_bind(path)) < 0)
594 		return (-1);
595 
596 	if (listen(s, 5) < 0) {
597 		close(s);
598 		return (-1);
599 	}
600 	return (s);
601 }
602 
603 /*
604  * remote_connect()
605  * Returns a socket connected to a remote host. Properly binds to a local
606  * port or source address if needed. Returns -1 on failure.
607  */
608 int
609 remote_connect(const char *host, const char *port, struct addrinfo hints)
610 {
611 	struct addrinfo *res, *res0;
612 	int s, error, on = 1;
613 
614 	if ((error = getaddrinfo(host, port, &hints, &res)))
615 		errx(1, "getaddrinfo: %s", gai_strerror(error));
616 
617 	res0 = res;
618 	do {
619 		if ((s = socket(res0->ai_family, res0->ai_socktype,
620 		    res0->ai_protocol)) < 0)
621 			continue;
622 #ifdef IPSEC
623 		if (ipsec_policy[0] != NULL)
624 			add_ipsec_policy(s, ipsec_policy[0]);
625 		if (ipsec_policy[1] != NULL)
626 			add_ipsec_policy(s, ipsec_policy[1]);
627 #endif
628 
629 		if (rtableid) {
630 			if (setsockopt(s, SOL_SOCKET, SO_SETFIB, &rtableid,
631 			    sizeof(rtableid)) == -1)
632 				err(1, "setsockopt(.., SO_SETFIB, %u, ..)",
633 				    rtableid);
634 		}
635 
636 		/* Bind to a local port or source address if specified. */
637 		if (sflag || pflag) {
638 			struct addrinfo ahints, *ares;
639 
640 			/* try IP_BINDANY, but don't insist */
641 			setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on));
642 			memset(&ahints, 0, sizeof(struct addrinfo));
643 			ahints.ai_family = res0->ai_family;
644 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
645 			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
646 			ahints.ai_flags = AI_PASSIVE;
647 			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
648 				errx(1, "getaddrinfo: %s", gai_strerror(error));
649 
650 			if (bind(s, (struct sockaddr *)ares->ai_addr,
651 			    ares->ai_addrlen) < 0)
652 				errx(1, "bind failed: %s", strerror(errno));
653 			freeaddrinfo(ares);
654 		}
655 
656 		set_common_sockopts(s);
657 
658 		if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
659 			break;
660 		else if (vflag)
661 			warn("connect to %s port %s (%s) failed", host, port,
662 			    uflag ? "udp" : "tcp");
663 
664 		close(s);
665 		s = -1;
666 	} while ((res0 = res0->ai_next) != NULL);
667 
668 	freeaddrinfo(res);
669 
670 	return (s);
671 }
672 
673 int
674 timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
675 {
676 	struct pollfd pfd;
677 	socklen_t optlen;
678 	int flags, optval;
679 	int ret;
680 
681 	if (timeout != -1) {
682 		flags = fcntl(s, F_GETFL, 0);
683 		if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
684 			err(1, "set non-blocking mode");
685 	}
686 
687 	if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
688 		pfd.fd = s;
689 		pfd.events = POLLOUT;
690 		if ((ret = poll(&pfd, 1, timeout)) == 1) {
691 			optlen = sizeof(optval);
692 			if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
693 			    &optval, &optlen)) == 0) {
694 				errno = optval;
695 				ret = optval == 0 ? 0 : -1;
696 			}
697 		} else if (ret == 0) {
698 			errno = ETIMEDOUT;
699 			ret = -1;
700 		} else
701 			err(1, "poll failed");
702 	}
703 
704 	if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
705 		err(1, "restoring flags");
706 
707 	return (ret);
708 }
709 
710 /*
711  * local_listen()
712  * Returns a socket listening on a local port, binds to specified source
713  * address. Returns -1 on failure.
714  */
715 int
716 local_listen(char *host, char *port, struct addrinfo hints)
717 {
718 	struct addrinfo *res, *res0;
719 	int s, ret, x = 1;
720 	int error;
721 
722 	/* Allow nodename to be null. */
723 	hints.ai_flags |= AI_PASSIVE;
724 
725 	/*
726 	 * In the case of binding to a wildcard address
727 	 * default to binding to an ipv4 address.
728 	 */
729 	if (host == NULL && hints.ai_family == AF_UNSPEC)
730 		hints.ai_family = AF_INET;
731 
732 	if ((error = getaddrinfo(host, port, &hints, &res)))
733 		errx(1, "getaddrinfo: %s", gai_strerror(error));
734 
735 	res0 = res;
736 	do {
737 		if ((s = socket(res0->ai_family, res0->ai_socktype,
738 		    res0->ai_protocol)) < 0)
739 			continue;
740 
741 		if (rtableid) {
742 			ret = setsockopt(s, SOL_SOCKET, SO_SETFIB, &rtableid,
743 			    sizeof(rtableid));
744 			if (ret == -1)
745 				err(1, "setsockopt(.., SO_SETFIB, %u, ..)",
746 				    rtableid);
747 		}
748 
749 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
750 		if (ret == -1)
751 			err(1, NULL);
752 #ifdef IPSEC
753 		if (ipsec_policy[0] != NULL)
754 			add_ipsec_policy(s, ipsec_policy[0]);
755 		if (ipsec_policy[1] != NULL)
756 			add_ipsec_policy(s, ipsec_policy[1]);
757 #endif
758 		if (FreeBSD_Oflag) {
759 			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
760 			    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
761 				err(1, "disable TCP options");
762 		}
763 
764 		if (bind(s, (struct sockaddr *)res0->ai_addr,
765 		    res0->ai_addrlen) == 0)
766 			break;
767 
768 		close(s);
769 		s = -1;
770 	} while ((res0 = res0->ai_next) != NULL);
771 
772 	if (!uflag && s != -1) {
773 		if (listen(s, 1) < 0)
774 			err(1, "listen");
775 	}
776 
777 	freeaddrinfo(res);
778 
779 	return (s);
780 }
781 
782 /*
783  * readwrite()
784  * Loop that polls on the network file descriptor and stdin.
785  */
786 void
787 readwrite(int nfd)
788 {
789 	struct pollfd pfd[2];
790 	unsigned char buf[16384];
791 	int n, wfd = fileno(stdin);
792 	int lfd = fileno(stdout);
793 	int plen;
794 
795 	plen = 2048;
796 
797 	/* Setup Network FD */
798 	pfd[0].fd = nfd;
799 	pfd[0].events = POLLIN;
800 
801 	/* Set up STDIN FD. */
802 	pfd[1].fd = wfd;
803 	pfd[1].events = POLLIN;
804 
805 	while (pfd[0].fd != -1) {
806 		if (iflag)
807 			sleep(iflag);
808 
809 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
810 			close(nfd);
811 			err(1, "Polling Error");
812 		}
813 
814 		if (n == 0)
815 			return;
816 
817 		if (pfd[0].revents & POLLIN) {
818 			if ((n = read(nfd, buf, plen)) < 0)
819 				return;
820 			else if (n == 0) {
821 				shutdown(nfd, SHUT_RD);
822 				pfd[0].fd = -1;
823 				pfd[0].events = 0;
824 			} else {
825 				if (tflag)
826 					atelnet(nfd, buf, n);
827 				if (atomicio(vwrite, lfd, buf, n) != n)
828 					return;
829 			}
830 		}
831 
832 		if (!dflag && pfd[1].revents & POLLIN) {
833 			if ((n = read(wfd, buf, plen)) < 0)
834 				return;
835 			else if (n == 0) {
836 				shutdown(nfd, SHUT_WR);
837 				pfd[1].fd = -1;
838 				pfd[1].events = 0;
839 			} else {
840 				if (atomicio(vwrite, nfd, buf, n) != n)
841 					return;
842 			}
843 		}
844 	}
845 }
846 
847 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
848 void
849 atelnet(int nfd, unsigned char *buf, unsigned int size)
850 {
851 	unsigned char *p, *end;
852 	unsigned char obuf[4];
853 
854 	if (size < 3)
855 		return;
856 	end = buf + size - 2;
857 
858 	for (p = buf; p < end; p++) {
859 		if (*p != IAC)
860 			continue;
861 
862 		obuf[0] = IAC;
863 		p++;
864 		if ((*p == WILL) || (*p == WONT))
865 			obuf[1] = DONT;
866 		else if ((*p == DO) || (*p == DONT))
867 			obuf[1] = WONT;
868 		else
869 			continue;
870 
871 		p++;
872 		obuf[2] = *p;
873 		if (atomicio(vwrite, nfd, obuf, 3) != 3)
874 			warn("Write Error!");
875 	}
876 }
877 
878 /*
879  * build_ports()
880  * Build an array of ports in portlist[], listing each port
881  * that we should try to connect to.
882  */
883 void
884 build_ports(char *p)
885 {
886 	const char *errstr;
887 	char *n;
888 	int hi, lo, cp;
889 	int x = 0;
890 
891 	if ((n = strchr(p, '-')) != NULL) {
892 		*n = '\0';
893 		n++;
894 
895 		/* Make sure the ports are in order: lowest->highest. */
896 		hi = strtonum(n, 1, PORT_MAX, &errstr);
897 		if (errstr)
898 			errx(1, "port number %s: %s", errstr, n);
899 		lo = strtonum(p, 1, PORT_MAX, &errstr);
900 		if (errstr)
901 			errx(1, "port number %s: %s", errstr, p);
902 
903 		if (lo > hi) {
904 			cp = hi;
905 			hi = lo;
906 			lo = cp;
907 		}
908 
909 		/* Load ports sequentially. */
910 		for (cp = lo; cp <= hi; cp++) {
911 			portlist[x] = calloc(1, PORT_MAX_LEN);
912 			if (portlist[x] == NULL)
913 				err(1, NULL);
914 			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
915 			x++;
916 		}
917 
918 		/* Randomly swap ports. */
919 		if (rflag) {
920 			int y;
921 			char *c;
922 
923 			for (x = 0; x <= (hi - lo); x++) {
924 				y = (arc4random() & 0xFFFF) % (hi - lo);
925 				c = portlist[x];
926 				portlist[x] = portlist[y];
927 				portlist[y] = c;
928 			}
929 		}
930 	} else {
931 		hi = strtonum(p, 1, PORT_MAX, &errstr);
932 		if (errstr)
933 			errx(1, "port number %s: %s", errstr, p);
934 		portlist[0] = strdup(p);
935 		if (portlist[0] == NULL)
936 			err(1, NULL);
937 	}
938 }
939 
940 /*
941  * udptest()
942  * Do a few writes to see if the UDP port is there.
943  * Fails once PF state table is full.
944  */
945 int
946 udptest(int s)
947 {
948 	int i, ret;
949 
950 	for (i = 0; i <= 3; i++) {
951 		if (write(s, "X", 1) == 1)
952 			ret = 1;
953 		else
954 			ret = -1;
955 	}
956 	return (ret);
957 }
958 
959 void
960 set_common_sockopts(int s)
961 {
962 	int x = 1;
963 
964 	if (Sflag) {
965 		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
966 			&x, sizeof(x)) == -1)
967 			err(1, NULL);
968 	}
969 	if (Dflag) {
970 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
971 			&x, sizeof(x)) == -1)
972 			err(1, NULL);
973 	}
974 	if (Tflag != -1) {
975 		if (setsockopt(s, IPPROTO_IP, IP_TOS,
976 		    &Tflag, sizeof(Tflag)) == -1)
977 			err(1, "set IP ToS");
978 	}
979 	if (Iflag) {
980 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
981 		    &Iflag, sizeof(Iflag)) == -1)
982 			err(1, "set TCP receive buffer size");
983 	}
984 	if (Oflag) {
985 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
986 		    &Oflag, sizeof(Oflag)) == -1)
987 			err(1, "set TCP send buffer size");
988 	}
989 	if (FreeBSD_Oflag) {
990 		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
991 		    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
992 			err(1, "disable TCP options");
993 	}
994 }
995 
996 int
997 map_tos(char *s, int *val)
998 {
999 	/* DiffServ Codepoints and other TOS mappings */
1000 	const struct toskeywords {
1001 		const char	*keyword;
1002 		int		 val;
1003 	} *t, toskeywords[] = {
1004 		{ "af11",		IPTOS_DSCP_AF11 },
1005 		{ "af12",		IPTOS_DSCP_AF12 },
1006 		{ "af13",		IPTOS_DSCP_AF13 },
1007 		{ "af21",		IPTOS_DSCP_AF21 },
1008 		{ "af22",		IPTOS_DSCP_AF22 },
1009 		{ "af23",		IPTOS_DSCP_AF23 },
1010 		{ "af31",		IPTOS_DSCP_AF31 },
1011 		{ "af32",		IPTOS_DSCP_AF32 },
1012 		{ "af33",		IPTOS_DSCP_AF33 },
1013 		{ "af41",		IPTOS_DSCP_AF41 },
1014 		{ "af42",		IPTOS_DSCP_AF42 },
1015 		{ "af43",		IPTOS_DSCP_AF43 },
1016 		{ "critical",		IPTOS_PREC_CRITIC_ECP },
1017 		{ "cs0",		IPTOS_DSCP_CS0 },
1018 		{ "cs1",		IPTOS_DSCP_CS1 },
1019 		{ "cs2",		IPTOS_DSCP_CS2 },
1020 		{ "cs3",		IPTOS_DSCP_CS3 },
1021 		{ "cs4",		IPTOS_DSCP_CS4 },
1022 		{ "cs5",		IPTOS_DSCP_CS5 },
1023 		{ "cs6",		IPTOS_DSCP_CS6 },
1024 		{ "cs7",		IPTOS_DSCP_CS7 },
1025 		{ "ef",			IPTOS_DSCP_EF },
1026 		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
1027 		{ "lowdelay",		IPTOS_LOWDELAY },
1028 		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
1029 		{ "reliability",	IPTOS_RELIABILITY },
1030 		{ "throughput",		IPTOS_THROUGHPUT },
1031 		{ NULL, 		-1 },
1032 	};
1033 
1034 	for (t = toskeywords; t->keyword != NULL; t++) {
1035 		if (strcmp(s, t->keyword) == 0) {
1036 			*val = t->val;
1037 			return (1);
1038 		}
1039 	}
1040 
1041 	return (0);
1042 }
1043 
1044 void
1045 report_connect(const struct sockaddr *sa, socklen_t salen)
1046 {
1047 	char remote_host[NI_MAXHOST];
1048 	char remote_port[NI_MAXSERV];
1049 	int herr;
1050 	int flags = NI_NUMERICSERV;
1051 
1052 	if (nflag)
1053 		flags |= NI_NUMERICHOST;
1054 
1055 	if ((herr = getnameinfo(sa, salen,
1056 	    remote_host, sizeof(remote_host),
1057 	    remote_port, sizeof(remote_port),
1058 	    flags)) != 0) {
1059 		if (herr == EAI_SYSTEM)
1060 			err(1, "getnameinfo");
1061 		else
1062 			errx(1, "getnameinfo: %s", gai_strerror(herr));
1063 	}
1064 
1065 	fprintf(stderr,
1066 	    "Connection from %s %s "
1067 	    "received!\n", remote_host, remote_port);
1068 }
1069 
1070 void
1071 help(void)
1072 {
1073 	usage(0);
1074 	fprintf(stderr, "\tCommand Summary:\n\
1075 	\t-4		Use IPv4\n\
1076 	\t-6		Use IPv6\n\
1077 	\t-D		Enable the debug socket option\n\
1078 	\t-d		Detach from stdin\n");
1079 #ifdef IPSEC
1080 	fprintf(stderr, "\
1081 	\t-E		Use IPsec ESP\n\
1082 	\t-e policy	Use specified IPsec policy\n");
1083 #endif
1084 	fprintf(stderr, "\
1085 	\t-h		This help text\n\
1086 	\t-I length	TCP receive buffer length\n\
1087 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
1088 	\t-k		Keep inbound sockets open for multiple connects\n\
1089 	\t-l		Listen mode, for inbound connects\n\
1090 	\t-n		Suppress name/port resolutions\n\
1091 	\t--no-tcpopt	Disable TCP options\n\
1092 	\t-O length	TCP send buffer length\n\
1093 	\t-P proxyuser\tUsername for proxy authentication\n\
1094 	\t-p port\t	Specify local port for remote connects\n\
1095 	\t-r		Randomize remote ports\n\
1096 	\t-S		Enable the TCP MD5 signature option\n\
1097 	\t-s addr\t	Local source address\n\
1098 	\t-T toskeyword\tSet IP Type of Service\n\
1099 	\t-t		Answer TELNET negotiation\n\
1100 	\t-U		Use UNIX domain socket\n\
1101 	\t-u		UDP mode\n\
1102 	\t-V rtable	Specify alternate routing table\n\
1103 	\t-v		Verbose\n\
1104 	\t-w secs\t	Timeout for connects and final net reads\n\
1105 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1106 	\t-x addr[:port]\tSpecify proxy address and port\n\
1107 	\t-z		Zero-I/O mode [used for scanning]\n\
1108 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1109 #ifdef IPSEC
1110 	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
1111 #endif
1112 	exit(1);
1113 }
1114 
1115 #ifdef IPSEC
1116 void
1117 add_ipsec_policy(int s, char *policy)
1118 {
1119 	char *raw;
1120 	int e;
1121 
1122 	raw = ipsec_set_policy(policy, strlen(policy));
1123 	if (raw == NULL)
1124 		errx(1, "ipsec_set_policy `%s': %s", policy,
1125 		     ipsec_strerror());
1126 	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
1127 			ipsec_get_policylen(raw));
1128 	if (e < 0)
1129 		err(1, "ipsec policy cannot be configured");
1130 	free(raw);
1131 	if (vflag)
1132 		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
1133 	return;
1134 }
1135 #endif /* IPSEC */
1136 
1137 void
1138 usage(int ret)
1139 {
1140 	fprintf(stderr,
1141 #ifdef IPSEC
1142 	    "usage: nc [-46DdEhklnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
1143 #else
1144 	    "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
1145 #endif
1146 	    "\t  [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1147 	    "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1148 	    "\t  [-x proxy_address[:port]] [destination] [port]\n");
1149 	if (ret)
1150 		exit(1);
1151 }
1152