8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / nc / netcat.c
blob435597be96fe89b605f462f2550fa0426dd24e0a
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>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
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.
30 * Re-written nc(1) for OpenBSD. Original implementation by
31 * *Hobbit* <hobbit@avian.org>.
35 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
36 * Use is subject to license terms.
40 * Portions Copyright 2008 Erik Trauschke
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <sys/time.h>
46 #include <sys/un.h>
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>
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>
67 #include "atomicio.h"
69 #ifndef SUN_LEN
70 #define SUN_LEN(su) \
71 (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path))
72 #endif
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 */
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 */
98 int timeout = -1;
99 int family = AF_UNSPEC;
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.
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;
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);
129 main(int argc, char *argv[])
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];
141 ret = 1;
142 s = -1;
143 socksv = 5;
144 host = NULL;
145 uport = NULL;
146 sv = NULL;
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);
236 argc -= optind;
237 argv += optind;
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);
260 if (argc > 2)
261 usage(1);
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;
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");
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;
291 if (xflag) {
292 if (uflag)
293 errx(1, "no proxy support for UDP mode");
295 if (lflag)
296 errx(1, "no proxy support for listen");
298 if (family == AF_UNIX)
299 errx(1, "no proxy support for unix sockets");
301 if (family == AF_INET6)
302 errx(1, "no proxy support for IPv6");
304 if (sflag)
305 errx(1, "no proxy support for local source address");
307 if ((proxyhost = strtok(proxy, ":")) == NULL)
308 errx(1, "missing port specification");
309 proxyport = strtok(NULL, ":");
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;
319 if (lflag) {
320 int connfd;
321 ret = 0;
323 if (family == AF_UNIX) {
324 if (host == NULL)
325 usage(1);
326 s = unix_listen(host);
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);
339 if (s < 0)
340 err(1, NULL);
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.
346 if (uflag) {
347 int rv, plen;
348 char buf[8192];
349 struct sockaddr_storage z;
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");
358 rv = connect(s, (struct sockaddr *)&z, len);
359 if (rv < 0)
360 err(1, "connect");
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));
377 readwrite(connfd);
378 (void) close(connfd);
379 if (family != AF_UNIX)
380 (void) close(s);
382 if (!kflag)
383 break;
385 } else if (family == AF_UNIX) {
386 ret = 0;
388 if ((s = unix_connect(host)) > 0 && !zflag) {
389 readwrite(s);
390 (void) close(s);
391 } else
392 ret = 1;
394 exit(ret);
396 } else { /* AF_INET or AF_INET6 */
397 int i;
399 /* Construct the portlist. */
400 build_ports(uport);
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]);
407 if (s != -1)
408 (void) close(s);
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);
417 if (s < 0)
418 continue;
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;
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");
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 : "*");
444 if (!zflag)
445 readwrite(s);
447 free(ports.list);
450 if (s != -1)
451 (void) close(s);
453 return (ret);
457 * print IP address and (optionally) a port
459 char *
460 print_addr(char *ntop, size_t ntlen, struct sockaddr *addr, int len, int flags)
462 char port[NI_MAXSERV];
463 int e;
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));
471 (void) snprintf(ntop, ntlen, "%s port %s", ntop, port);
473 return (ntop);
477 * unix_connect()
478 * Returns a socket connected to a local unix socket. Returns -1 on failure.
481 unix_connect(char *path)
483 struct sockaddr_un sunaddr;
484 int s;
486 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
487 return (-1);
489 (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
490 sunaddr.sun_family = AF_UNIX;
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);
498 if (connect(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
499 (void) close(s);
500 return (-1);
502 return (s);
506 * unix_listen()
507 * Create a unix domain socket, and listen on it.
510 unix_listen(char *path)
512 struct sockaddr_un sunaddr;
513 int s;
515 /* Create unix domain socket. */
516 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
517 return (-1);
519 (void) memset(&sunaddr, 0, sizeof (struct sockaddr_un));
520 sunaddr.sun_family = AF_UNIX;
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);
529 if (bind(s, (struct sockaddr *)&sunaddr, SUN_LEN(&sunaddr)) < 0) {
530 (void) close(s);
531 return (-1);
534 if (listen(s, 5) < 0) {
535 (void) close(s);
536 return (-1);
538 return (s);
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.
547 remote_connect(const char *host, const char *port, struct addrinfo hints)
549 struct addrinfo *res, *res0;
550 int s, error;
552 if ((error = getaddrinfo(host, port, &hints, &res)))
553 errx(1, "getaddrinfo: %s", gai_strerror(error));
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;
563 /* Bind to a local port or source address if specified. */
564 if (sflag || pflag) {
565 struct addrinfo ahints, *ares;
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));
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);
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);
591 set_common_sockopts(s);
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");
603 (void) close(s);
604 s = -1;
605 } while ((res0 = res0->ai_next) != NULL);
607 freeaddrinfo(res);
609 return (s);
613 * local_listen()
614 * Returns a socket listening on a local port, binds to specified source
615 * address. Returns -1 on failure.
618 local_listen(char *host, char *port, struct addrinfo hints)
620 struct addrinfo *res, *res0;
621 int s, ret, x = 1;
622 int error;
624 /* Allow nodename to be null. */
625 hints.ai_flags |= AI_PASSIVE;
627 if ((error = getaddrinfo(host, port, &hints, &res)))
628 errx(1, "getaddrinfo: %s", gai_strerror(error));
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;
638 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x));
639 if (ret == -1)
640 err(1, NULL);
642 set_common_sockopts(s);
644 if (bind(s, (struct sockaddr *)res0->ai_addr,
645 res0->ai_addrlen) == 0)
646 break;
648 (void) close(s);
649 s = -1;
650 } while ((res0 = res0->ai_next) != NULL);
652 if (!uflag && s != -1) {
653 if (listen(s, 1) < 0)
654 err(1, "listen");
657 freeaddrinfo(res);
659 return (s);
663 * readwrite()
664 * Loop that polls on the network file descriptor and stdin.
666 void
667 readwrite(int nfd)
669 struct pollfd pfd[2];
670 unsigned char buf[8192];
671 int n, wfd = fileno(stdin);
672 int lfd = fileno(stdout);
673 int plen;
675 plen = 1024;
677 /* Setup Network FD */
678 pfd[0].fd = nfd;
679 pfd[0].events = POLLIN;
681 /* Set up STDIN FD. */
682 pfd[1].fd = wfd;
683 pfd[1].events = POLLIN;
685 while (pfd[0].fd != -1) {
686 if (iflag)
687 (void) sleep(iflag);
689 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
690 (void) close(nfd);
691 err(1, "Polling Error");
694 if (n == 0)
695 return;
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;
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.
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;
734 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
735 void
736 atelnet(int nfd, unsigned char *buf, unsigned int size)
738 unsigned char *p, *end;
739 unsigned char obuf[4];
741 end = buf + size;
742 obuf[0] = '\0';
744 for (p = buf; p < end; p++) {
745 if (*p != IAC)
746 break;
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';
768 * build_ports()
769 * Build an array of ports in ports.list[], listing each port
770 * that we should try to connect to.
772 void
773 build_ports(char *p)
775 const char *errstr;
776 const char *token;
777 char *n;
778 int lo, hi, cp;
779 int i;
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;
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");
794 /* check if it is a range */
795 if ((n = strchr(token, '-')) != NULL)
796 *n++ = '\0';
798 lo = strtonum(token, PORT_MIN, PORT_MAX, &errstr);
799 if (errstr)
800 errx(1, "port number %s: %s", errstr, token);
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;
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.
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);
828 /* Load ports sequentially. */
829 for (i = lo; i <= hi; i++)
830 ports.list[ports.numports++] = i;
833 /* Randomly swap ports. */
834 if (rflag) {
835 int y;
836 uint16_t u;
838 if (ports.numports < 2) {
839 warnx("can not swap %d port randomly",
840 ports.numports);
841 return;
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;
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.
860 udptest(int s)
862 int i, ret;
864 for (i = 0; i <= 3; i++) {
865 if (write(s, "X", 1) == 1)
866 ret = 1;
867 else
868 ret = -1;
870 return (ret);
873 void
874 set_common_sockopts(int s)
876 int x = 1;
878 if (Dflag) {
879 if (setsockopt(s, SOL_SOCKET, SO_DEBUG, &x, sizeof (x)) == -1)
880 err(1, NULL);
882 if (Tflag != -1) {
883 if (setsockopt(s, IPPROTO_IP, IP_TOS, &Tflag,
884 sizeof (Tflag)) == -1)
885 err(1, "set IP ToS");
890 parse_iptos(char *s)
892 int tos = -1;
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);
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);
907 void
908 help(void)
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);
939 void
940 usage(int ret)
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);