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