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