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