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