xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.bin/nc/netcat.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
1 /* $OpenBSD: netcat.c,v 1.89 2007/02/20 14:11:17 jmc 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 
29 /*
30  * Re-written nc(1) for OpenBSD. Original implementation by
31  * *Hobbit* <hobbit@avian.org>.
32  */
33 
34 /*
35  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
36  * Use is subject to license terms.
37  */
38 
39 /*
40  * Portions Copyright 2008 Erik Trauschke
41  * Copyright 2024 Oxide Computer Company
42  */
43 
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <sys/time.h>
47 #include <sys/un.h>
48 
49 #include <netinet/in.h>
50 #include <netinet/in_systm.h>
51 #include <netinet/tcp.h>
52 #include <netinet/ip.h>
53 #include <arpa/telnet.h>
54 
55 #include <err.h>
56 #include <errno.h>
57 #include <netdb.h>
58 #include <poll.h>
59 #include <stdarg.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <fcntl.h>
65 #include <limits.h>
66 #include <signal.h>
67 
68 #include "atomicio.h"
69 
70 #ifndef	SUN_LEN
71 #define	SUN_LEN(su) \
72 	(sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
73 #endif
74 
75 #define	PORT_MIN	1
76 #define	PORT_MAX	65535
77 #define	PORT_MAX_LEN	6
78 #define	PLIST_SZ	32	/* initial capacity of the portlist */
79 
80 /* Command Line Options */
81 int	dflag;		/* detached, no stdin */
82 unsigned int iflag;	/* Interval Flag */
83 int	kflag;		/* More than one connect */
84 int	lflag;		/* Bind to local port */
85 int	nflag;		/* Don't do name lookup */
86 const char *Pflag;		/* Proxy username */
87 char	*pflag;		/* Localport flag */
88 int	rflag;		/* Random ports flag */
89 const char *sflag;		/* Source Address */
90 int	tflag;		/* Telnet Emulation */
91 int	uflag;		/* UDP - Default to TCP */
92 int	vflag;		/* Verbosity */
93 int	xflag;		/* Socks proxy */
94 int	Xflag;		/* indicator of Socks version set */
95 int	zflag;		/* Port Scan Flag */
96 int	Dflag;		/* sodebug */
97 int	Sflag;		/* TCP MD5 signature option */
98 int	Tflag = -1;	/* IP Type of Service */
99 
100 int	timeout = -1;
101 int	family = AF_UNSPEC;
102 int	ttl = -1;
103 int	minttl = -1;
104 
105 /*
106  * portlist structure
107  * Used to store a list of ports given by the user and maintaining
108  * information about the number of ports stored.
109  */
110 struct {
111 	uint16_t *list; /* list containing the ports */
112 	uint_t listsize;   /* capacity of the list (number of entries) */
113 	uint_t numports;   /* number of ports in the list */
114 } ports;
115 
116 void	atelnet(int, unsigned char *, unsigned int);
117 void	build_ports(char *);
118 void	help(void);
119 int	local_listen(const char *, const char *, struct addrinfo);
120 void	readwrite(int);
121 int	remote_connect(const char *, const char *, struct addrinfo);
122 int	socks_connect(const char *, const char *,
123 	    const char *, const char *, struct addrinfo, int, const char *);
124 int	udptest(int);
125 int	unix_connect(const char *);
126 int	unix_listen(const char *);
127 void	set_common_sockopts(int, int);
128 int	parse_iptos(const char *);
129 void	usage(int);
130 const char *print_addr(char *, size_t, struct sockaddr *, int, int);
131 
132 int
133 main(int argc, char *argv[])
134 {
135 	int ch, s, ret, socksv;
136 	char *host, *uport, *proxy;
137 	struct addrinfo hints;
138 	struct servent *sv;
139 	socklen_t len;
140 	struct sockaddr_storage cliaddr;
141 	const char *errstr, *proxyhost = "", *proxyport = NULL;
142 	struct addrinfo proxyhints;
143 	char port[PORT_MAX_LEN];
144 
145 	ret = 1;
146 	s = -1;
147 	socksv = 5;
148 	host = NULL;
149 	uport = NULL;
150 	sv = NULL;
151 
152 	while ((ch = getopt(argc, argv,
153 	    "46Ddhi:klm:M:nP:p:rs:ST:tUuvw:X:x:z")) != -1) {
154 		switch (ch) {
155 		case '4':
156 			family = AF_INET;
157 			break;
158 		case '6':
159 			family = AF_INET6;
160 			break;
161 		case 'U':
162 			family = AF_UNIX;
163 			break;
164 		case 'X':
165 			Xflag = 1;
166 			if (strcasecmp(optarg, "connect") == 0)
167 				socksv = -1; /* HTTP proxy CONNECT */
168 			else if (strcmp(optarg, "4") == 0)
169 				socksv = 4; /* SOCKS v.4 */
170 			else if (strcmp(optarg, "5") == 0)
171 				socksv = 5; /* SOCKS v.5 */
172 			else
173 				errx(1, "unsupported proxy protocol");
174 			break;
175 		case 'd':
176 			dflag = 1;
177 			break;
178 		case 'h':
179 			help();
180 			break;
181 		case 'i':
182 			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
183 			if (errstr)
184 				errx(1, "interval %s: %s", errstr, optarg);
185 			break;
186 		case 'k':
187 			kflag = 1;
188 			break;
189 		case 'M':
190 			ttl = strtonumx(optarg, 1, 255, &errstr, 0);
191 			if (errstr != NULL) {
192 				errx(1, "ttl is %s: %s, valid values are "
193 				    "between 1 and 255", errstr, optarg);
194 			}
195 			break;
196 		case 'm':
197 			minttl = strtonumx(optarg, 0, 255, &errstr, 0);
198 			if (errstr != NULL) {
199 				errx(1, "minimum ttl is %s: %s, valid values "
200 				    "are between 0 and 255", errstr, optarg);
201 			}
202 			break;
203 		case 'l':
204 			lflag = 1;
205 			break;
206 		case 'n':
207 			nflag = 1;
208 			break;
209 		case 'P':
210 			Pflag = optarg;
211 			break;
212 		case 'p':
213 			pflag = optarg;
214 			break;
215 		case 'r':
216 			rflag = 1;
217 			break;
218 		case 's':
219 			sflag = optarg;
220 			break;
221 		case 't':
222 			tflag = 1;
223 			break;
224 		case 'u':
225 			uflag = 1;
226 			break;
227 		case 'v':
228 			vflag = 1;
229 			break;
230 		case 'w':
231 			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
232 			if (errstr)
233 				errx(1, "timeout %s: %s", errstr, optarg);
234 			timeout *= 1000;
235 			break;
236 		case 'x':
237 			xflag = 1;
238 			if ((proxy = strdup(optarg)) == NULL)
239 				err(1, NULL);
240 			break;
241 		case 'z':
242 			zflag = 1;
243 			break;
244 		case 'D':
245 			Dflag = 1;
246 			break;
247 		case 'S':
248 			Sflag = 1;
249 			break;
250 		case 'T':
251 			Tflag = parse_iptos(optarg);
252 			break;
253 		default:
254 			usage(1);
255 		}
256 	}
257 	argc -= optind;
258 	argv += optind;
259 
260 	/* Cruft to make sure options are clean, and used properly. */
261 	if (argv[0] && !argv[1] && family == AF_UNIX) {
262 		if (uflag)
263 			errx(1, "cannot use -u and -U");
264 		host = argv[0];
265 		uport = NULL;
266 	} else if (argv[0] && !argv[1]) {
267 		if (!lflag)
268 			usage(1);
269 		uport = argv[0];
270 		host = NULL;
271 	} else if (argv[0] && argv[1]) {
272 		if (family == AF_UNIX)
273 			usage(1);
274 		host = argv[0];
275 		uport = argv[1];
276 	} else {
277 		if (!(lflag && pflag))
278 			usage(1);
279 	}
280 
281 	if (argc > 2)
282 		usage(1);
283 
284 	if (lflag && sflag)
285 		errx(1, "cannot use -s and -l");
286 	if (lflag && rflag)
287 		errx(1, "cannot use -r and -l");
288 	if (lflag && (timeout >= 0))
289 		warnx("-w has no effect with -l");
290 	if (lflag && pflag) {
291 		if (uport)
292 			usage(1);
293 		uport = pflag;
294 	}
295 	if (lflag && zflag)
296 		errx(1, "cannot use -z and -l");
297 	if (!lflag && kflag)
298 		errx(1, "must use -l with -k");
299 	if (lflag && (Pflag || xflag || Xflag))
300 		errx(1, "cannot use -l with -P, -X or -x");
301 
302 	/* Initialize addrinfo structure. */
303 	if (family != AF_UNIX) {
304 		(void) memset(&hints, 0, sizeof (struct addrinfo));
305 		hints.ai_family = family;
306 		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
307 		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
308 		if (nflag)
309 			hints.ai_flags |= AI_NUMERICHOST;
310 	}
311 
312 	if (xflag) {
313 		if (uflag)
314 			errx(1, "no proxy support for UDP mode");
315 
316 		if (lflag)
317 			errx(1, "no proxy support for listen");
318 
319 		if (family == AF_UNIX)
320 			errx(1, "no proxy support for unix sockets");
321 
322 		if (family == AF_INET6)
323 			errx(1, "no proxy support for IPv6");
324 
325 		if (sflag)
326 			errx(1, "no proxy support for local source address");
327 
328 		if ((proxyhost = strtok(proxy, ":")) == NULL)
329 			errx(1, "missing port specification");
330 		proxyport = strtok(NULL, ":");
331 
332 		(void) memset(&proxyhints, 0, sizeof (struct addrinfo));
333 		proxyhints.ai_family = family;
334 		proxyhints.ai_socktype = SOCK_STREAM;
335 		proxyhints.ai_protocol = IPPROTO_TCP;
336 		if (nflag)
337 			proxyhints.ai_flags |= AI_NUMERICHOST;
338 	}
339 
340 	if (lflag) {
341 		int connfd;
342 		ret = 0;
343 
344 		if (family == AF_UNIX) {
345 			if (host == NULL)
346 				usage(1);
347 			s = unix_listen(host);
348 		}
349 
350 		/* Allow only one connection at a time, but stay alive. */
351 		for (;;) {
352 			if (family != AF_UNIX) {
353 				/* check if uport is valid */
354 				if (strtonum(uport, PORT_MIN, PORT_MAX,
355 				    &errstr) == 0)
356 					errx(1, "port number %s: %s",
357 					    uport, errstr);
358 				s = local_listen(host, uport, hints);
359 			}
360 			if (s < 0)
361 				err(1, NULL);
362 			/*
363 			 * For UDP, we will use recvfrom() initially
364 			 * to wait for a caller, then use the regular
365 			 * functions to talk to the caller.
366 			 */
367 			if (uflag) {
368 				int rv, plen;
369 				char buf[8192];
370 				struct sockaddr_storage z;
371 
372 				len = sizeof (z);
373 				plen = 1024;
374 				rv = recvfrom(s, buf, plen, MSG_PEEK,
375 				    (struct sockaddr *)&z, &len);
376 				if (rv < 0)
377 					err(1, "recvfrom");
378 
379 				rv = connect(s, (struct sockaddr *)&z, len);
380 				if (rv < 0)
381 					err(1, "connect");
382 
383 				connfd = s;
384 			} else {
385 				len = sizeof (cliaddr);
386 				connfd = accept(s, (struct sockaddr *)&cliaddr,
387 				    &len);
388 				if ((connfd != -1) && vflag) {
389 					char ntop[NI_MAXHOST + NI_MAXSERV];
390 					(void) fprintf(stderr,
391 					    "Received connection from %s\n",
392 					    print_addr(ntop, sizeof (ntop),
393 					    (struct sockaddr *)&cliaddr, len,
394 					    nflag ? NI_NUMERICHOST : 0));
395 				}
396 			}
397 
398 			readwrite(connfd);
399 			(void) close(connfd);
400 			if (family != AF_UNIX)
401 				(void) close(s);
402 
403 			if (!kflag)
404 				break;
405 		}
406 	} else if (family == AF_UNIX) {
407 		ret = 0;
408 
409 		if ((s = unix_connect(host)) > 0 && !zflag) {
410 			readwrite(s);
411 			(void) close(s);
412 		} else
413 			ret = 1;
414 
415 		exit(ret);
416 
417 	} else {	/* AF_INET or AF_INET6 */
418 		int i;
419 
420 		/* Construct the portlist. */
421 		build_ports(uport);
422 
423 		/* Cycle through portlist, connecting to each port. */
424 		for (i = 0; i < ports.numports; i++) {
425 			(void) snprintf(port, sizeof (port), "%u",
426 			    ports.list[i]);
427 
428 			if (s != -1)
429 				(void) close(s);
430 
431 			if (xflag)
432 				s = socks_connect(host, port,
433 				    proxyhost, proxyport, proxyhints, socksv,
434 				    Pflag);
435 			else
436 				s = remote_connect(host, port, hints);
437 
438 			if (s < 0)
439 				continue;
440 
441 			ret = 0;
442 			if (vflag || zflag) {
443 				/* For UDP, make sure we are connected. */
444 				if (uflag) {
445 					if (udptest(s) == -1) {
446 						ret = 1;
447 						continue;
448 					}
449 				}
450 
451 				/* Don't look up port if -n. */
452 				if (nflag)
453 					sv = NULL;
454 				else {
455 					sv = getservbyport(
456 					    ntohs(ports.list[i]),
457 					    uflag ? "udp" : "tcp");
458 				}
459 
460 				(void) fprintf(stderr, "Connection to %s %s "
461 				    "port [%s/%s] succeeded!\n",
462 				    host, port, uflag ? "udp" : "tcp",
463 				    sv ? sv->s_name : "*");
464 			}
465 			if (!zflag)
466 				readwrite(s);
467 		}
468 		free(ports.list);
469 	}
470 
471 	if (s != -1)
472 		(void) close(s);
473 
474 	return (ret);
475 }
476 
477 /*
478  * print IP address and (optionally) a port
479  */
480 const char *
481 print_addr(char *ntop, size_t ntlen, struct sockaddr *addr, int len, int flags)
482 {
483 	char port[NI_MAXSERV];
484 	int e;
485 
486 	/* print port always as number */
487 	if ((e = getnameinfo(addr, len, ntop, ntlen,
488 	    port, sizeof (port), flags|NI_NUMERICSERV)) != 0) {
489 		return ((char *)gai_strerror(e));
490 	}
491 
492 	(void) strlcat(ntop, " port ", ntlen);
493 	(void) strlcat(ntop, port, ntlen);
494 
495 	return (ntop);
496 }
497 
498 /*
499  * unix_connect()
500  * Returns a socket connected to a local unix socket. Returns -1 on failure.
501  */
502 int
503 unix_connect(const char *path)
504 {
505 	struct sockaddr_un sunaddr;
506 	int s;
507 
508 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
509 		return (-1);
510 
511 	(void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
512 	sunaddr.sun_family = AF_UNIX;
513 
514 	if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
515 	    sizeof (sunaddr.sun_path)) {
516 		(void) close(s);
517 		errno = ENAMETOOLONG;
518 		return (-1);
519 	}
520 	if (connect(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
521 		(void) close(s);
522 		return (-1);
523 	}
524 	return (s);
525 }
526 
527 /*
528  * unix_listen()
529  * Create a unix domain socket, and listen on it.
530  */
531 int
532 unix_listen(const char *path)
533 {
534 	struct sockaddr_un sunaddr;
535 	int s;
536 
537 	/* Create unix domain socket. */
538 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
539 		return (-1);
540 
541 	(void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
542 	sunaddr.sun_family = AF_UNIX;
543 
544 	if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
545 	    sizeof (sunaddr.sun_path)) {
546 		(void) close(s);
547 		errno = ENAMETOOLONG;
548 		return (-1);
549 	}
550 
551 	if (bind(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
552 		(void) close(s);
553 		return (-1);
554 	}
555 
556 	if (listen(s, 5) < 0) {
557 		(void) close(s);
558 		return (-1);
559 	}
560 	return (s);
561 }
562 
563 /*
564  * remote_connect()
565  * Returns a socket connected to a remote host. Properly binds to a local
566  * port or source address if needed. Returns -1 on failure.
567  */
568 int
569 remote_connect(const char *host, const char *port, struct addrinfo hints)
570 {
571 	struct addrinfo *res, *res0;
572 	int s, error;
573 
574 	if ((error = getaddrinfo(host, port, &hints, &res)))
575 		errx(1, "getaddrinfo: %s", gai_strerror(error));
576 
577 	res0 = res;
578 	do {
579 		if ((s = socket(res0->ai_family, res0->ai_socktype,
580 		    res0->ai_protocol)) < 0) {
581 			warn("failed to create socket");
582 			continue;
583 		}
584 
585 		/* Bind to a local port or source address if specified. */
586 		if (sflag || pflag) {
587 			struct addrinfo ahints, *ares;
588 
589 			(void) memset(&ahints, 0, sizeof (struct addrinfo));
590 			ahints.ai_family = res0->ai_family;
591 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
592 			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
593 			ahints.ai_flags = AI_PASSIVE;
594 			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
595 				errx(1, "getaddrinfo: %s", gai_strerror(error));
596 
597 			if (bind(s, (struct sockaddr *)ares->ai_addr,
598 			    ares->ai_addrlen) < 0)
599 				errx(1, "bind failed: %s", strerror(errno));
600 			freeaddrinfo(ares);
601 
602 			if (vflag && !lflag) {
603 				if (sflag != NULL)
604 					(void) fprintf(stderr,
605 					    "Using source address: %s\n",
606 					    sflag);
607 				if (pflag != NULL)
608 					(void) fprintf(stderr,
609 					    "Using source port: %s\n", pflag);
610 			}
611 		}
612 
613 		set_common_sockopts(s, res0->ai_family);
614 
615 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
616 			break;
617 		else if (vflag) {
618 			char ntop[NI_MAXHOST + NI_MAXSERV];
619 			warn("connect to %s [host %s] (%s) failed",
620 			    print_addr(ntop, sizeof (ntop),
621 			    res0->ai_addr, res0->ai_addrlen, NI_NUMERICHOST),
622 			    host, uflag ? "udp" : "tcp");
623 		}
624 
625 		(void) close(s);
626 		s = -1;
627 	} while ((res0 = res0->ai_next) != NULL);
628 
629 	freeaddrinfo(res);
630 
631 	return (s);
632 }
633 
634 /*
635  * local_listen()
636  * Returns a socket listening on a local port, binds to specified source
637  * address. Returns -1 on failure.
638  */
639 int
640 local_listen(const char *host, const char *port, struct addrinfo hints)
641 {
642 	struct addrinfo *res, *res0;
643 	int s, ret, x = 1;
644 	int error;
645 
646 	/* Allow nodename to be null. */
647 	hints.ai_flags |= AI_PASSIVE;
648 
649 	if ((error = getaddrinfo(host, port, &hints, &res)))
650 		errx(1, "getaddrinfo: %s", gai_strerror(error));
651 
652 	res0 = res;
653 	do {
654 		if ((s = socket(res0->ai_family, res0->ai_socktype,
655 		    res0->ai_protocol)) < 0) {
656 			warn("failed to create socket");
657 			continue;
658 		}
659 
660 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
661 		if (ret == -1)
662 			err(1, NULL);
663 
664 		set_common_sockopts(s, res0->ai_family);
665 
666 		if (bind(s, (struct sockaddr *)res0->ai_addr,
667 		    res0->ai_addrlen) == 0)
668 			break;
669 
670 		(void) close(s);
671 		s = -1;
672 	} while ((res0 = res0->ai_next) != NULL);
673 
674 	if (!uflag && s != -1) {
675 		if (listen(s, 1) < 0)
676 			err(1, "listen");
677 	}
678 
679 	freeaddrinfo(res);
680 
681 	return (s);
682 }
683 
684 /*
685  * readwrite()
686  * Loop that polls on the network file descriptor and stdin.
687  */
688 void
689 readwrite(int nfd)
690 {
691 	struct pollfd pfd[2];
692 	unsigned char buf[8192];
693 	int n, wfd = fileno(stdin);
694 	int lfd = fileno(stdout);
695 	int plen;
696 
697 	plen = 1024;
698 
699 	/* Setup Network FD */
700 	pfd[0].fd = nfd;
701 	pfd[0].events = POLLIN;
702 
703 	/* Set up STDIN FD. */
704 	pfd[1].fd = wfd;
705 	pfd[1].events = POLLIN;
706 
707 	while (pfd[0].fd != -1) {
708 		if (iflag)
709 			(void) sleep(iflag);
710 
711 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
712 			(void) close(nfd);
713 			err(1, "Polling Error");
714 		}
715 
716 		if (n == 0)
717 			return;
718 
719 		if (pfd[0].revents & (POLLIN|POLLHUP)) {
720 			if ((n = read(nfd, buf, plen)) < 0)
721 				return;
722 			else if (n == 0) {
723 				(void) shutdown(nfd, SHUT_RD);
724 				pfd[0].fd = -1;
725 				pfd[0].events = 0;
726 			} else {
727 				if (tflag)
728 					atelnet(nfd, buf, n);
729 				if (atomicio(vwrite, lfd, buf, n) != n)
730 					return;
731 			}
732 		}
733 
734 		/*
735 		 * handle the case of disconnected pipe: after pipe
736 		 * is closed (indicated by POLLHUP) there may still
737 		 * be some data lingering (POLLIN). After we read
738 		 * the data, only POLLHUP remains, read() returns 0
739 		 * and we are finished.
740 		 */
741 		if (!dflag && (pfd[1].revents & (POLLIN|POLLHUP))) {
742 			if ((n = read(wfd, buf, plen)) < 0)
743 				return;
744 			else if (n == 0) {
745 				(void) shutdown(nfd, SHUT_WR);
746 				pfd[1].fd = -1;
747 				pfd[1].events = 0;
748 			} else {
749 				if (atomicio(vwrite, nfd, buf, n) != n)
750 					return;
751 			}
752 		}
753 	}
754 }
755 
756 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
757 void
758 atelnet(int nfd, unsigned char *buf, unsigned int size)
759 {
760 	unsigned char *p, *end;
761 	unsigned char obuf[4];
762 
763 	end = buf + size;
764 	obuf[0] = '\0';
765 
766 	for (p = buf; p < end; p++) {
767 		if (*p != IAC)
768 			break;
769 
770 		obuf[0] = IAC;
771 		obuf[1] = 0;
772 		p++;
773 		/* refuse all options */
774 		if ((*p == WILL) || (*p == WONT))
775 			obuf[1] = DONT;
776 		if ((*p == DO) || (*p == DONT))
777 			obuf[1] = WONT;
778 		if (obuf[1]) {
779 			p++;
780 			obuf[2] = *p;
781 			obuf[3] = '\0';
782 			if (atomicio(vwrite, nfd, obuf, 3) != 3)
783 				warn("Write Error!");
784 			obuf[0] = '\0';
785 		}
786 	}
787 }
788 
789 /*
790  * build_ports()
791  * Build an array of ports in ports.list[], listing each port
792  * that we should try to connect to.
793  */
794 void
795 build_ports(char *p)
796 {
797 	const char *errstr;
798 	const char *token;
799 	char *n;
800 	int lo, hi, cp;
801 	int i;
802 
803 	/* Set up initial portlist. */
804 	ports.list = malloc(PLIST_SZ * sizeof (uint16_t));
805 	if (ports.list == NULL)
806 		err(1, NULL);
807 	ports.listsize = PLIST_SZ;
808 	ports.numports = 0;
809 
810 	/* Cycle through list of given ports sep. by "," */
811 	while ((token = strsep(&p, ",")) != NULL) {
812 		if (*token == '\0')
813 			errx(1, "Invalid port/portlist format: "
814 			    "zero length port");
815 
816 		/* check if it is a range */
817 		if ((n = strchr(token, '-')) != NULL)
818 			*n++ = '\0';
819 
820 		lo = strtonum(token, PORT_MIN, PORT_MAX, &errstr);
821 		if (errstr)
822 			errx(1, "port number %s: %s", errstr, token);
823 
824 		if (n == NULL) {
825 			hi = lo;
826 		} else {
827 			hi = strtonum(n, PORT_MIN, PORT_MAX, &errstr);
828 			if (errstr)
829 				errx(1, "port number %s: %s", errstr, n);
830 			if (lo > hi) {
831 				cp = hi;
832 				hi = lo;
833 				lo = cp;
834 			}
835 		}
836 
837 		/*
838 		 * Grow the portlist if needed.
839 		 * We double the size and add size of current range
840 		 * to make sure we don't have to resize that often.
841 		 */
842 		if (hi - lo + ports.numports + 1 >= ports.listsize) {
843 			ports.listsize = ports.listsize * 2 + hi - lo;
844 			ports.list = realloc(ports.list,
845 			    ports.listsize * sizeof (uint16_t));
846 			if (ports.list == NULL)
847 				err(1, NULL);
848 		}
849 
850 		/* Load ports sequentially. */
851 		for (i = lo; i <= hi; i++)
852 			ports.list[ports.numports++] = i;
853 	}
854 
855 	/* Randomly swap ports. */
856 	if (rflag) {
857 		int y;
858 		uint16_t u;
859 
860 		if (ports.numports < 2) {
861 			warnx("can not swap %d port randomly",
862 			    ports.numports);
863 			return;
864 		}
865 		srandom(time(NULL));
866 		for (i = 0; i < ports.numports; i++) {
867 			y = random() % (ports.numports - 1);
868 			u = ports.list[i];
869 			ports.list[i] = ports.list[y];
870 			ports.list[y] = u;
871 		}
872 	}
873 }
874 
875 /*
876  * udptest()
877  * Do a few writes to see if the UDP port is there.
878  * XXX - Better way of doing this? Doesn't work for IPv6.
879  * Also fails after around 100 ports checked.
880  */
881 int
882 udptest(int s)
883 {
884 	int i, ret;
885 
886 	for (i = 0; i <= 3; i++) {
887 		if (write(s, "X", 1) == 1)
888 			ret = 1;
889 		else
890 			ret = -1;
891 	}
892 	return (ret);
893 }
894 
895 void
896 set_common_sockopts(int s, int af)
897 {
898 	int x = 1;
899 
900 	if (Sflag) {
901 		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
902 		    &x, sizeof (x)) == -1) {
903 			err(1, NULL);
904 		}
905 	}
906 
907 	if (Dflag) {
908 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof (x)) == -1)
909 			err(1, NULL);
910 	}
911 	if (Tflag != -1) {
912 		switch (af) {
913 		case AF_INET:
914 			if (setsockopt(s, IPPROTO_IP, IP_TOS, &Tflag,
915 			    sizeof (Tflag)) == -1) {
916 				err(1, "failed to set IP ToS socket option");
917 			}
918 			break;
919 		case AF_INET6:
920 			if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &Tflag,
921 			    sizeof (Tflag)) == -1) {
922 				err(1, "failed to set IPv6 traffic class "
923 				    "socket option");
924 			}
925 			break;
926 		default:
927 			err(1, "cannot set TTL/Hops on unsupported socket "
928 			    "family 0x%x", af);
929 		}
930 	}
931 
932 	if (ttl != -1) {
933 		switch (af) {
934 		case AF_INET:
935 			if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl,
936 			    sizeof (ttl)) != 0) {
937 				err(1, "failed to set IP TTL socket option");
938 			}
939 			break;
940 		case AF_INET6:
941 			if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl,
942 			    sizeof (ttl)) != 0) {
943 				err(1, "failed to set IPv6 unicast hops socket "
944 				    "option");
945 			}
946 			break;
947 		default:
948 			err(1, "cannot set TTL/Hops on unsupported socket "
949 			    "family 0x%x", af);
950 		}
951 	}
952 
953 	if (minttl != -1) {
954 		switch (af) {
955 		case AF_INET:
956 			if (setsockopt(s, IPPROTO_IP, IP_MINTTL, &minttl,
957 			    sizeof (minttl)) != 0) {
958 				err(1, "failed to set IP minimum TTL socket "
959 				    "option");
960 			}
961 			break;
962 		case AF_INET6:
963 			if (setsockopt(s, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
964 			    &minttl, sizeof (minttl)) != 0) {
965 				err(1, "failed to set IPv6 minimum hop count "
966 				    "socket option");
967 			}
968 			break;
969 		default:
970 			err(1, "cannot set minimum TTL/Hops on unsupported "
971 			    "socket family 0x%x", af);
972 		}
973 	}
974 
975 }
976 
977 int
978 parse_iptos(const char *s)
979 {
980 	int tos;
981 	const char *errstr;
982 
983 	if (strcmp(s, "lowdelay") == 0)
984 		return (IPTOS_LOWDELAY);
985 	if (strcmp(s, "throughput") == 0)
986 		return (IPTOS_THROUGHPUT);
987 	if (strcmp(s, "reliability") == 0)
988 		return (IPTOS_RELIABILITY);
989 
990 	tos = strtonumx(s, 0, 255, &errstr, 0);
991 	if (errstr != NULL) {
992 		errx(1, "IP ToS/IPv6 TC is %s: %s, valid values are "
993 		    "between 0 and 255", errstr, optarg);
994 	}
995 
996 	return (tos);
997 }
998 
999 void
1000 help(void)
1001 {
1002 	usage(0);
1003 	(void) fprintf(stderr, "\tCommand Summary:\n\
1004 	\t-4		Use IPv4\n\
1005 	\t-6		Use IPv6\n\
1006 	\t-D		Enable the debug socket option\n\
1007 	\t-d		Detach from stdin\n\
1008 	\t-h		This help text\n\
1009 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
1010 	\t-k		Keep inbound sockets open for multiple connects\n\
1011 	\t-l		Listen mode, for inbound connects\n\
1012 	\t-l		Listen mode, for inbound connects\n\
1013 	\t-M ttl\t	Set the outbound IPv4 TTL / IPv6 Hop Limit\n\
1014 	\t-m minttl	Set the inbound minimum IPv4 TTL / IPv6 Hop Limit\n\
1015 	\t-n		Suppress name/port resolutions\n\
1016 	\t-P proxyuser\tUsername for proxy authentication\n\
1017 	\t-p port\t	Specify local port or listen port\n\
1018 	\t-r		Randomize remote ports\n\
1019 	\t-S		Enable TCP MD5 signature socket option\n\
1020 	\t-s addr\t	Local source address\n\
1021 	\t-T ToS\t	Set IP Type of Service\n\
1022 	\t-t		Answer TELNET negotiation\n\
1023 	\t-U		Use UNIX domain socket\n\
1024 	\t-u		UDP mode\n\
1025 	\t-v		Verbose\n\
1026 	\t-w secs\t	Timeout for connects and final net reads\n\
1027 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1028 	\t-x addr[:port]\tSpecify proxy address and port\n\
1029 	\t-z		Zero-I/O mode [used for scanning]\n\
1030 	Port numbers can be individuals, ranges (lo-hi; inclusive) and\n\
1031 	combinations of both separated by comma (e.g. 10,22-25,80)\n");
1032 	exit(1);
1033 }
1034 
1035 void
1036 usage(int ret)
1037 {
1038 	(void) fprintf(stderr,
1039 	    "usage: nc [-46DdhklnrStUuvz] [-i interval] [-M ttl] [-m minttl]\n"
1040 	    "\t  [-P proxy_username] [-p port] [-s source_ip_address] "
1041 	    "[-T ToS]\n"
1042 	    "\t  [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]]\n"
1043 	    "\t  [hostname] [port[s]]\n");
1044 	if (ret)
1045 		exit(1);
1046 }
1047