xref: /freebsd/contrib/netcat/netcat.c (revision 5c52a79884070364bfc920fb8e492cfac61ec72f)
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  * $FreeBSD$
29  */
30 
31 /*
32  * Re-written nc(1) for OpenBSD. Original implementation by
33  * *Hobbit* <hobbit@avian.org>.
34  */
35 
36 #include <sys/limits.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/time.h>
40 #include <sys/un.h>
41 
42 #include <netinet/in.h>
43 #include <netinet/in_systm.h>
44 #ifdef IPSEC
45 #include <netipsec/ipsec.h>
46 #endif
47 #include <netinet/tcp.h>
48 #include <netinet/ip.h>
49 #include <arpa/telnet.h>
50 
51 #include <err.h>
52 #include <errno.h>
53 #include <netdb.h>
54 #include <poll.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <unistd.h>
60 #include <fcntl.h>
61 #include <limits.h>
62 #include "atomicio.h"
63 
64 #ifndef SUN_LEN
65 #define SUN_LEN(su) \
66 	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
67 #endif
68 
69 #define PORT_MAX	65535
70 #define PORT_MAX_LEN	6
71 
72 /* Command Line Options */
73 int	Eflag;					/* Use IPsec ESP */
74 int	dflag;					/* detached, no stdin */
75 unsigned int iflag;				/* Interval Flag */
76 int	jflag;					/* use jumbo frames if we can */
77 int	kflag;					/* More than one connect */
78 int	lflag;					/* Bind to local port */
79 int	nflag;					/* Don't do name look up */
80 int	oflag;					/* Once only: stop on EOF */
81 int	Oflag;					/* Do not use TCP options */
82 char   *Pflag;					/* Proxy username */
83 char   *pflag;					/* Localport flag */
84 int	rflag;					/* Random ports flag */
85 char   *sflag;					/* Source Address */
86 int	tflag;					/* Telnet Emulation */
87 int	uflag;					/* UDP - Default to TCP */
88 int	vflag;					/* Verbosity */
89 int	xflag;					/* Socks proxy */
90 int	zflag;					/* Port Scan Flag */
91 int	Dflag;					/* sodebug */
92 int	Sflag;					/* TCP MD5 signature option */
93 int	Tflag = -1;				/* IP Type of Service */
94 
95 int timeout = -1;
96 int family = AF_UNSPEC;
97 char *portlist[PORT_MAX+1];
98 
99 void	atelnet(int, unsigned char *, unsigned int);
100 void	build_ports(char *);
101 void	help(void);
102 int	local_listen(char *, char *, struct addrinfo);
103 void	readwrite(int);
104 int	remote_connect(const char *, const char *, struct addrinfo);
105 int	socks_connect(const char *, const char *, struct addrinfo,
106 	    const char *, const char *, struct addrinfo, int, const char *);
107 int	udptest(int);
108 int	unix_connect(char *);
109 int	unix_listen(char *);
110 void	set_common_sockopts(int);
111 int	parse_iptos(char *);
112 void	usage(int);
113 
114 #ifdef IPSEC
115 void	add_ipsec_policy(int, char *);
116 
117 char	*ipsec_policy[2];
118 #endif
119 
120 int
121 main(int argc, char *argv[])
122 {
123 	int ch, s, ret, socksv, ipsec_count;
124 	char *host, *uport;
125 	struct addrinfo hints;
126 	struct servent *sv;
127 	socklen_t len;
128 	struct sockaddr_storage cliaddr;
129 	char *proxy;
130 	const char *errstr, *proxyhost = "", *proxyport = NULL;
131 	struct addrinfo proxyhints;
132 
133 	ret = 1;
134 	ipsec_count = 0;
135 	s = 0;
136 	socksv = 5;
137 	host = NULL;
138 	uport = NULL;
139 	sv = NULL;
140 
141 	while ((ch = getopt(argc, argv,
142 	    "46e:DEdhi:jklnoOP:p:rSs:tT:Uuvw:X:x:z")) != -1) {
143 		switch (ch) {
144 		case '4':
145 			family = AF_INET;
146 			break;
147 		case '6':
148 			family = AF_INET6;
149 			break;
150 		case 'U':
151 			family = AF_UNIX;
152 			break;
153 		case 'X':
154 			if (strcasecmp(optarg, "connect") == 0)
155 				socksv = -1; /* HTTP proxy CONNECT */
156 			else if (strcmp(optarg, "4") == 0)
157 				socksv = 4; /* SOCKS v.4 */
158 			else if (strcmp(optarg, "5") == 0)
159 				socksv = 5; /* SOCKS v.5 */
160 			else
161 				errx(1, "unsupported proxy protocol");
162 			break;
163 		case 'd':
164 			dflag = 1;
165 			break;
166 		case 'e':
167 #ifdef IPSEC
168 			ipsec_policy[ipsec_count++ % 2] = optarg;
169 #else
170 			errx(1, "IPsec support unavailable.");
171 #endif
172 			break;
173 		case 'E':
174 #ifdef IPSEC
175 			ipsec_policy[0] = "in  ipsec esp/transport//require";
176 			ipsec_policy[1] = "out ipsec esp/transport//require";
177 #else
178 			errx(1, "IPsec support unavailable.");
179 #endif
180 			break;
181 		case 'h':
182 			help();
183 			break;
184 		case 'i':
185 			iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
186 			if (errstr)
187 				errx(1, "interval %s: %s", errstr, optarg);
188 			break;
189 #ifdef SO_JUMBO
190 		case 'j':
191 			jflag = 1;
192 			break;
193 #endif
194 		case 'k':
195 			kflag = 1;
196 			break;
197 		case 'l':
198 			lflag = 1;
199 			break;
200 		case 'n':
201 			nflag = 1;
202 			break;
203 		case 'o':
204 			oflag = 1;
205 			break;
206 		case 'O':
207 			Oflag = 1;
208 			break;
209 		case 'P':
210 			Pflag = optarg;
211 			break;
212 		case 'p':
213 			pflag = optarg;
214 			break;
215 		case 'r':
216 			rflag = 1;
217 			break;
218 		case 's':
219 			sflag = optarg;
220 			break;
221 		case 't':
222 			tflag = 1;
223 			break;
224 		case 'u':
225 			uflag = 1;
226 			break;
227 		case 'v':
228 			vflag = 1;
229 			break;
230 		case 'w':
231 			timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
232 			if (errstr)
233 				errx(1, "timeout %s: %s", errstr, optarg);
234 			timeout *= 1000;
235 			break;
236 		case 'x':
237 			xflag = 1;
238 			if ((proxy = strdup(optarg)) == NULL)
239 				err(1, NULL);
240 			break;
241 		case 'z':
242 			zflag = 1;
243 			break;
244 		case 'D':
245 			Dflag = 1;
246 			break;
247 		case 'S':
248 			Sflag = 1;
249 			break;
250 		case 'T':
251 			Tflag = parse_iptos(optarg);
252 			break;
253 		default:
254 			usage(1);
255 		}
256 	}
257 	argc -= optind;
258 	argv += optind;
259 
260 	/* Cruft to make sure options are clean, and used properly. */
261 	if (argv[0] && !argv[1] && family == AF_UNIX) {
262 		if (uflag)
263 			errx(1, "cannot use -u and -U");
264 		host = argv[0];
265 		uport = NULL;
266 	} else if (argv[0] && !argv[1]) {
267 		if  (!lflag)
268 			usage(1);
269 		uport = argv[0];
270 		host = NULL;
271 	} else if (argv[0] && argv[1]) {
272 		host = argv[0];
273 		uport = argv[1];
274 	} else
275 		usage(1);
276 
277 	if (lflag && sflag)
278 		errx(1, "cannot use -s and -l");
279 	if (lflag && pflag)
280 		errx(1, "cannot use -p and -l");
281 	if (lflag && zflag)
282 		errx(1, "cannot use -z and -l");
283 	if (!lflag && kflag)
284 		errx(1, "must use -l with -k");
285 
286 	/* Initialize addrinfo structure. */
287 	if (family != AF_UNIX) {
288 		memset(&hints, 0, sizeof(struct addrinfo));
289 		hints.ai_family = family;
290 		hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
291 		hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
292 		if (nflag)
293 			hints.ai_flags |= AI_NUMERICHOST;
294 	}
295 
296 	if (xflag) {
297 		if (uflag)
298 			errx(1, "no proxy support for UDP mode");
299 
300 		if (lflag)
301 			errx(1, "no proxy support for listen");
302 
303 		if (family == AF_UNIX)
304 			errx(1, "no proxy support for unix sockets");
305 
306 		/* XXX IPv6 transport to proxy would probably work */
307 		if (family == AF_INET6)
308 			errx(1, "no proxy support for IPv6");
309 
310 		if (sflag)
311 			errx(1, "no proxy support for local source address");
312 
313 		proxyhost = strsep(&proxy, ":");
314 		proxyport = proxy;
315 
316 		memset(&proxyhints, 0, sizeof(struct addrinfo));
317 		proxyhints.ai_family = family;
318 		proxyhints.ai_socktype = SOCK_STREAM;
319 		proxyhints.ai_protocol = IPPROTO_TCP;
320 		if (nflag)
321 			proxyhints.ai_flags |= AI_NUMERICHOST;
322 	}
323 
324 	if (lflag) {
325 		int connfd;
326 		ret = 0;
327 
328 		if (family == AF_UNIX)
329 			s = unix_listen(host);
330 
331 		/* Allow only one connection at a time, but stay alive. */
332 		for (;;) {
333 			if (family != AF_UNIX)
334 				s = local_listen(host, uport, hints);
335 			if (s < 0)
336 				err(1, NULL);
337 			/*
338 			 * For UDP, we will use recvfrom() initially
339 			 * to wait for a caller, then use the regular
340 			 * functions to talk to the caller.
341 			 */
342 			if (uflag) {
343 				int rv, plen;
344 				char buf[8192];
345 				struct sockaddr_storage z;
346 
347 				len = sizeof(z);
348 				plen = jflag ? 8192 : 1024;
349 				rv = recvfrom(s, buf, plen, MSG_PEEK,
350 				    (struct sockaddr *)&z, &len);
351 				if (rv < 0)
352 					err(1, "recvfrom");
353 
354 				rv = connect(s, (struct sockaddr *)&z, len);
355 				if (rv < 0)
356 					err(1, "connect");
357 
358 				connfd = s;
359 			} else {
360 				len = sizeof(cliaddr);
361 				connfd = accept(s, (struct sockaddr *)&cliaddr,
362 				    &len);
363 			}
364 
365 			readwrite(connfd);
366 			close(connfd);
367 			if (family != AF_UNIX)
368 				close(s);
369 
370 			if (!kflag)
371 				break;
372 		}
373 	} else if (family == AF_UNIX) {
374 		ret = 0;
375 
376 		if ((s = unix_connect(host)) > 0 && !zflag) {
377 			readwrite(s);
378 			close(s);
379 		} else
380 			ret = 1;
381 
382 		exit(ret);
383 
384 	} else {
385 		int i = 0;
386 
387 		/* Construct the portlist[] array. */
388 		build_ports(uport);
389 
390 		/* Cycle through portlist, connecting to each port. */
391 		for (i = 0; portlist[i] != NULL; i++) {
392 			if (s)
393 				close(s);
394 
395 			if (xflag)
396 				s = socks_connect(host, portlist[i], hints,
397 				    proxyhost, proxyport, proxyhints, socksv,
398 				    Pflag);
399 			else
400 				s = remote_connect(host, portlist[i], hints);
401 
402 			if (s < 0)
403 				continue;
404 
405 			ret = 0;
406 			if (vflag || zflag) {
407 				/* For UDP, make sure we are connected. */
408 				if (uflag) {
409 					if (udptest(s) == -1) {
410 						ret = 1;
411 						continue;
412 					}
413 				}
414 
415 				/* Don't look up port if -n. */
416 				if (nflag)
417 					sv = NULL;
418 				else {
419 					sv = getservbyport(
420 					    ntohs(atoi(portlist[i])),
421 					    uflag ? "udp" : "tcp");
422 				}
423 
424 				printf("Connection to %s %s port [%s/%s] succeeded!\n",
425 				    host, portlist[i], uflag ? "udp" : "tcp",
426 				    sv ? sv->s_name : "*");
427 			}
428 			if (!zflag)
429 				readwrite(s);
430 		}
431 	}
432 
433 	if (s)
434 		close(s);
435 
436 	exit(ret);
437 }
438 
439 /*
440  * unix_connect()
441  * Returns a socket connected to a local unix socket. Returns -1 on failure.
442  */
443 int
444 unix_connect(char *path)
445 {
446 	struct sockaddr_un sun;
447 	int s;
448 
449 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
450 		return (-1);
451 	(void)fcntl(s, F_SETFD, 1);
452 
453 	memset(&sun, 0, sizeof(struct sockaddr_un));
454 	sun.sun_family = AF_UNIX;
455 
456 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
457 	    sizeof(sun.sun_path)) {
458 		close(s);
459 		errno = ENAMETOOLONG;
460 		return (-1);
461 	}
462 	if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
463 		close(s);
464 		return (-1);
465 	}
466 	return (s);
467 
468 }
469 
470 /*
471  * unix_listen()
472  * Create a unix domain socket, and listen on it.
473  */
474 int
475 unix_listen(char *path)
476 {
477 	struct sockaddr_un sun;
478 	int s;
479 
480 	/* Create unix domain socket. */
481 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
482 		return (-1);
483 
484 	memset(&sun, 0, sizeof(struct sockaddr_un));
485 	sun.sun_family = AF_UNIX;
486 
487 	if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
488 	    sizeof(sun.sun_path)) {
489 		close(s);
490 		errno = ENAMETOOLONG;
491 		return (-1);
492 	}
493 
494 	if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
495 		close(s);
496 		return (-1);
497 	}
498 
499 	if (listen(s, 5) < 0) {
500 		close(s);
501 		return (-1);
502 	}
503 	return (s);
504 }
505 
506 /*
507  * remote_connect()
508  * Returns a socket connected to a remote host. Properly binds to a local
509  * port or source address if needed. Returns -1 on failure.
510  */
511 int
512 remote_connect(const char *host, const char *port, struct addrinfo hints)
513 {
514 	struct addrinfo *res, *res0;
515 	int s, error;
516 
517 	if ((error = getaddrinfo(host, port, &hints, &res)))
518 		errx(1, "getaddrinfo: %s", gai_strerror(error));
519 
520 	res0 = res;
521 	do {
522 		if ((s = socket(res0->ai_family, res0->ai_socktype,
523 		    res0->ai_protocol)) < 0)
524 			continue;
525 #ifdef IPSEC
526 		if (ipsec_policy[0] != NULL)
527 			add_ipsec_policy(s, ipsec_policy[0]);
528 		if (ipsec_policy[1] != NULL)
529 			add_ipsec_policy(s, ipsec_policy[1]);
530 #endif
531 
532 		/* Bind to a local port or source address if specified. */
533 		if (sflag || pflag) {
534 			struct addrinfo ahints, *ares;
535 
536 			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 
550 		set_common_sockopts(s);
551 
552 		if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
553 			break;
554 		else if (vflag)
555 			warn("connect to %s port %s (%s) failed", host, port,
556 			    uflag ? "udp" : "tcp");
557 
558 		close(s);
559 		s = -1;
560 	} while ((res0 = res0->ai_next) != NULL);
561 
562 	freeaddrinfo(res);
563 
564 	return (s);
565 }
566 
567 /*
568  * local_listen()
569  * Returns a socket listening on a local port, binds to specified source
570  * address. Returns -1 on failure.
571  */
572 int
573 local_listen(char *host, char *port, struct addrinfo hints)
574 {
575 	struct addrinfo *res, *res0;
576 	int s, ret, x = 1;
577 	int error;
578 
579 	/* Allow nodename to be null. */
580 	hints.ai_flags |= AI_PASSIVE;
581 
582 	/*
583 	 * In the case of binding to a wildcard address
584 	 * default to binding to an ipv4 address.
585 	 */
586 	if (host == NULL && hints.ai_family == AF_UNSPEC)
587 		hints.ai_family = AF_INET;
588 
589 	if ((error = getaddrinfo(host, port, &hints, &res)))
590 		errx(1, "getaddrinfo: %s", gai_strerror(error));
591 
592 	res0 = res;
593 	do {
594 		if ((s = socket(res0->ai_family, res0->ai_socktype,
595 		    res0->ai_protocol)) < 0)
596 			continue;
597 
598 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
599 		if (ret == -1)
600 			err(1, NULL);
601 #ifdef IPSEC
602 		if (ipsec_policy[0] != NULL)
603 			add_ipsec_policy(s, ipsec_policy[0]);
604 		if (ipsec_policy[1] != NULL)
605 			add_ipsec_policy(s, ipsec_policy[1]);
606 #endif
607 		if (Oflag) {
608 			if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
609 			    &Oflag, sizeof(Oflag)) == -1)
610 				err(1, "disable TCP options");
611 		}
612 
613 		if (bind(s, (struct sockaddr *)res0->ai_addr,
614 		    res0->ai_addrlen) == 0)
615 			break;
616 
617 		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 = jflag ? 8192 : 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 			sleep(iflag);
657 
658 		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
659 			close(nfd);
660 			err(1, "Polling Error");
661 		}
662 
663 		if (n == 0)
664 			return;
665 
666 		if (pfd[0].revents & POLLIN) {
667 			if ((n = read(nfd, buf, plen)) < 0)
668 				return;
669 			else if (n == 0) {
670 				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 		if (!dflag && pfd[1].revents & POLLIN) {
682 			if ((n = read(wfd, buf, plen)) < 0 ||
683 			    (oflag && n == 0)) {
684 				return;
685 			} else if (n == 0) {
686 				shutdown(nfd, SHUT_WR);
687 				pfd[1].fd = -1;
688 				pfd[1].events = 0;
689 			} else {
690 				if (atomicio(vwrite, nfd, buf, n) != n)
691 					return;
692 			}
693 		}
694 	}
695 }
696 
697 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
698 void
699 atelnet(int nfd, unsigned char *buf, unsigned int size)
700 {
701 	unsigned char *p, *end;
702 	unsigned char obuf[4];
703 
704 	end = buf + size;
705 	obuf[0] = '\0';
706 
707 	for (p = buf; p < end; p++) {
708 		if (*p != IAC)
709 			break;
710 
711 		obuf[0] = IAC;
712 		p++;
713 		if ((*p == WILL) || (*p == WONT))
714 			obuf[1] = DONT;
715 		if ((*p == DO) || (*p == DONT))
716 			obuf[1] = WONT;
717 		if (obuf) {
718 			p++;
719 			obuf[2] = *p;
720 			obuf[3] = '\0';
721 			if (atomicio(vwrite, nfd, obuf, 3) != 3)
722 				warn("Write Error!");
723 			obuf[0] = '\0';
724 		}
725 	}
726 }
727 
728 /*
729  * build_ports()
730  * Build an array or ports in portlist[], listing each port
731  * that we should try to connect to.
732  */
733 void
734 build_ports(char *p)
735 {
736 	const char *errstr;
737 	char *n;
738 	int hi, lo, cp;
739 	int x = 0;
740 
741 	if ((n = strchr(p, '-')) != NULL) {
742 		if (lflag)
743 			errx(1, "Cannot use -l with multiple ports!");
744 
745 		*n = '\0';
746 		n++;
747 
748 		/* Make sure the ports are in order: lowest->highest. */
749 		hi = strtonum(n, 1, PORT_MAX, &errstr);
750 		if (errstr)
751 			errx(1, "port number %s: %s", errstr, n);
752 		lo = strtonum(p, 1, PORT_MAX, &errstr);
753 		if (errstr)
754 			errx(1, "port number %s: %s", errstr, p);
755 
756 		if (lo > hi) {
757 			cp = hi;
758 			hi = lo;
759 			lo = cp;
760 		}
761 
762 		/* Load ports sequentially. */
763 		for (cp = lo; cp <= hi; cp++) {
764 			portlist[x] = calloc(1, PORT_MAX_LEN);
765 			if (portlist[x] == NULL)
766 				err(1, NULL);
767 			snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
768 			x++;
769 		}
770 
771 		/* Randomly swap ports. */
772 		if (rflag) {
773 			int y;
774 			char *c;
775 
776 			for (x = 0; x <= (hi - lo); x++) {
777 				y = (arc4random() & 0xFFFF) % (hi - lo);
778 				c = portlist[x];
779 				portlist[x] = portlist[y];
780 				portlist[y] = c;
781 			}
782 		}
783 	} else {
784 		hi = strtonum(p, 1, PORT_MAX, &errstr);
785 		if (errstr)
786 			errx(1, "port number %s: %s", errstr, p);
787 		portlist[0] = calloc(1, PORT_MAX_LEN);
788 		if (portlist[0] == NULL)
789 			err(1, NULL);
790 		portlist[0] = p;
791 	}
792 }
793 
794 /*
795  * udptest()
796  * Do a few writes to see if the UDP port is there.
797  * XXX - Better way of doing this? Doesn't work for IPv6.
798  * Also fails after around 100 ports checked.
799  */
800 int
801 udptest(int s)
802 {
803 	int i, ret;
804 
805 	for (i = 0; i <= 3; i++) {
806 		if (write(s, "X", 1) == 1)
807 			ret = 1;
808 		else
809 			ret = -1;
810 	}
811 	return (ret);
812 }
813 
814 void
815 set_common_sockopts(int s)
816 {
817 	int x = 1;
818 
819 	if (Sflag) {
820 		if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
821 			&x, sizeof(x)) == -1)
822 			err(1, NULL);
823 	}
824 	if (Dflag) {
825 		if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
826 			&x, sizeof(x)) == -1)
827 			err(1, NULL);
828 	}
829 #ifdef SO_JUMBO
830 	if (jflag) {
831 		if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
832 			&x, sizeof(x)) == -1)
833 			err(1, NULL);
834 	}
835 #endif
836 	if (Tflag != -1) {
837 		if (setsockopt(s, IPPROTO_IP, IP_TOS,
838 		    &Tflag, sizeof(Tflag)) == -1)
839 			err(1, "set IP ToS");
840 	}
841 	if (Oflag) {
842 		if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
843 		    &Oflag, sizeof(Oflag)) == -1)
844 			err(1, "disable TCP options");
845 	}
846 }
847 
848 int
849 parse_iptos(char *s)
850 {
851 	int tos = -1;
852 
853 	if (strcmp(s, "lowdelay") == 0)
854 		return (IPTOS_LOWDELAY);
855 	if (strcmp(s, "throughput") == 0)
856 		return (IPTOS_THROUGHPUT);
857 	if (strcmp(s, "reliability") == 0)
858 		return (IPTOS_RELIABILITY);
859 
860 	if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
861 		errx(1, "invalid IP Type of Service");
862 	return (tos);
863 }
864 
865 void
866 help(void)
867 {
868 	usage(0);
869 	fprintf(stderr, "\tCommand Summary:\n\
870 	\t-4		Use IPv4\n\
871 	\t-6		Use IPv6\n\
872 	\t-D		Enable the debug socket option\n\
873 	\t-d		Detach from stdin\n");
874 #ifdef IPSEC
875 	fprintf(stderr, "\
876 	\t-E		Use IPsec ESP\n\
877 	\t-e policy	Use specified IPsec policy\n");
878 #endif
879 	fprintf(stderr, "\
880 	\t-h		This help text\n\
881 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
882 	\t-k		Keep inbound sockets open for multiple connects\n\
883 	\t-l		Listen mode, for inbound connects\n\
884 	\t-n		Suppress name/port resolutions\n\
885 	\t-O		Disable TCP options\n\
886 	\t-o		Terminate on EOF on input\n\
887 	\t-P proxyuser\tUsername for proxy authentication\n\
888 	\t-p port\t	Specify local port for remote connects\n\
889 	\t-r		Randomize remote ports\n\
890 	\t-S		Enable the TCP MD5 signature option\n\
891 	\t-s addr\t	Local source address\n\
892 	\t-T ToS\t	Set IP Type of Service\n\
893 	\t-t		Answer TELNET negotiation\n\
894 	\t-U		Use UNIX domain socket\n\
895 	\t-u		UDP mode\n\
896 	\t-v		Verbose\n\
897 	\t-w secs\t	Timeout for connects and final net reads\n\
898 	\t-X proto	Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
899 	\t-x addr[:port]\tSpecify proxy address and port\n\
900 	\t-z		Zero-I/O mode [used for scanning]\n\
901 	Port numbers can be individual or ranges: lo-hi [inclusive]\n");
902 #ifdef IPSEC
903 	fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
904 #endif
905 	exit(1);
906 }
907 
908 #ifdef IPSEC
909 void
910 add_ipsec_policy(int s, char *policy)
911 {
912 	char *raw;
913 	int e;
914 
915 	raw = ipsec_set_policy(policy, strlen(policy));
916 	if (raw == NULL)
917 		errx(1, "ipsec_set_policy `%s': %s", policy,
918 		     ipsec_strerror());
919 	e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
920 			ipsec_get_policylen(raw));
921 	if (e < 0)
922 		err(1, "ipsec policy cannot be configured");
923 	free(raw);
924 	if (vflag)
925 		fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
926 	return;
927 }
928 #endif /* IPSEC */
929 
930 void
931 usage(int ret)
932 {
933 #ifdef IPSEC
934 	fprintf(stderr, "usage: nc [-46DdEhklnOorStUuvz] [-e policy] [-i interval] [-P proxy_username] [-p source_port]\n");
935 #else
936 	fprintf(stderr, "usage: nc [-46DdhklnOorStUuvz] [-i interval] [-P proxy_username] [-p source_port]\n");
937 #endif
938 	fprintf(stderr, "\t  [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol]\n");
939 	fprintf(stderr, "\t  [-x proxy_address[:port]] [hostname] [port[s]]\n");
940 	if (ret)
941 		exit(1);
942 }
943