xref: /titanic_41/usr/src/cmd/cmd-inet/usr.bin/nc/netcat.c (revision f6acbf7c6543dc0aab58cae1df419f0147c46d77)
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 #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 (lflag && sflag)
248 		errx(1, "cannot use -s and -l");
249 	if (lflag && rflag)
250 		errx(1, "cannot use -r and -l");
251 	if (lflag && pflag) {
252 		if (uport)
253 			usage(1);
254 		uport = pflag;
255 	}
256 	if (lflag && zflag)
257 		errx(1, "cannot use -z and -l");
258 	if (!lflag && kflag)
259 		errx(1, "must use -l with -k");
260 	if (lflag && (Pflag || xflag || Xflag))
261 		errx(1, "cannot use -l with -P, -X or -x");
262 
263 	/* Initialize addrinfo structure. */
264 	if (family != AF_UNIX) {
265 		(void) memset(&hints, 0, sizeof (struct addrinfo));
266 		hints.ai_family = family;
267 		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
268 		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
269 		if (nflag)
270 			hints.ai_flags |= AI_NUMERICHOST;
271 	}
272 
273 	if (xflag) {
274 		if (uflag)
275 			errx(1, "no proxy support for UDP mode");
276 
277 		if (lflag)
278 			errx(1, "no proxy support for listen");
279 
280 		if (family == AF_UNIX)
281 			errx(1, "no proxy support for unix sockets");
282 
283 		if (family == AF_INET6)
284 			errx(1, "no proxy support for IPv6");
285 
286 		if (sflag)
287 			errx(1, "no proxy support for local source address");
288 
289 		if ((proxyhost = strtok(proxy, ":")) == NULL)
290 			errx(1, "missing port specification");
291 		proxyport = strtok(NULL, ":");
292 
293 		(void) memset(&proxyhints, 0, sizeof (struct addrinfo));
294 		proxyhints.ai_family = family;
295 		proxyhints.ai_socktype = SOCK_STREAM;
296 		proxyhints.ai_protocol = IPPROTO_TCP;
297 		if (nflag)
298 			proxyhints.ai_flags |= AI_NUMERICHOST;
299 	}
300 
301 	if (lflag) {
302 		int connfd;
303 		ret = 0;
304 
305 		if (family == AF_UNIX)
306 			s = unix_listen(host);
307 
308 		/* Allow only one connection at a time, but stay alive. */
309 		for (;;) {
310 			if (family != AF_UNIX)
311 				s = local_listen(host, uport, hints);
312 			if (s < 0)
313 				err(1, NULL);
314 			/*
315 			 * For UDP, we will use recvfrom() initially
316 			 * to wait for a caller, then use the regular
317 			 * functions to talk to the caller.
318 			 */
319 			if (uflag) {
320 				int rv, plen;
321 				char buf[8192];
322 				struct sockaddr_storage z;
323 
324 				len = sizeof (z);
325 				plen = 1024;
326 				rv = recvfrom(s, buf, plen, MSG_PEEK,
327 				    (struct sockaddr *)&z, &len);
328 				if (rv < 0)
329 					err(1, "recvfrom");
330 
331 				rv = connect(s, (struct sockaddr *)&z, len);
332 				if (rv < 0)
333 					err(1, "connect");
334 
335 				connfd = s;
336 			} else {
337 				len = sizeof (cliaddr);
338 				connfd = accept(s, (struct sockaddr *)&cliaddr,
339 				    &len);
340 				if ((connfd != -1) && vflag) {
341 					char ntop[NI_MAXHOST + NI_MAXSERV];
342 					(void) fprintf(stderr,
343 					    "Received connection from %s\n",
344 					    print_addr(ntop, sizeof (ntop),
345 					    (struct sockaddr *)&cliaddr, len,
346 					    nflag ? NI_NUMERICHOST : 0));
347 				}
348 			}
349 
350 			readwrite(connfd);
351 			(void) close(connfd);
352 			if (family != AF_UNIX)
353 				(void) close(s);
354 
355 			if (!kflag)
356 				break;
357 		}
358 	} else if (family == AF_UNIX) {
359 		ret = 0;
360 
361 		if ((s = unix_connect(host)) > 0 && !zflag) {
362 			readwrite(s);
363 			(void) close(s);
364 		} else
365 			ret = 1;
366 
367 		exit(ret);
368 
369 	} else {	/* AF_INET or AF_INET6 */
370 		int i = 0;
371 
372 		/* Construct the portlist[] array. */
373 		build_ports(uport);
374 
375 		/* Cycle through portlist, connecting to each port. */
376 		for (i = 0; portlist[i] != NULL; i++) {
377 			if (s)
378 				(void) close(s);
379 
380 			if (xflag)
381 				s = socks_connect(host, portlist[i],
382 				    proxyhost, proxyport, proxyhints, socksv,
383 				    Pflag);
384 			else
385 				s = remote_connect(host, portlist[i], hints);
386 
387 			if (s < 0)
388 				continue;
389 
390 			ret = 0;
391 			if (vflag || zflag) {
392 				/* For UDP, make sure we are connected. */
393 				if (uflag) {
394 					if (udptest(s) == -1) {
395 						ret = 1;
396 						continue;
397 					}
398 				}
399 
400 				/* Don't look up port if -n. */
401 				if (nflag)
402 					sv = NULL;
403 				else {
404 					sv = getservbyport(
405 					    ntohs(atoi(portlist[i])),
406 					    uflag ? "udp" : "tcp");
407 				}
408 
409 				(void) fprintf(stderr, "Connection to %s %s "
410 				    "port [%s/%s] succeeded!\n",
411 				    host, portlist[i], uflag ? "udp" : "tcp",
412 				    sv ? sv->s_name : "*");
413 			}
414 			if (!zflag)
415 				readwrite(s);
416 		}
417 	}
418 
419 	if (s)
420 		(void) close(s);
421 
422 	return (ret);
423 }
424 
425 /*
426  * print IP address and (optionally) a port
427  */
428 char *
429 print_addr(char *ntop, size_t ntlen, struct sockaddr *addr, int len, int flags)
430 {
431 	char port[NI_MAXSERV];
432 	int e;
433 
434 	/* print port always as number */
435 	if ((e = getnameinfo(addr, len, ntop, ntlen,
436 	    port, sizeof (port), flags|NI_NUMERICSERV)) != 0) {
437 		return ((char *)gai_strerror(e));
438 	}
439 
440 	(void) snprintf(ntop, ntlen, "%s port %s", ntop, port);
441 
442 	return (ntop);
443 }
444 
445 /*
446  * unix_connect()
447  * Returns a socket connected to a local unix socket. Returns -1 on failure.
448  */
449 int
450 unix_connect(char *path)
451 {
452 	struct sockaddr_un sunaddr;
453 	int s;
454 
455 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
456 		return (-1);
457 
458 	(void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
459 	sunaddr.sun_family = AF_UNIX;
460 
461 	if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
462 	    sizeof (sunaddr.sun_path)) {
463 		(void) close(s);
464 		errno = ENAMETOOLONG;
465 		return (-1);
466 	}
467 	if (connect(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
468 		(void) close(s);
469 		return (-1);
470 	}
471 	return (s);
472 }
473 
474 /*
475  * unix_listen()
476  * Create a unix domain socket, and listen on it.
477  */
478 int
479 unix_listen(char *path)
480 {
481 	struct sockaddr_un sunaddr;
482 	int s;
483 
484 	/* Create unix domain socket. */
485 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
486 		return (-1);
487 
488 	(void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
489 	sunaddr.sun_family = AF_UNIX;
490 
491 	if (strlcpy(sunaddr.sun_path, path, sizeof (sunaddr.sun_path)) >=
492 	    sizeof (sunaddr.sun_path)) {
493 		(void) close(s);
494 		errno = ENAMETOOLONG;
495 		return (-1);
496 	}
497 
498 	if (bind(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
499 		(void) close(s);
500 		return (-1);
501 	}
502 
503 	if (listen(s, 5) < 0) {
504 		(void) close(s);
505 		return (-1);
506 	}
507 	return (s);
508 }
509 
510 /*
511  * remote_connect()
512  * Returns a socket connected to a remote host. Properly binds to a local
513  * port or source address if needed. Returns -1 on failure.
514  */
515 int
516 remote_connect(const char *host, const char *port, struct addrinfo hints)
517 {
518 	struct addrinfo *res, *res0;
519 	int s, error;
520 
521 	if ((error = getaddrinfo(host, port, &hints, &res)))
522 		errx(1, "getaddrinfo: %s", gai_strerror(error));
523 
524 	res0 = res;
525 	do {
526 		if ((s = socket(res0->ai_family, res0->ai_socktype,
527 		    res0->ai_protocol)) < 0) {
528 			warn("failed to create socket");
529 			continue;
530 		}
531 
532 		/* Bind to a local port or source address if specified. */
533 		if (sflag || pflag) {
534 			struct addrinfo ahints, *ares;
535 
536 			(void) memset(&ahints, 0, sizeof (struct addrinfo));
537 			ahints.ai_family = res0->ai_family;
538 			ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
539 			ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
540 			ahints.ai_flags = AI_PASSIVE;
541 			if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
542 				errx(1, "getaddrinfo: %s", gai_strerror(error));
543 
544 			if (bind(s, (struct sockaddr *)ares->ai_addr,
545 			    ares->ai_addrlen) < 0)
546 				errx(1, "bind failed: %s", strerror(errno));
547 			freeaddrinfo(ares);
548 
549 			if (vflag && !lflag) {
550 				if (sflag != NULL)
551 					(void) fprintf(stderr,
552 					    "Using source address: %s\n",
553 					    sflag);
554 				if (pflag != NULL)
555 					(void) fprintf(stderr,
556 					    "Using source port: %s\n", pflag);
557 			}
558 		}
559 
560 		set_common_sockopts(s);
561 
562 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
563 			break;
564 		else if (vflag) {
565 			char ntop[NI_MAXHOST + NI_MAXSERV];
566 			warn("connect to %s [host %s] (%s) failed",
567 			    print_addr(ntop, sizeof (ntop),
568 			    res0->ai_addr, res0->ai_addrlen, NI_NUMERICHOST),
569 			    host, uflag ? "udp" : "tcp");
570 		}
571 
572 		(void) close(s);
573 		s = -1;
574 	} while ((res0 = res0->ai_next) != NULL);
575 
576 	freeaddrinfo(res);
577 
578 	return (s);
579 }
580 
581 /*
582  * local_listen()
583  * Returns a socket listening on a local port, binds to specified source
584  * address. Returns -1 on failure.
585  */
586 int
587 local_listen(char *host, char *port, struct addrinfo hints)
588 {
589 	struct addrinfo *res, *res0;
590 	int s, ret, x = 1;
591 	int error;
592 
593 	/* Allow nodename to be null. */
594 	hints.ai_flags |= AI_PASSIVE;
595 
596 	if ((error = getaddrinfo(host, port, &hints, &res)))
597 		errx(1, "getaddrinfo: %s", gai_strerror(error));
598 
599 	res0 = res;
600 	do {
601 		if ((s = socket(res0->ai_family, res0->ai_socktype,
602 		    res0->ai_protocol)) < 0) {
603 			warn("failed to create socket");
604 			continue;
605 		}
606 
607 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
608 		if (ret == -1)
609 			err(1, NULL);
610 
611 		set_common_sockopts(s);
612 
613 		if (bind(s, (struct sockaddr *)res0->ai_addr,
614 		    res0->ai_addrlen) == 0)
615 			break;
616 
617 		(void) close(s);
618 		s = -1;
619 	} while ((res0 = res0->ai_next) != NULL);
620 
621 	if (!uflag && s != -1) {
622 		if (listen(s, 1) < 0)
623 			err(1, "listen");
624 	}
625 
626 	freeaddrinfo(res);
627 
628 	return (s);
629 }
630 
631 /*
632  * readwrite()
633  * Loop that polls on the network file descriptor and stdin.
634  */
635 void
636 readwrite(int nfd)
637 {
638 	struct pollfd pfd[2];
639 	unsigned char buf[8192];
640 	int n, wfd = fileno(stdin);
641 	int lfd = fileno(stdout);
642 	int plen;
643 
644 	plen = 1024;
645 
646 	/* Setup Network FD */
647 	pfd[0].fd = nfd;
648 	pfd[0].events = POLLIN;
649 
650 	/* Set up STDIN FD. */
651 	pfd[1].fd = wfd;
652 	pfd[1].events = POLLIN;
653 
654 	while (pfd[0].fd != -1) {
655 		if (iflag)
656 			(void) sleep(iflag);
657 
658 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
659 			(void) close(nfd);
660 			err(1, "Polling Error");
661 		}
662 
663 		if (n == 0)
664 			return;
665 
666 		if (pfd[0].revents & (POLLIN|POLLHUP)) {
667 			if ((n = read(nfd, buf, plen)) < 0)
668 				return;
669 			else if (n == 0) {
670 				(void) shutdown(nfd, SHUT_RD);
671 				pfd[0].fd = -1;
672 				pfd[0].events = 0;
673 			} else {
674 				if (tflag)
675 					atelnet(nfd, buf, n);
676 				if (atomicio(vwrite, lfd, buf, n) != n)
677 					return;
678 			}
679 		}
680 
681 		/*
682 		 * handle the case of disconnected pipe: after pipe
683 		 * is closed (indicated by POLLHUP) there may still
684 		 * be some data lingering (POLLIN). After we read
685 		 * the data, only POLLHUP remains, read() returns 0
686 		 * and we are finished.
687 		 */
688 		if (!dflag && (pfd[1].revents & (POLLIN|POLLHUP))) {
689 			if ((n = read(wfd, buf, plen)) < 0)
690 				return;
691 			else if (n == 0) {
692 				(void) shutdown(nfd, SHUT_WR);
693 				pfd[1].fd = -1;
694 				pfd[1].events = 0;
695 			} else {
696 				if (atomicio(vwrite, nfd, buf, n) != n)
697 					return;
698 			}
699 		}
700 	}
701 }
702 
703 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
704 void
705 atelnet(int nfd, unsigned char *buf, unsigned int size)
706 {
707 	unsigned char *p, *end;
708 	unsigned char obuf[4];
709 
710 	end = buf + size;
711 	obuf[0] = '\0';
712 
713 	for (p = buf; p < end; p++) {
714 		if (*p != IAC)
715 			break;
716 
717 		obuf[0] = IAC;
718 		obuf[1] = 0;
719 		p++;
720 		/* refuse all options */
721 		if ((*p == WILL) || (*p == WONT))
722 			obuf[1] = DONT;
723 		if ((*p == DO) || (*p == DONT))
724 			obuf[1] = WONT;
725 		if (obuf[1]) {
726 			p++;
727 			obuf[2] = *p;
728 			obuf[3] = '\0';
729 			if (atomicio(vwrite, nfd, obuf, 3) != 3)
730 				warn("Write Error!");
731 			obuf[0] = '\0';
732 		}
733 	}
734 }
735 
736 /*
737  * build_ports()
738  * Build an array of ports in portlist[], listing each port
739  * that we should try to connect to.
740  */
741 void
742 build_ports(char *p)
743 {
744 	const char *errstr;
745 	char *n;
746 	int hi, lo, cp;
747 	int x = 0;
748 
749 	if ((n = strchr(p, '-')) != NULL) {
750 		if (lflag)
751 			errx(1, "Cannot use -l with multiple ports!");
752 
753 		*n = '\0';
754 		n++;
755 
756 		/* Make sure the ports are in order: lowest->highest. */
757 		hi = strtonum(n, PORT_MIN, PORT_MAX, &errstr);
758 		if (errstr)
759 			errx(1, "port number %s: %s", errstr, n);
760 		lo = strtonum(p, PORT_MIN, PORT_MAX, &errstr);
761 		if (errstr)
762 			errx(1, "port number %s: %s", errstr, p);
763 
764 		if (lo > hi) {
765 			cp = hi;
766 			hi = lo;
767 			lo = cp;
768 		}
769 
770 		/* Load ports sequentially. */
771 		for (cp = lo; cp <= hi; cp++) {
772 			portlist[x] = calloc(1, PORT_MAX_LEN);
773 			if (portlist[x] == NULL)
774 				err(1, NULL);
775 			(void) snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
776 			x++;
777 		}
778 
779 		/* Randomly swap ports. */
780 		if (rflag) {
781 			int y;
782 			char *c;
783 
784 			srandom(time((time_t *)0));
785 
786 			for (x = 0; x <= (hi - lo); x++) {
787 				y = (random() & 0xFFFF) % (hi - lo);
788 				c = portlist[x];
789 				portlist[x] = portlist[y];
790 				portlist[y] = c;
791 			}
792 		}
793 	} else {
794 		hi = strtonum(p, PORT_MIN, PORT_MAX, &errstr);
795 		if (errstr)
796 			errx(1, "port number %s: %s", errstr, p);
797 		portlist[0] = calloc(1, PORT_MAX_LEN);
798 		if (portlist[0] == NULL)
799 			err(1, NULL);
800 		portlist[0] = p;
801 	}
802 }
803 
804 /*
805  * udptest()
806  * Do a few writes to see if the UDP port is there.
807  * XXX - Better way of doing this? Doesn't work for IPv6.
808  * Also fails after around 100 ports checked.
809  */
810 int
811 udptest(int s)
812 {
813 	int i, ret;
814 
815 	for (i = 0; i <= 3; i++) {
816 		if (write(s, "X", 1) == 1)
817 			ret = 1;
818 		else
819 			ret = -1;
820 	}
821 	return (ret);
822 }
823 
824 void
825 set_common_sockopts(int s)
826 {
827 	int x = 1;
828 
829 	if (Dflag) {
830 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof (x)) == -1)
831 			err(1, NULL);
832 	}
833 	if (Tflag != -1) {
834 		if (setsockopt(s, IPPROTO_IP, IP_TOS, &Tflag,
835 		    sizeof (Tflag)) == -1)
836 			err(1, "set IP ToS");
837 	}
838 }
839 
840 int
841 parse_iptos(char *s)
842 {
843 	int tos = -1;
844 
845 	if (strcmp(s, "lowdelay") == 0)
846 		return (IPTOS_LOWDELAY);
847 	if (strcmp(s, "throughput") == 0)
848 		return (IPTOS_THROUGHPUT);
849 	if (strcmp(s, "reliability") == 0)
850 		return (IPTOS_RELIABILITY);
851 
852 	if (sscanf(s, "0x%x", (unsigned int *) &tos) != 1 ||
853 	    tos < 0 || tos > 0xff)
854 		errx(1, "invalid IP Type of Service");
855 	return (tos);
856 }
857 
858 void
859 help(void)
860 {
861 	usage(0);
862 	(void) fprintf(stderr, "\tCommand Summary:\n\
863 	\t-4		Use IPv4\n\
864 	\t-6		Use IPv6\n\
865 	\t-D		Enable the debug socket option\n\
866 	\t-d		Detach from stdin\n\
867 	\t-h		This help text\n\
868 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
869 	\t-k		Keep inbound sockets open for multiple connects\n\
870 	\t-l		Listen mode, for inbound connects\n\
871 	\t-n		Suppress name/port resolutions\n\
872 	\t-P proxyuser\tUsername for proxy authentication\n\
873 	\t-p port\t	Specify local port or listen port\n\
874 	\t-r		Randomize remote ports\n\
875 	\t-s addr\t	Local source address\n\
876 	\t-T ToS\t	Set IP Type of Service\n\
877 	\t-t		Answer TELNET negotiation\n\
878 	\t-U		Use UNIX domain socket\n\
879 	\t-u		UDP mode\n\
880 	\t-v		Verbose\n\
881 	\t-w secs\t	Timeout for connects and final net reads\n\
882 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
883 	\t-x addr[:port]\tSpecify proxy address and port\n\
884 	\t-z		Zero-I/O mode [used for scanning]\n\
885 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
886 	exit(1);
887 }
888 
889 void
890 usage(int ret)
891 {
892 	(void) fprintf(stderr,
893 	    "usage: nc [-46DdhklnrtUuvz] [-i interval] [-P proxy_username]"
894 	    " [-p port]\n");
895 	(void) fprintf(stderr,
896 	    "\t  [-s source_ip_address] [-T ToS] [-w timeout]"
897 	    " [-X proxy_protocol]\n");
898 	(void) fprintf(stderr,
899 	    "\t  [-x proxy_address[:port]] [hostname]"
900 	    " [port[s]]\n");
901 	if (ret)
902 		exit(1);
903 }
904