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