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