xref: /freebsd/contrib/netcat/netcat.c (revision 4ed925457ab06e83238a5db33e89ccc94b99a713)
1 /* $OpenBSD: netcat.c,v 1.93 2009/06/05 00:18:10 claudio 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 				printf("Connection to %s %s port [%s/%s] succeeded!\n",
459 				    host, portlist[i], uflag ? "udp" : "tcp",
460 				    sv ? sv->s_name : "*");
461 			}
462 			if (!zflag)
463 				readwrite(s);
464 		}
465 	}
466 
467 	if (s)
468 		close(s);
469 
470 	exit(ret);
471 }
472 
473 /*
474  * unix_connect()
475  * Returns a socket connected to a local unix socket. Returns -1 on failure.
476  */
477 int
478 unix_connect(char *path)
479 {
480 	struct sockaddr_un sun;
481 	int s;
482 
483 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
484 		return (-1);
485 	(void)fcntl(s, F_SETFD, 1);
486 
487 	memset(&sun, 0, sizeof(struct sockaddr_un));
488 	sun.sun_family = AF_UNIX;
489 
490 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
491 	    sizeof(sun.sun_path)) {
492 		close(s);
493 		errno = ENAMETOOLONG;
494 		return (-1);
495 	}
496 	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
497 		close(s);
498 		return (-1);
499 	}
500 	return (s);
501 
502 }
503 
504 /*
505  * unix_listen()
506  * Create a unix domain socket, and listen on it.
507  */
508 int
509 unix_listen(char *path)
510 {
511 	struct sockaddr_un sun;
512 	int s;
513 
514 	/* Create unix domain socket. */
515 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
516 		return (-1);
517 
518 	memset(&sun, 0, sizeof(struct sockaddr_un));
519 	sun.sun_family = AF_UNIX;
520 
521 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
522 	    sizeof(sun.sun_path)) {
523 		close(s);
524 		errno = ENAMETOOLONG;
525 		return (-1);
526 	}
527 
528 	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
529 		close(s);
530 		return (-1);
531 	}
532 
533 	if (listen(s, 5) < 0) {
534 		close(s);
535 		return (-1);
536 	}
537 	return (s);
538 }
539 
540 /*
541  * remote_connect()
542  * Returns a socket connected to a remote host. Properly binds to a local
543  * port or source address if needed. Returns -1 on failure.
544  */
545 int
546 remote_connect(const char *host, const char *port, struct addrinfo hints)
547 {
548 	struct addrinfo *res, *res0;
549 	int s, error, on = 1;
550 
551 	if ((error = getaddrinfo(host, port, &hints, &res)))
552 		errx(1, "getaddrinfo: %s", gai_strerror(error));
553 
554 	res0 = res;
555 	do {
556 		if ((s = socket(res0->ai_family, res0->ai_socktype,
557 		    res0->ai_protocol)) < 0)
558 			continue;
559 #ifdef IPSEC
560 		if (ipsec_policy[0] != NULL)
561 			add_ipsec_policy(s, ipsec_policy[0]);
562 		if (ipsec_policy[1] != NULL)
563 			add_ipsec_policy(s, ipsec_policy[1]);
564 #endif
565 
566 		if (rdomain) {
567 			if (setfib(rdomain) == -1)
568 				err(1, "setfib");
569 		}
570 
571 		/* Bind to a local port or source address if specified. */
572 		if (sflag || pflag) {
573 			struct addrinfo ahints, *ares;
574 
575 #ifdef SO_BINDANY
576 			/* try SO_BINDANY, but don't insist */
577 			setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
578 #endif
579 			memset(&ahints, 0, sizeof(struct addrinfo));
580 			ahints.ai_family = res0->ai_family;
581 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
582 			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
583 			ahints.ai_flags = AI_PASSIVE;
584 			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
585 				errx(1, "getaddrinfo: %s", gai_strerror(error));
586 
587 			if (bind(s, (struct sockaddr *)ares->ai_addr,
588 			    ares->ai_addrlen) < 0)
589 				errx(1, "bind failed: %s", strerror(errno));
590 			freeaddrinfo(ares);
591 		}
592 
593 		set_common_sockopts(s);
594 
595 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
596 			break;
597 		else if (vflag)
598 			warn("connect to %s port %s (%s) failed", host, port,
599 			    uflag ? "udp" : "tcp");
600 
601 		close(s);
602 		s = -1;
603 	} while ((res0 = res0->ai_next) != NULL);
604 
605 	freeaddrinfo(res);
606 
607 	return (s);
608 }
609 
610 /*
611  * local_listen()
612  * Returns a socket listening on a local port, binds to specified source
613  * address. Returns -1 on failure.
614  */
615 int
616 local_listen(char *host, char *port, struct addrinfo hints)
617 {
618 	struct addrinfo *res, *res0;
619 	int s, ret, x = 1;
620 	int error;
621 
622 	/* Allow nodename to be null. */
623 	hints.ai_flags |= AI_PASSIVE;
624 
625 	/*
626 	 * In the case of binding to a wildcard address
627 	 * default to binding to an ipv4 address.
628 	 */
629 	if (host == NULL && hints.ai_family == AF_UNSPEC)
630 		hints.ai_family = AF_INET;
631 
632 	if ((error = getaddrinfo(host, port, &hints, &res)))
633 		errx(1, "getaddrinfo: %s", gai_strerror(error));
634 
635 	res0 = res;
636 	do {
637 		if ((s = socket(res0->ai_family, res0->ai_socktype,
638 		    res0->ai_protocol)) < 0)
639 			continue;
640 
641 		if (rdomain) {
642 			if (setfib(rdomain) == -1)
643 				err(1, "setfib");
644 		}
645 
646 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
647 		if (ret == -1)
648 			err(1, NULL);
649 #ifdef IPSEC
650 		if (ipsec_policy[0] != NULL)
651 			add_ipsec_policy(s, ipsec_policy[0]);
652 		if (ipsec_policy[1] != NULL)
653 			add_ipsec_policy(s, ipsec_policy[1]);
654 #endif
655 		if (FreeBSD_Oflag) {
656 			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
657 			    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
658 				err(1, "disable TCP options");
659 		}
660 
661 		if (bind(s, (struct sockaddr *)res0->ai_addr,
662 		    res0->ai_addrlen) == 0)
663 			break;
664 
665 		close(s);
666 		s = -1;
667 	} while ((res0 = res0->ai_next) != NULL);
668 
669 	if (!uflag && s != -1) {
670 		if (listen(s, 1) < 0)
671 			err(1, "listen");
672 	}
673 
674 	freeaddrinfo(res);
675 
676 	return (s);
677 }
678 
679 /*
680  * readwrite()
681  * Loop that polls on the network file descriptor and stdin.
682  */
683 void
684 readwrite(int nfd)
685 {
686 	struct pollfd pfd[2];
687 	unsigned char buf[8192];
688 	int n, wfd = fileno(stdin);
689 	int lfd = fileno(stdout);
690 	int plen;
691 
692 	plen = jflag ? 8192 : 1024;
693 
694 	/* Setup Network FD */
695 	pfd[0].fd = nfd;
696 	pfd[0].events = POLLIN;
697 
698 	/* Set up STDIN FD. */
699 	pfd[1].fd = wfd;
700 	pfd[1].events = POLLIN;
701 
702 	while (pfd[0].fd != -1) {
703 		if (iflag)
704 			sleep(iflag);
705 
706 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
707 			close(nfd);
708 			err(1, "Polling Error");
709 		}
710 
711 		if (n == 0)
712 			return;
713 
714 		if (pfd[0].revents & POLLIN) {
715 			if ((n = read(nfd, buf, plen)) < 0)
716 				return;
717 			else if (n == 0) {
718 				shutdown(nfd, SHUT_RD);
719 				pfd[0].fd = -1;
720 				pfd[0].events = 0;
721 			} else {
722 				if (tflag)
723 					atelnet(nfd, buf, n);
724 				if (atomicio(vwrite, lfd, buf, n) != n)
725 					return;
726 			}
727 		}
728 
729 		if (!dflag && pfd[1].revents & POLLIN) {
730 			if ((n = read(wfd, buf, plen)) < 0 ||
731 			    (oflag && n == 0)) {
732 				return;
733 			} else if (n == 0) {
734 				shutdown(nfd, SHUT_WR);
735 				pfd[1].fd = -1;
736 				pfd[1].events = 0;
737 			} else {
738 				if (atomicio(vwrite, nfd, buf, n) != n)
739 					return;
740 			}
741 		}
742 	}
743 }
744 
745 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
746 void
747 atelnet(int nfd, unsigned char *buf, unsigned int size)
748 {
749 	unsigned char *p, *end;
750 	unsigned char obuf[4];
751 
752 	end = buf + size;
753 	obuf[0] = '\0';
754 
755 	for (p = buf; p < end; p++) {
756 		if (*p != IAC)
757 			break;
758 
759 		obuf[0] = IAC;
760 		p++;
761 		if ((*p == WILL) || (*p == WONT))
762 			obuf[1] = DONT;
763 		if ((*p == DO) || (*p == DONT))
764 			obuf[1] = WONT;
765 		if (obuf) {
766 			p++;
767 			obuf[2] = *p;
768 			obuf[3] = '\0';
769 			if (atomicio(vwrite, nfd, obuf, 3) != 3)
770 				warn("Write Error!");
771 			obuf[0] = '\0';
772 		}
773 	}
774 }
775 
776 /*
777  * build_ports()
778  * Build an array or ports in portlist[], listing each port
779  * that we should try to connect to.
780  */
781 void
782 build_ports(char *p)
783 {
784 	const char *errstr;
785 	char *n;
786 	int hi, lo, cp;
787 	int x = 0;
788 
789 	if ((n = strchr(p, '-')) != NULL) {
790 		if (lflag)
791 			errx(1, "Cannot use -l with multiple ports!");
792 
793 		*n = '\0';
794 		n++;
795 
796 		/* Make sure the ports are in order: lowest->highest. */
797 		hi = strtonum(n, 1, PORT_MAX, &errstr);
798 		if (errstr)
799 			errx(1, "port number %s: %s", errstr, n);
800 		lo = strtonum(p, 1, PORT_MAX, &errstr);
801 		if (errstr)
802 			errx(1, "port number %s: %s", errstr, p);
803 
804 		if (lo > hi) {
805 			cp = hi;
806 			hi = lo;
807 			lo = cp;
808 		}
809 
810 		/* Load ports sequentially. */
811 		for (cp = lo; cp <= hi; cp++) {
812 			portlist[x] = calloc(1, PORT_MAX_LEN);
813 			if (portlist[x] == NULL)
814 				err(1, NULL);
815 			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
816 			x++;
817 		}
818 
819 		/* Randomly swap ports. */
820 		if (rflag) {
821 			int y;
822 			char *c;
823 
824 			for (x = 0; x <= (hi - lo); x++) {
825 				y = (arc4random() & 0xFFFF) % (hi - lo);
826 				c = portlist[x];
827 				portlist[x] = portlist[y];
828 				portlist[y] = c;
829 			}
830 		}
831 	} else {
832 		hi = strtonum(p, 1, PORT_MAX, &errstr);
833 		if (errstr)
834 			errx(1, "port number %s: %s", errstr, p);
835 		portlist[0] = calloc(1, PORT_MAX_LEN);
836 		if (portlist[0] == NULL)
837 			err(1, NULL);
838 		portlist[0] = p;
839 	}
840 }
841 
842 /*
843  * udptest()
844  * Do a few writes to see if the UDP port is there.
845  * XXX - Better way of doing this? Doesn't work for IPv6.
846  * Also fails after around 100 ports checked.
847  */
848 int
849 udptest(int s)
850 {
851 	int i, ret;
852 
853 	for (i = 0; i <= 3; i++) {
854 		if (write(s, "X", 1) == 1)
855 			ret = 1;
856 		else
857 			ret = -1;
858 	}
859 	return (ret);
860 }
861 
862 void
863 set_common_sockopts(int s)
864 {
865 	int x = 1;
866 
867 	if (Sflag) {
868 		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
869 			&x, sizeof(x)) == -1)
870 			err(1, NULL);
871 	}
872 	if (Dflag) {
873 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
874 			&x, sizeof(x)) == -1)
875 			err(1, NULL);
876 	}
877 #ifdef SO_JUMBO
878 	if (jflag) {
879 		if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
880 			&x, sizeof(x)) == -1)
881 			err(1, NULL);
882 	}
883 #endif
884 	if (Tflag != -1) {
885 		if (setsockopt(s, IPPROTO_IP, IP_TOS,
886 		    &Tflag, sizeof(Tflag)) == -1)
887 			err(1, "set IP ToS");
888 	}
889 	if (Iflag) {
890 		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
891 		    &Iflag, sizeof(Iflag)) == -1)
892 			err(1, "set TCP receive buffer size");
893 	}
894 	if (Oflag) {
895 		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
896 		    &Oflag, sizeof(Oflag)) == -1)
897 			err(1, "set TCP send buffer size");
898 	}
899 	if (FreeBSD_Oflag) {
900 		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
901 		    &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
902 			err(1, "disable TCP options");
903 	}
904 }
905 
906 int
907 parse_iptos(char *s)
908 {
909 	int tos = -1;
910 
911 	if (strcmp(s, "lowdelay") == 0)
912 		return (IPTOS_LOWDELAY);
913 	if (strcmp(s, "throughput") == 0)
914 		return (IPTOS_THROUGHPUT);
915 	if (strcmp(s, "reliability") == 0)
916 		return (IPTOS_RELIABILITY);
917 
918 	if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
919 		errx(1, "invalid IP Type of Service");
920 	return (tos);
921 }
922 
923 void
924 help(void)
925 {
926 	usage(0);
927 	fprintf(stderr, "\tCommand Summary:\n\
928 	\t-4		Use IPv4\n\
929 	\t-6		Use IPv6\n\
930 	\t-D		Enable the debug socket option\n\
931 	\t-d		Detach from stdin\n");
932 #ifdef IPSEC
933 	fprintf(stderr, "\
934 	\t-E		Use IPsec ESP\n\
935 	\t-e policy	Use specified IPsec policy\n");
936 #endif
937 	fprintf(stderr, "\
938 	\t-h		This help text\n\
939 	\t-I length	TCP receive buffer length\n\
940 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
941 	\t-k		Keep inbound sockets open for multiple connects\n\
942 	\t-l		Listen mode, for inbound connects\n\
943 	\t-n		Suppress name/port resolutions\n\
944 	\t--no-tcpopt	Disable TCP options\n\
945 	\t-O length	TCP send buffer length\n\
946 	\t-o		Terminate on EOF on input\n\
947 	\t-P proxyuser\tUsername for proxy authentication\n\
948 	\t-p port\t	Specify local port for remote connects\n\
949 	\t-r		Randomize remote ports\n\
950 	\t-S		Enable the TCP MD5 signature option\n\
951 	\t-s addr\t	Local source address\n\
952 	\t-T ToS\t	Set IP Type of Service\n\
953 	\t-t		Answer TELNET negotiation\n\
954 	\t-U		Use UNIX domain socket\n\
955 	\t-u		UDP mode\n\
956 	\t-V fib	Specify alternate routing table (FIB)\n\
957 	\t-v		Verbose\n\
958 	\t-w secs\t	Timeout for connects and final net reads\n\
959 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
960 	\t-x addr[:port]\tSpecify proxy address and port\n\
961 	\t-z		Zero-I/O mode [used for scanning]\n\
962 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
963 #ifdef IPSEC
964 	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
965 #endif
966 	exit(1);
967 }
968 
969 #ifdef IPSEC
970 void
971 add_ipsec_policy(int s, char *policy)
972 {
973 	char *raw;
974 	int e;
975 
976 	raw = ipsec_set_policy(policy, strlen(policy));
977 	if (raw == NULL)
978 		errx(1, "ipsec_set_policy `%s': %s", policy,
979 		     ipsec_strerror());
980 	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
981 			ipsec_get_policylen(raw));
982 	if (e < 0)
983 		err(1, "ipsec policy cannot be configured");
984 	free(raw);
985 	if (vflag)
986 		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
987 	return;
988 }
989 #endif /* IPSEC */
990 
991 void
992 usage(int ret)
993 {
994 	fprintf(stderr,
995 #ifdef IPSEC
996 	    "usage: nc [-46DdEhklnorStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
997 #else
998 	    "usage: nc [-46DdhklnorStUuvz] [-I length] [-i interval] [-O length]\n"
999 #endif
1000 	    "\t  [-P proxy_username] [-p source_port] [-s source_ip_address] [-T ToS]\n"
1001 	    "\t  [-V fib] [-w timeout] [-X proxy_protocol]\n"
1002 	    "\t  [-x proxy_address[:port]] [hostname] [port]\n");
1003 	if (ret)
1004 		exit(1);
1005 }
1006