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