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