xref: /freebsd/contrib/netcat/netcat.c (revision 70ed590b393173d4ea697be2a27054ed171f0c1a)
1 /* $OpenBSD: netcat.c,v 1.95 2010/02/27 00:58:56 nicm 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 
74 /* Command Line Options */
75 int	Eflag;					/* Use IPsec ESP */
76 int	dflag;					/* detached, no stdin */
77 unsigned int iflag;				/* Interval Flag */
78 int	jflag;					/* use jumbo frames if we can */
79 int	kflag;					/* More than one connect */
80 int	lflag;					/* Bind to local port */
81 int	nflag;					/* Don't do name look up */
82 int	oflag;					/* Once only: stop on EOF */
83 int	FreeBSD_Oflag;				/* Do not use TCP options */
84 char   *Pflag;					/* Proxy username */
85 char   *pflag;					/* Localport flag */
86 int	rflag;					/* Random ports flag */
87 char   *sflag;					/* Source Address */
88 int	tflag;					/* Telnet Emulation */
89 int	uflag;					/* UDP - Default to TCP */
90 int	vflag;					/* Verbosity */
91 int	xflag;					/* Socks proxy */
92 int	zflag;					/* Port Scan Flag */
93 int	Dflag;					/* sodebug */
94 int	Iflag;					/* TCP receive buffer size */
95 int	Oflag;					/* TCP send buffer size */
96 int	Sflag;					/* TCP MD5 signature option */
97 int	Tflag = -1;				/* IP Type of Service */
98 u_int	rdomain;
99 
100 int timeout = -1;
101 int family = AF_UNSPEC;
102 char *portlist[PORT_MAX+1];
103 
104 void	atelnet(int, unsigned char *, unsigned int);
105 void	build_ports(char *);
106 void	help(void);
107 int	local_listen(char *, char *, struct addrinfo);
108 void	readwrite(int);
109 int	remote_connect(const char *, const char *, struct addrinfo);
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_connect(char *);
114 int	unix_listen(char *);
115 void	set_common_sockopts(int);
116 int	parse_iptos(char *);
117 void	usage(int);
118 
119 #ifdef IPSEC
120 void	add_ipsec_policy(int, char *);
121 
122 char	*ipsec_policy[2];
123 #endif
124 
125 int
126 main(int argc, char *argv[])
127 {
128 	int ch, s, ret, socksv, ipsec_count;
129 	int numfibs;
130 	size_t intsize = sizeof(int);
131 	char *host, *uport;
132 	struct addrinfo hints;
133 	struct servent *sv;
134 	socklen_t len;
135 	struct sockaddr_storage cliaddr;
136 	char *proxy;
137 	const char *errstr, *proxyhost = "", *proxyport = NULL;
138 	struct addrinfo proxyhints;
139 	struct option longopts[] = {
140 		{ "no-tcpopt",	no_argument,	&FreeBSD_Oflag,	1 },
141 		{ NULL,		0,		NULL,		0 }
142 	};
143 
144 	rdomain = 0;
145 	ret = 1;
146 	ipsec_count = 0;
147 	s = 0;
148 	socksv = 5;
149 	host = NULL;
150 	uport = NULL;
151 	sv = NULL;
152 
153 	while ((ch = getopt_long(argc, argv,
154 	    "46DdEe:hI:i:jklnO:oP:p:rSs:tT:UuV:vw:X:x:z",
155 	    longopts, NULL)) != -1) {
156 		switch (ch) {
157 		case '4':
158 			family = AF_INET;
159 			break;
160 		case '6':
161 			family = AF_INET6;
162 			break;
163 		case 'U':
164 			family = AF_UNIX;
165 			break;
166 		case 'X':
167 			if (strcasecmp(optarg, "connect") == 0)
168 				socksv = -1; /* HTTP proxy CONNECT */
169 			else if (strcmp(optarg, "4") == 0)
170 				socksv = 4; /* SOCKS v.4 */
171 			else if (strcmp(optarg, "5") == 0)
172 				socksv = 5; /* SOCKS v.5 */
173 			else
174 				errx(1, "unsupported proxy protocol");
175 			break;
176 		case 'd':
177 			dflag = 1;
178 			break;
179 		case 'e':
180 #ifdef IPSEC
181 			ipsec_policy[ipsec_count++ % 2] = optarg;
182 #else
183 			errx(1, "IPsec support unavailable.");
184 #endif
185 			break;
186 		case 'E':
187 #ifdef IPSEC
188 			ipsec_policy[0] = "in  ipsec esp/transport//require";
189 			ipsec_policy[1] = "out ipsec esp/transport//require";
190 #else
191 			errx(1, "IPsec support unavailable.");
192 #endif
193 			break;
194 		case 'h':
195 			help();
196 			break;
197 		case 'i':
198 			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
199 			if (errstr)
200 				errx(1, "interval %s: %s", errstr, optarg);
201 			break;
202 #ifdef SO_JUMBO
203 		case 'j':
204 			jflag = 1;
205 			break;
206 #endif
207 		case 'k':
208 			kflag = 1;
209 			break;
210 		case 'l':
211 			lflag = 1;
212 			break;
213 		case 'n':
214 			nflag = 1;
215 			break;
216 		case 'o':
217 			oflag = 1;
218 			break;
219 		case 'P':
220 			Pflag = optarg;
221 			break;
222 		case 'p':
223 			pflag = optarg;
224 			break;
225 		case 'r':
226 			rflag = 1;
227 			break;
228 		case 's':
229 			sflag = optarg;
230 			break;
231 		case 't':
232 			tflag = 1;
233 			break;
234 		case 'u':
235 			uflag = 1;
236 			break;
237 		case 'V':
238 			if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
239 				errx(1, "Multiple FIBS not supported");
240 			rdomain = (unsigned int)strtonum(optarg, 0,
241 			    numfibs - 1, &errstr);
242 			if (errstr)
243 				errx(1, "FIB %s: %s", errstr, optarg);
244 			break;
245 		case 'v':
246 			vflag = 1;
247 			break;
248 		case 'w':
249 			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
250 			if (errstr)
251 				errx(1, "timeout %s: %s", errstr, optarg);
252 			timeout *= 1000;
253 			break;
254 		case 'x':
255 			xflag = 1;
256 			if ((proxy = strdup(optarg)) == NULL)
257 				err(1, NULL);
258 			break;
259 		case 'z':
260 			zflag = 1;
261 			break;
262 		case 'D':
263 			Dflag = 1;
264 			break;
265 		case 'I':
266 			Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
267 			if (errstr != NULL)
268 				errx(1, "TCP receive window %s: %s",
269 				    errstr, optarg);
270 			break;
271 		case 'O':
272 			Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
273 			if (errstr != NULL) {
274 			    if (strcmp(errstr, "invalid") != 0)
275 				errx(1, "TCP send window %s: %s",
276 				    errstr, optarg);
277 			}
278 			break;
279 		case 'S':
280 			Sflag = 1;
281 			break;
282 		case 'T':
283 			Tflag = parse_iptos(optarg);
284 			break;
285 		case 0:
286 			break;
287 		default:
288 			usage(1);
289 		}
290 	}
291 	argc -= optind;
292 	argv += optind;
293 
294 	/* Cruft to make sure options are clean, and used properly. */
295 	if (argv[0] && !argv[1] && family == AF_UNIX) {
296 		if (uflag)
297 			errx(1, "cannot use -u and -U");
298 		host = argv[0];
299 		uport = NULL;
300 	} else if (argv[0] && !argv[1]) {
301 		if  (!lflag)
302 			usage(1);
303 		uport = argv[0];
304 		host = NULL;
305 	} else if (argv[0] && argv[1]) {
306 		host = argv[0];
307 		uport = argv[1];
308 	} else
309 		usage(1);
310 
311 	if (lflag && sflag)
312 		errx(1, "cannot use -s and -l");
313 	if (lflag && pflag)
314 		errx(1, "cannot use -p and -l");
315 	if (lflag && zflag)
316 		errx(1, "cannot use -z and -l");
317 	if (!lflag && kflag)
318 		errx(1, "must use -l with -k");
319 
320 	/* Initialize addrinfo structure. */
321 	if (family != AF_UNIX) {
322 		memset(&hints, 0, sizeof(struct addrinfo));
323 		hints.ai_family = family;
324 		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
325 		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
326 		if (nflag)
327 			hints.ai_flags |= AI_NUMERICHOST;
328 	}
329 
330 	if (xflag) {
331 		if (uflag)
332 			errx(1, "no proxy support for UDP mode");
333 
334 		if (lflag)
335 			errx(1, "no proxy support for listen");
336 
337 		if (family == AF_UNIX)
338 			errx(1, "no proxy support for unix sockets");
339 
340 		/* XXX IPv6 transport to proxy would probably work */
341 		if (family == AF_INET6)
342 			errx(1, "no proxy support for IPv6");
343 
344 		if (sflag)
345 			errx(1, "no proxy support for local source address");
346 
347 		proxyhost = strsep(&proxy, ":");
348 		proxyport = proxy;
349 
350 		memset(&proxyhints, 0, sizeof(struct addrinfo));
351 		proxyhints.ai_family = family;
352 		proxyhints.ai_socktype = SOCK_STREAM;
353 		proxyhints.ai_protocol = IPPROTO_TCP;
354 		if (nflag)
355 			proxyhints.ai_flags |= AI_NUMERICHOST;
356 	}
357 
358 	if (lflag) {
359 		int connfd;
360 		ret = 0;
361 
362 		if (family == AF_UNIX)
363 			s = unix_listen(host);
364 
365 		/* Allow only one connection at a time, but stay alive. */
366 		for (;;) {
367 			if (family != AF_UNIX)
368 				s = local_listen(host, uport, hints);
369 			if (s < 0)
370 				err(1, NULL);
371 			/*
372 			 * For UDP, we will use recvfrom() initially
373 			 * to wait for a caller, then use the regular
374 			 * functions to talk to the caller.
375 			 */
376 			if (uflag) {
377 				int rv, plen;
378 				char buf[8192];
379 				struct sockaddr_storage z;
380 
381 				len = sizeof(z);
382 				plen = jflag ? 8192 : 1024;
383 				rv = recvfrom(s, buf, plen, MSG_PEEK,
384 				    (struct sockaddr *)&z, &len);
385 				if (rv < 0)
386 					err(1, "recvfrom");
387 
388 				rv = connect(s, (struct sockaddr *)&z, len);
389 				if (rv < 0)
390 					err(1, "connect");
391 
392 				connfd = s;
393 			} else {
394 				len = sizeof(cliaddr);
395 				connfd = accept(s, (struct sockaddr *)&cliaddr,
396 				    &len);
397 			}
398 
399 			readwrite(connfd);
400 			close(connfd);
401 			if (family != AF_UNIX)
402 				close(s);
403 
404 			if (!kflag)
405 				break;
406 		}
407 	} else if (family == AF_UNIX) {
408 		ret = 0;
409 
410 		if ((s = unix_connect(host)) > 0 && !zflag) {
411 			readwrite(s);
412 			close(s);
413 		} else
414 			ret = 1;
415 
416 		exit(ret);
417 
418 	} else {
419 		int i = 0;
420 
421 		/* Construct the portlist[] array. */
422 		build_ports(uport);
423 
424 		/* Cycle through portlist, connecting to each port. */
425 		for (i = 0; portlist[i] != NULL; i++) {
426 			if (s)
427 				close(s);
428 
429 			if (xflag)
430 				s = socks_connect(host, portlist[i], hints,
431 				    proxyhost, proxyport, proxyhints, socksv,
432 				    Pflag);
433 			else
434 				s = remote_connect(host, portlist[i], hints);
435 
436 			if (s < 0)
437 				continue;
438 
439 			ret = 0;
440 			if (vflag || zflag) {
441 				/* For UDP, make sure we are connected. */
442 				if (uflag) {
443 					if (udptest(s) == -1) {
444 						ret = 1;
445 						continue;
446 					}
447 				}
448 
449 				/* Don't look up port if -n. */
450 				if (nflag)
451 					sv = NULL;
452 				else {
453 					sv = getservbyport(
454 					    ntohs(atoi(portlist[i])),
455 					    uflag ? "udp" : "tcp");
456 				}
457 
458 				fprintf(stderr,
459 				    "Connection to %s %s port [%s/%s] "
460 				    "succeeded!\n", host, portlist[i],
461 				    uflag ? "udp" : "tcp",
462 				    sv ? sv->s_name : "*");
463 			}
464 			if (!zflag)
465 				readwrite(s);
466 		}
467 	}
468 
469 	if (s)
470 		close(s);
471 
472 	exit(ret);
473 }
474 
475 /*
476  * unix_connect()
477  * Returns a socket connected to a local unix socket. Returns -1 on failure.
478  */
479 int
480 unix_connect(char *path)
481 {
482 	struct sockaddr_un sun;
483 	int s;
484 
485 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
486 		return (-1);
487 	(void)fcntl(s, F_SETFD, 1);
488 
489 	memset(&sun, 0, sizeof(struct sockaddr_un));
490 	sun.sun_family = AF_UNIX;
491 
492 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
493 	    sizeof(sun.sun_path)) {
494 		close(s);
495 		errno = ENAMETOOLONG;
496 		return (-1);
497 	}
498 	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
499 		close(s);
500 		return (-1);
501 	}
502 	return (s);
503 
504 }
505 
506 /*
507  * unix_listen()
508  * Create a unix domain socket, and listen on it.
509  */
510 int
511 unix_listen(char *path)
512 {
513 	struct sockaddr_un sun;
514 	int s;
515 
516 	/* Create unix domain socket. */
517 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
518 		return (-1);
519 
520 	memset(&sun, 0, sizeof(struct sockaddr_un));
521 	sun.sun_family = AF_UNIX;
522 
523 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
524 	    sizeof(sun.sun_path)) {
525 		close(s);
526 		errno = ENAMETOOLONG;
527 		return (-1);
528 	}
529 
530 	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
531 		close(s);
532 		return (-1);
533 	}
534 
535 	if (listen(s, 5) < 0) {
536 		close(s);
537 		return (-1);
538 	}
539 	return (s);
540 }
541 
542 /*
543  * remote_connect()
544  * Returns a socket connected to a remote host. Properly binds to a local
545  * port or source address if needed. Returns -1 on failure.
546  */
547 int
548 remote_connect(const char *host, const char *port, struct addrinfo hints)
549 {
550 	struct addrinfo *res, *res0;
551 	int s, error, on = 1;
552 
553 	if ((error = getaddrinfo(host, port, &hints, &res)))
554 		errx(1, "getaddrinfo: %s", gai_strerror(error));
555 
556 	res0 = res;
557 	do {
558 		if ((s = socket(res0->ai_family, res0->ai_socktype,
559 		    res0->ai_protocol)) < 0)
560 			continue;
561 #ifdef IPSEC
562 		if (ipsec_policy[0] != NULL)
563 			add_ipsec_policy(s, ipsec_policy[0]);
564 		if (ipsec_policy[1] != NULL)
565 			add_ipsec_policy(s, ipsec_policy[1]);
566 #endif
567 
568 		if (rdomain) {
569 			if (setfib(rdomain) == -1)
570 				err(1, "setfib");
571 		}
572 
573 		/* Bind to a local port or source address if specified. */
574 		if (sflag || pflag) {
575 			struct addrinfo ahints, *ares;
576 
577 #ifdef SO_BINDANY
578 			/* try SO_BINDANY, but don't insist */
579 			setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
580 #endif
581 			memset(&ahints, 0, sizeof(struct addrinfo));
582 			ahints.ai_family = res0->ai_family;
583 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
584 			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
585 			ahints.ai_flags = AI_PASSIVE;
586 			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
587 				errx(1, "getaddrinfo: %s", gai_strerror(error));
588 
589 			if (bind(s, (struct sockaddr *)ares->ai_addr,
590 			    ares->ai_addrlen) < 0)
591 				errx(1, "bind failed: %s", strerror(errno));
592 			freeaddrinfo(ares);
593 		}
594 
595 		set_common_sockopts(s);
596 
597 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
598 			break;
599 		else if (vflag)
600 			warn("connect to %s port %s (%s) failed", host, port,
601 			    uflag ? "udp" : "tcp");
602 
603 		close(s);
604 		s = -1;
605 	} while ((res0 = res0->ai_next) != NULL);
606 
607 	freeaddrinfo(res);
608 
609 	return (s);
610 }
611 
612 /*
613  * local_listen()
614  * Returns a socket listening on a local port, binds to specified source
615  * address. Returns -1 on failure.
616  */
617 int
618 local_listen(char *host, char *port, struct addrinfo hints)
619 {
620 	struct addrinfo *res, *res0;
621 	int s, ret, x = 1;
622 	int error;
623 
624 	/* Allow nodename to be null. */
625 	hints.ai_flags |= AI_PASSIVE;
626 
627 	/*
628 	 * In the case of binding to a wildcard address
629 	 * default to binding to an ipv4 address.
630 	 */
631 	if (host == NULL && hints.ai_family == AF_UNSPEC)
632 		hints.ai_family = AF_INET;
633 
634 	if ((error = getaddrinfo(host, port, &hints, &res)))
635 		errx(1, "getaddrinfo: %s", gai_strerror(error));
636 
637 	res0 = res;
638 	do {
639 		if ((s = socket(res0->ai_family, res0->ai_socktype,
640 		    res0->ai_protocol)) < 0)
641 			continue;
642 
643 		if (rdomain) {
644 			if (setfib(rdomain) == -1)
645 				err(1, "setfib");
646 		}
647 
648 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
649 		if (ret == -1)
650 			err(1, NULL);
651 #ifdef IPSEC
652 		if (ipsec_policy[0] != NULL)
653 			add_ipsec_policy(s, ipsec_policy[0]);
654 		if (ipsec_policy[1] != NULL)
655 			add_ipsec_policy(s, ipsec_policy[1]);
656 #endif
657 		if (FreeBSD_Oflag) {
658 			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
659 			    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
660 				err(1, "disable TCP options");
661 		}
662 
663 		if (bind(s, (struct sockaddr *)res0->ai_addr,
664 		    res0->ai_addrlen) == 0)
665 			break;
666 
667 		close(s);
668 		s = -1;
669 	} while ((res0 = res0->ai_next) != NULL);
670 
671 	if (!uflag && s != -1) {
672 		if (listen(s, 1) < 0)
673 			err(1, "listen");
674 	}
675 
676 	freeaddrinfo(res);
677 
678 	return (s);
679 }
680 
681 /*
682  * readwrite()
683  * Loop that polls on the network file descriptor and stdin.
684  */
685 void
686 readwrite(int nfd)
687 {
688 	struct pollfd pfd[2];
689 	unsigned char buf[8192];
690 	int n, wfd = fileno(stdin);
691 	int lfd = fileno(stdout);
692 	int plen;
693 
694 	plen = jflag ? 8192 : 1024;
695 
696 	/* Setup Network FD */
697 	pfd[0].fd = nfd;
698 	pfd[0].events = POLLIN;
699 
700 	/* Set up STDIN FD. */
701 	pfd[1].fd = wfd;
702 	pfd[1].events = POLLIN;
703 
704 	while (pfd[0].fd != -1) {
705 		if (iflag)
706 			sleep(iflag);
707 
708 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
709 			close(nfd);
710 			err(1, "Polling Error");
711 		}
712 
713 		if (n == 0)
714 			return;
715 
716 		if (pfd[0].revents & POLLIN) {
717 			if ((n = read(nfd, buf, plen)) < 0)
718 				return;
719 			else if (n == 0) {
720 				shutdown(nfd, SHUT_RD);
721 				pfd[0].fd = -1;
722 				pfd[0].events = 0;
723 			} else {
724 				if (tflag)
725 					atelnet(nfd, buf, n);
726 				if (atomicio(vwrite, lfd, buf, n) != n)
727 					return;
728 			}
729 		}
730 
731 		if (!dflag && pfd[1].revents & POLLIN) {
732 			if ((n = read(wfd, buf, plen)) < 0 ||
733 			    (oflag && n == 0)) {
734 				return;
735 			} else if (n == 0) {
736 				shutdown(nfd, SHUT_WR);
737 				pfd[1].fd = -1;
738 				pfd[1].events = 0;
739 			} else {
740 				if (atomicio(vwrite, nfd, buf, n) != n)
741 					return;
742 			}
743 		}
744 	}
745 }
746 
747 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
748 void
749 atelnet(int nfd, unsigned char *buf, unsigned int size)
750 {
751 	unsigned char *p, *end;
752 	unsigned char obuf[4];
753 
754 	if (size < 3)
755 		return;
756 	end = buf + size - 2;
757 
758 	for (p = buf; p < end; p++) {
759 		if (*p != IAC)
760 			continue;
761 
762 		obuf[0] = IAC;
763 		p++;
764 		if ((*p == WILL) || (*p == WONT))
765 			obuf[1] = DONT;
766 		else if ((*p == DO) || (*p == DONT))
767 			obuf[1] = WONT;
768 		else
769 			continue;
770 
771 		p++;
772 		obuf[2] = *p;
773 		if (atomicio(vwrite, nfd, obuf, 3) != 3)
774 			warn("Write Error!");
775 	}
776 }
777 
778 /*
779  * build_ports()
780  * Build an array or ports in portlist[], listing each port
781  * that we should try to connect to.
782  */
783 void
784 build_ports(char *p)
785 {
786 	const char *errstr;
787 	char *n;
788 	int hi, lo, cp;
789 	int x = 0;
790 
791 	if ((n = strchr(p, '-')) != NULL) {
792 		if (lflag)
793 			errx(1, "Cannot use -l with multiple ports!");
794 
795 		*n = '\0';
796 		n++;
797 
798 		/* Make sure the ports are in order: lowest->highest. */
799 		hi = strtonum(n, 1, PORT_MAX, &errstr);
800 		if (errstr)
801 			errx(1, "port number %s: %s", errstr, n);
802 		lo = strtonum(p, 1, PORT_MAX, &errstr);
803 		if (errstr)
804 			errx(1, "port number %s: %s", errstr, p);
805 
806 		if (lo > hi) {
807 			cp = hi;
808 			hi = lo;
809 			lo = cp;
810 		}
811 
812 		/* Load ports sequentially. */
813 		for (cp = lo; cp <= hi; cp++) {
814 			portlist[x] = calloc(1, PORT_MAX_LEN);
815 			if (portlist[x] == NULL)
816 				err(1, NULL);
817 			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
818 			x++;
819 		}
820 
821 		/* Randomly swap ports. */
822 		if (rflag) {
823 			int y;
824 			char *c;
825 
826 			for (x = 0; x <= (hi - lo); x++) {
827 				y = (arc4random() & 0xFFFF) % (hi - lo);
828 				c = portlist[x];
829 				portlist[x] = portlist[y];
830 				portlist[y] = c;
831 			}
832 		}
833 	} else {
834 		hi = strtonum(p, 1, PORT_MAX, &errstr);
835 		if (errstr)
836 			errx(1, "port number %s: %s", errstr, p);
837 		portlist[0] = calloc(1, PORT_MAX_LEN);
838 		if (portlist[0] == NULL)
839 			err(1, NULL);
840 		portlist[0] = p;
841 	}
842 }
843 
844 /*
845  * udptest()
846  * Do a few writes to see if the UDP port is there.
847  * XXX - Better way of doing this? Doesn't work for IPv6.
848  * Also fails after around 100 ports checked.
849  */
850 int
851 udptest(int s)
852 {
853 	int i, ret;
854 
855 	for (i = 0; i <= 3; i++) {
856 		if (write(s, "X", 1) == 1)
857 			ret = 1;
858 		else
859 			ret = -1;
860 	}
861 	return (ret);
862 }
863 
864 void
865 set_common_sockopts(int s)
866 {
867 	int x = 1;
868 
869 	if (Sflag) {
870 		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
871 			&x, sizeof(x)) == -1)
872 			err(1, NULL);
873 	}
874 	if (Dflag) {
875 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
876 			&x, sizeof(x)) == -1)
877 			err(1, NULL);
878 	}
879 #ifdef SO_JUMBO
880 	if (jflag) {
881 		if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
882 			&x, sizeof(x)) == -1)
883 			err(1, NULL);
884 	}
885 #endif
886 	if (Tflag != -1) {
887 		if (setsockopt(s, IPPROTO_IP, IP_TOS,
888 		    &Tflag, sizeof(Tflag)) == -1)
889 			err(1, "set IP ToS");
890 	}
891 	if (Iflag) {
892 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
893 		    &Iflag, sizeof(Iflag)) == -1)
894 			err(1, "set TCP receive buffer size");
895 	}
896 	if (Oflag) {
897 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
898 		    &Oflag, sizeof(Oflag)) == -1)
899 			err(1, "set TCP send buffer size");
900 	}
901 	if (FreeBSD_Oflag) {
902 		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
903 		    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
904 			err(1, "disable TCP options");
905 	}
906 }
907 
908 int
909 parse_iptos(char *s)
910 {
911 	int tos = -1;
912 
913 	if (strcmp(s, "lowdelay") == 0)
914 		return (IPTOS_LOWDELAY);
915 	if (strcmp(s, "throughput") == 0)
916 		return (IPTOS_THROUGHPUT);
917 	if (strcmp(s, "reliability") == 0)
918 		return (IPTOS_RELIABILITY);
919 
920 	if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
921 		errx(1, "invalid IP Type of Service");
922 	return (tos);
923 }
924 
925 void
926 help(void)
927 {
928 	usage(0);
929 	fprintf(stderr, "\tCommand Summary:\n\
930 	\t-4		Use IPv4\n\
931 	\t-6		Use IPv6\n\
932 	\t-D		Enable the debug socket option\n\
933 	\t-d		Detach from stdin\n");
934 #ifdef IPSEC
935 	fprintf(stderr, "\
936 	\t-E		Use IPsec ESP\n\
937 	\t-e policy	Use specified IPsec policy\n");
938 #endif
939 	fprintf(stderr, "\
940 	\t-h		This help text\n\
941 	\t-I length	TCP receive buffer length\n\
942 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
943 	\t-k		Keep inbound sockets open for multiple connects\n\
944 	\t-l		Listen mode, for inbound connects\n\
945 	\t-n		Suppress name/port resolutions\n\
946 	\t--no-tcpopt	Disable TCP options\n\
947 	\t-O length	TCP send buffer length\n\
948 	\t-o		Terminate on EOF on input\n\
949 	\t-P proxyuser\tUsername for proxy authentication\n\
950 	\t-p port\t	Specify local port for remote connects\n\
951 	\t-r		Randomize remote ports\n\
952 	\t-S		Enable the TCP MD5 signature option\n\
953 	\t-s addr\t	Local source address\n\
954 	\t-T ToS\t	Set IP Type of Service\n\
955 	\t-t		Answer TELNET negotiation\n\
956 	\t-U		Use UNIX domain socket\n\
957 	\t-u		UDP mode\n\
958 	\t-V fib	Specify alternate routing table (FIB)\n\
959 	\t-v		Verbose\n\
960 	\t-w secs\t	Timeout for connects and final net reads\n\
961 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
962 	\t-x addr[:port]\tSpecify proxy address and port\n\
963 	\t-z		Zero-I/O mode [used for scanning]\n\
964 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
965 #ifdef IPSEC
966 	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
967 #endif
968 	exit(1);
969 }
970 
971 #ifdef IPSEC
972 void
973 add_ipsec_policy(int s, char *policy)
974 {
975 	char *raw;
976 	int e;
977 
978 	raw = ipsec_set_policy(policy, strlen(policy));
979 	if (raw == NULL)
980 		errx(1, "ipsec_set_policy `%s': %s", policy,
981 		     ipsec_strerror());
982 	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
983 			ipsec_get_policylen(raw));
984 	if (e < 0)
985 		err(1, "ipsec policy cannot be configured");
986 	free(raw);
987 	if (vflag)
988 		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
989 	return;
990 }
991 #endif /* IPSEC */
992 
993 void
994 usage(int ret)
995 {
996 	fprintf(stderr,
997 #ifdef IPSEC
998 	    "usage: nc [-46DdEhklnorStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
999 #else
1000 	    "usage: nc [-46DdhklnorStUuvz] [-I length] [-i interval] [-O length]\n"
1001 #endif
1002 	    "\t  [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n"
1003 	    "\t  [-V fib] [-w timeout] [-X proxy_protocol]\n"
1004 	    "\t  [-x proxy_address[:port]] [hostname] [port]\n");
1005 	if (ret)
1006 		exit(1);
1007 }
1008