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