Annotation of src/usr.bin/nc/netcat.c, Revision 1.50
1.50 ! vincent 1: /* $OpenBSD: netcat.c,v 1.49 2002/05/30 09:37:38 hugh Exp $ */
1.21 ericj 2: /*
3: * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
1.7 deraadt 4: *
1.21 ericj 5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
1.7 deraadt 8: *
1.21 ericj 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.
1.7 deraadt 16: *
1.21 ericj 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: */
1.1 deraadt 28:
1.24 ericj 29: /*
30: * Re-written nc(1) for OpenBSD. Original implementation by
1.21 ericj 31: * *Hobbit* <hobbit@avian.org>.
32: */
1.1 deraadt 33:
1.7 deraadt 34: #include <sys/types.h>
1.21 ericj 35: #include <sys/socket.h>
1.7 deraadt 36: #include <sys/time.h>
1.42 ericj 37: #include <sys/un.h>
1.21 ericj 38:
1.7 deraadt 39: #include <netinet/in.h>
1.21 ericj 40: #include <arpa/telnet.h>
1.29 smart 41:
1.11 ericj 42: #include <err.h>
1.7 deraadt 43: #include <errno.h>
1.21 ericj 44: #include <netdb.h>
45: #include <poll.h>
1.13 ericj 46: #include <stdarg.h>
1.21 ericj 47: #include <stdio.h>
1.1 deraadt 48: #include <stdlib.h>
1.21 ericj 49: #include <string.h>
1.5 art 50: #include <unistd.h>
1.42 ericj 51: #include <fcntl.h>
1.1 deraadt 52:
1.31 ericj 53: #define PORT_MAX 65535
54:
1.21 ericj 55: /* Command Line Options */
56: int iflag; /* Interval Flag */
57: int kflag; /* More than one connect */
58: int lflag; /* Bind to local port */
59: int nflag; /* Dont do name lookup */
60: char *pflag; /* Localport flag */
61: int rflag; /* Random ports flag */
62: char *sflag; /* Source Address */
63: int tflag; /* Telnet Emulation */
64: int uflag; /* UDP - Default to TCP */
65: int vflag; /* Verbosity */
1.34 jakob 66: int xflag; /* Socks proxy */
1.21 ericj 67: int zflag; /* Port Scan Flag */
68:
1.49 hugh 69: int timeout = -1;
1.21 ericj 70: int family = AF_UNSPEC;
1.31 ericj 71: char *portlist[PORT_MAX];
1.21 ericj 72:
1.44 millert 73: ssize_t atomicio(ssize_t (*)(), int, void *, size_t);
1.40 millert 74: void atelnet(int, unsigned char *, unsigned int);
75: void build_ports(char *);
76: void help(void);
77: int local_listen(char *, char *, struct addrinfo);
78: void readwrite(int);
79: int remote_connect(char *, char *, struct addrinfo);
1.45 ericj 80: int socks_connect(char *, char *, struct addrinfo, char *, char *,
1.46 markus 81: struct addrinfo, int);
1.40 millert 82: int udptest(int);
1.42 ericj 83: int unix_connect(char *);
84: int unix_listen(char *);
1.40 millert 85: void usage(int);
1.1 deraadt 86:
1.21 ericj 87: int
1.37 jakob 88: main(int argc, char *argv[])
1.21 ericj 89: {
1.46 markus 90: int ch, s, ret, socksv;
1.26 ericj 91: char *host, *uport, *endp;
1.21 ericj 92: struct addrinfo hints;
1.29 smart 93: struct servent *sv;
1.21 ericj 94: socklen_t len;
95: struct sockaddr *cliaddr;
1.34 jakob 96: char *proxy;
1.45 ericj 97: char *proxyhost = "", *proxyport = NULL;
1.34 jakob 98: struct addrinfo proxyhints;
1.11 ericj 99:
1.29 smart 100: ret = 1;
101: s = 0;
1.46 markus 102: socksv = 5;
1.29 smart 103: host = NULL;
104: uport = NULL;
105: endp = NULL;
106: sv = NULL;
107:
1.46 markus 108: while ((ch = getopt(argc, argv, "46UX:hi:klnp:rs:tuvw:x:z")) != -1) {
1.21 ericj 109: switch (ch) {
110: case '4':
111: family = AF_INET;
112: break;
113: case '6':
114: family = AF_INET6;
115: break;
1.42 ericj 116: case 'U':
117: family = AF_UNIX;
118: break;
1.46 markus 119: case 'X':
120: socksv = (int)strtoul(optarg, &endp, 10);
121: if ((socksv != 4 && socksv != 5) || *endp != '\0')
122: errx(1, "only SOCKS version 4 and 5 supported");
123: break;
1.21 ericj 124: case 'h':
125: help();
126: break;
127: case 'i':
1.26 ericj 128: iflag = (int)strtoul(optarg, &endp, 10);
129: if (iflag < 0 || *endp != '\0')
130: errx(1, "interval cannot be negative");
1.21 ericj 131: break;
132: case 'k':
133: kflag = 1;
134: break;
135: case 'l':
136: lflag = 1;
137: break;
138: case 'n':
139: nflag = 1;
140: break;
141: case 'p':
142: pflag = optarg;
143: break;
144: case 'r':
145: rflag = 1;
146: break;
147: case 's':
148: sflag = optarg;
149: break;
150: case 't':
151: tflag = 1;
152: break;
153: case 'u':
154: uflag = 1;
155: break;
156: case 'v':
157: vflag = 1;
158: break;
1.26 ericj 159: case 'w':
160: timeout = (int)strtoul(optarg, &endp, 10);
161: if (timeout < 0 || *endp != '\0')
162: errx(1, "timeout cannot be negative");
1.49 hugh 163: if (timeout >= (INT_MAX / 1000))
164: errx(1, "timeout too large");
165: timeout *= 1000;
1.21 ericj 166: break;
1.34 jakob 167: case 'x':
168: xflag = 1;
169: proxy = strdup(optarg);
170: break;
1.21 ericj 171: case 'z':
172: zflag = 1;
173: break;
174: default:
175: usage(1);
176: }
177: }
178: argc -= optind;
179: argv += optind;
1.11 ericj 180:
1.21 ericj 181: /* Cruft to make sure options are clean, and used properly. */
1.42 ericj 182: if (argv[0] && !argv[1] && family == AF_UNIX) {
183: if (uflag)
184: errx(1, "cannot use -u and -U");
185: host = argv[0];
186: uport = NULL;
187: } else if (argv[0] && !argv[1]) {
1.21 ericj 188: if (!lflag)
189: usage(1);
190: uport = argv[0];
191: host = NULL;
192: } else if (argv[0] && argv[1]) {
193: host = argv[0];
194: uport = argv[1];
195: } else
196: usage(1);
1.1 deraadt 197:
1.21 ericj 198: if (lflag && sflag)
199: errx(1, "cannot use -s and -l");
200: if (lflag && pflag)
201: errx(1, "cannot use -p and -l");
202: if (lflag && zflag)
1.32 ericj 203: errx(1, "cannot use -z and -l");
1.21 ericj 204: if (!lflag && kflag)
1.32 ericj 205: errx(1, "must use -l with -k");
1.21 ericj 206:
207: /* Initialize addrinfo structure */
1.42 ericj 208: if (family != AF_UNIX) {
209: memset(&hints, 0, sizeof(struct addrinfo));
210: hints.ai_family = family;
211: hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
212: hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
213: if (nflag)
214: hints.ai_flags |= AI_NUMERICHOST;
215: }
1.50 ! vincent 216:
1.1 deraadt 217:
1.34 jakob 218: if (xflag) {
219: if (uflag)
220: errx(1, "no proxy support for UDP mode");
221:
222: if (lflag)
223: errx(1, "no proxy support for listen");
224:
1.42 ericj 225: if (family == AF_UNIX)
226: errx(1, "no proxy support for unix sockets");
227:
1.34 jakob 228: /* XXX IPv6 transport to proxy would probably work */
229: if (family == AF_INET6)
230: errx(1, "no proxy support for IPv6");
231:
232: if (sflag)
233: errx(1, "no proxy support for local source address");
234:
235: proxyhost = strsep(&proxy, ":");
236: proxyport = proxy;
237:
238: memset(&proxyhints, 0, sizeof(struct addrinfo));
239: proxyhints.ai_family = family;
240: proxyhints.ai_socktype = SOCK_STREAM;
241: proxyhints.ai_protocol = IPPROTO_TCP;
242: if (nflag)
243: proxyhints.ai_flags |= AI_NUMERICHOST;
244: }
245:
1.21 ericj 246: if (lflag) {
247: int connfd;
1.27 ericj 248: ret = 0;
1.1 deraadt 249:
1.42 ericj 250: if (family == AF_UNIX)
251: s = unix_listen(host);
252:
1.21 ericj 253: /* Allow only one connection at a time, but stay alive */
254: for (;;) {
1.42 ericj 255: if (family != AF_UNIX)
256: s = local_listen(host, uport, hints);
257: if (s < 0)
1.30 smart 258: err(1, NULL);
1.21 ericj 259: /*
260: * For UDP, we will use recvfrom() initially
261: * to wait for a caller, then use the regular
262: * functions to talk to the caller.
263: */
264: if (uflag) {
1.23 ericj 265: int rv;
1.21 ericj 266: char buf[1024];
267: struct sockaddr_storage z;
268:
269: len = sizeof(z);
1.23 ericj 270: rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
1.37 jakob 271: (struct sockaddr *)&z, &len);
1.23 ericj 272: if (rv < 0)
1.21 ericj 273: errx(1, "%s", strerror(errno));
274:
1.37 jakob 275: rv = connect(s, (struct sockaddr *)&z, len);
1.23 ericj 276: if (rv < 0)
1.21 ericj 277: errx(1, "%s", strerror(errno));
1.1 deraadt 278:
1.21 ericj 279: connfd = s;
280: } else {
281: connfd = accept(s, (struct sockaddr *)&cliaddr,
1.37 jakob 282: &len);
1.21 ericj 283: }
1.1 deraadt 284:
1.21 ericj 285: readwrite(connfd);
286: close(connfd);
1.42 ericj 287: if (family != AF_UNIX)
288: close(s);
1.27 ericj 289:
1.21 ericj 290: if (!kflag)
291: break;
1.11 ericj 292: }
1.42 ericj 293: } else if (family == AF_UNIX) {
294: ret = 0;
295:
296: if ((s = unix_connect(host)) > 0 && !zflag) {
297: readwrite(s);
298: close(s);
299: } else
300: ret = 1;
301:
302: exit(ret);
303:
1.21 ericj 304: } else {
305: int i = 0;
1.6 deraadt 306:
1.21 ericj 307: /* construct the portlist[] array */
308: build_ports(uport);
1.1 deraadt 309:
1.21 ericj 310: /* Cycle through portlist, connecting to each port */
311: for (i = 0; portlist[i] != NULL; i++) {
312: if (s)
313: close(s);
1.34 jakob 314:
315: if (xflag)
316: s = socks_connect(host, portlist[i], hints,
1.46 markus 317: proxyhost, proxyport, proxyhints, socksv);
1.34 jakob 318: else
319: s = remote_connect(host, portlist[i], hints);
320:
321: if (s < 0)
1.21 ericj 322: continue;
1.1 deraadt 323:
1.21 ericj 324: ret = 0;
325: if (vflag || zflag) {
326: /* For UDP, make sure we are connected */
327: if (uflag) {
1.50 ! vincent 328: if (udptest(s) == -1) {
1.21 ericj 329: ret = 1;
330: continue;
331: }
332: }
1.1 deraadt 333:
1.21 ericj 334: /* Don't lookup port if -n */
335: if (nflag)
336: sv = NULL;
337: else {
338: sv = getservbyport(
1.37 jakob 339: ntohs(atoi(portlist[i])),
340: uflag ? "udp" : "tcp");
1.21 ericj 341: }
1.50 ! vincent 342:
1.21 ericj 343: printf("Connection to %s %s port [%s/%s] succeeded!\n",
1.37 jakob 344: host, portlist[i], uflag ? "udp" : "tcp",
345: sv ? sv->s_name : "*");
1.21 ericj 346: }
347: if (!zflag)
348: readwrite(s);
1.7 deraadt 349: }
1.11 ericj 350: }
1.1 deraadt 351:
1.21 ericj 352: if (s)
353: close(s);
354:
355: exit(ret);
1.7 deraadt 356: }
1.1 deraadt 357:
1.11 ericj 358: /*
1.42 ericj 359: * unix_connect()
360: * Return's a socket connected to a local unix socket. Return's -1 on failure.
361: */
362: int
363: unix_connect(char *path)
364: {
365: struct sockaddr_un sun;
366: int s;
367:
368: if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
1.50 ! vincent 369: return (-1);
1.42 ericj 370: (void)fcntl(s, F_SETFD, 1);
371:
372: memset(&sun, 0, sizeof(struct sockaddr_un));
373: sun.sun_family = AF_UNIX;
374: strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
1.50 ! vincent 375: if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
! 376: close(s);
! 377: return (-1);
1.42 ericj 378: }
379: return (s);
1.50 ! vincent 380:
1.42 ericj 381: }
382:
383: /*
384: * unix_listen()
385: * create a unix domain socket, and listen on it.
386: */
387: int
388: unix_listen(char *path)
389: {
390: struct sockaddr_un sun;
391: int s;
392:
393: /* create unix domain socket */
394: if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
395: return (-1);
396:
1.50 ! vincent 397: strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
1.42 ericj 398: sun.sun_family = AF_UNIX;
1.50 ! vincent 399: if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
1.42 ericj 400: close(s);
401: return (-1);
402: }
403:
404: if (listen(s, 5) < 0) {
405: close(s);
406: return (-1);
407: }
408: return (s);
409: }
410:
411: /*
1.21 ericj 412: * remote_connect()
413: * Return's a socket connected to a remote host. Properly bind's to a local
414: * port or source address if needed. Return's -1 on failure.
1.11 ericj 415: */
1.21 ericj 416: int
1.37 jakob 417: remote_connect(char *host, char *port, struct addrinfo hints)
1.21 ericj 418: {
419: struct addrinfo *res, *res0;
420: int s, error;
421:
422: if ((error = getaddrinfo(host, port, &hints, &res)))
423: errx(1, "%s", gai_strerror(error));
424:
425: res0 = res;
426: do {
427: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.37 jakob 428: res0->ai_protocol)) < 0)
1.21 ericj 429: continue;
430:
431: /* Bind to a local port or source address if specified */
432: if (sflag || pflag) {
433: struct addrinfo ahints, *ares;
434:
435: if (!(sflag && pflag)) {
436: if (!sflag)
437: sflag = NULL;
438: else
439: pflag = NULL;
440: }
1.6 deraadt 441:
1.21 ericj 442: memset(&ahints, 0, sizeof(struct addrinfo));
443: ahints.ai_family = res0->ai_family;
444: ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
445: ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
1.25 ericj 446: ahints.ai_flags = AI_PASSIVE;
1.38 jakob 447: if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
1.21 ericj 448: errx(1, "%s", gai_strerror(error));
449:
450: if (bind(s, (struct sockaddr *)ares->ai_addr,
1.50 ! vincent 451: ares->ai_addrlen) < 0) {
1.21 ericj 452: errx(1, "bind failed: %s", strerror(errno));
453: freeaddrinfo(ares);
454: continue;
455: }
456: freeaddrinfo(ares);
1.6 deraadt 457: }
458:
1.21 ericj 459: if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
1.6 deraadt 460: break;
1.34 jakob 461:
1.21 ericj 462: close(s);
463: s = -1;
464: } while ((res0 = res0->ai_next) != NULL);
465:
466: freeaddrinfo(res);
1.1 deraadt 467:
1.21 ericj 468: return (s);
1.7 deraadt 469: }
1.1 deraadt 470:
1.11 ericj 471: /*
1.21 ericj 472: * local_listen()
473: * Return's a socket listening on a local port, binds to specified source
474: * address. Return's -1 on failure.
1.11 ericj 475: */
1.21 ericj 476: int
1.37 jakob 477: local_listen(char *host, char *port, struct addrinfo hints)
1.21 ericj 478: {
479: struct addrinfo *res, *res0;
480: int s, ret, x = 1;
481: int error;
1.6 deraadt 482:
1.21 ericj 483: /* Allow nodename to be null */
484: hints.ai_flags |= AI_PASSIVE;
1.7 deraadt 485:
1.21 ericj 486: /*
487: * In the case of binding to a wildcard address
488: * default to binding to an ipv4 address.
489: */
490: if (host == NULL && hints.ai_family == AF_UNSPEC)
491: hints.ai_family = AF_INET;
1.1 deraadt 492:
1.21 ericj 493: if ((error = getaddrinfo(host, port, &hints, &res)))
494: errx(1, "%s", gai_strerror(error));
1.14 ericj 495:
1.21 ericj 496: res0 = res;
497: do {
498: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.37 jakob 499: res0->ai_protocol)) == 0)
1.21 ericj 500: continue;
1.1 deraadt 501:
1.21 ericj 502: ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
503: if (ret == -1)
1.30 smart 504: err(1, NULL);
1.1 deraadt 505:
1.21 ericj 506: if (bind(s, (struct sockaddr *)res0->ai_addr,
1.37 jakob 507: res0->ai_addrlen) == 0)
1.21 ericj 508: break;
1.1 deraadt 509:
1.21 ericj 510: close(s);
511: s = -1;
512: } while ((res0 = res0->ai_next) != NULL);
1.1 deraadt 513:
1.47 ericj 514: if (!uflag && s != -1) {
1.21 ericj 515: if (listen(s, 1) < 0)
516: errx(1, "%s", strerror(errno));
1.12 ericj 517: }
1.1 deraadt 518:
1.21 ericj 519: freeaddrinfo(res);
1.1 deraadt 520:
1.21 ericj 521: return (s);
1.7 deraadt 522: }
523:
1.11 ericj 524: /*
1.21 ericj 525: * readwrite()
526: * Loop that polls on the network file descriptor and stdin.
1.11 ericj 527: */
1.21 ericj 528: void
1.37 jakob 529: readwrite(int nfd)
1.6 deraadt 530: {
1.21 ericj 531: struct pollfd *pfd;
532: char buf[BUFSIZ];
533: int wfd = fileno(stdin), n, ret;
534: int lfd = fileno(stdout);
535:
536: pfd = malloc(2 * sizeof(struct pollfd));
537:
538: /* Setup Network FD */
539: pfd[0].fd = nfd;
540: pfd[0].events = POLLIN;
541:
542: /* Setup STDIN FD */
543: pfd[1].fd = wfd;
544: pfd[1].events = POLLIN;
545:
546: for (;;) {
547: if (iflag)
548: sleep(iflag);
549:
1.49 hugh 550: if ((n = poll(pfd, 2, timeout)) < 0) {
1.21 ericj 551: close(nfd);
552: close(wfd);
553: free(pfd);
554: errx(1, "Polling Error");
555: }
1.49 hugh 556:
557: if (n == 0)
558: return;
1.21 ericj 559:
560: if (pfd[0].revents & POLLIN) {
561: if ((n = read(nfd, buf, sizeof(buf))) <= 0) {
562: return;
563: } else {
564: if (tflag)
565: atelnet(nfd, buf, n);
566: if ((ret = atomicio(write, lfd, buf, n)) != n)
567: return;
1.6 deraadt 568: }
1.21 ericj 569: }
570:
571: if (pfd[1].revents & POLLIN) {
1.50 ! vincent 572: if ((n = read(wfd, buf, sizeof(buf))) < 0)
1.21 ericj 573: return;
1.50 ! vincent 574: else {
1.21 ericj 575: if((ret = atomicio(write, nfd, buf, n)) != n)
576: return;
1.50 ! vincent 577: }
1.21 ericj 578: }
1.11 ericj 579: }
1.7 deraadt 580: }
1.50 ! vincent 581:
1.24 ericj 582: /* Deal with RFC854 WILL/WONT DO/DONT negotiation */
1.21 ericj 583: void
1.37 jakob 584: atelnet(int nfd, unsigned char *buf, unsigned int size)
1.6 deraadt 585: {
1.28 ericj 586: int ret;
1.24 ericj 587: unsigned char *p, *end;
588: unsigned char obuf[4];
589:
590: end = buf + size;
591: obuf[0] = '\0';
592:
593: for (p = buf; p < end; p++) {
1.21 ericj 594: if (*p != IAC)
1.24 ericj 595: break;
596:
1.25 ericj 597: obuf[0] = IAC;
1.24 ericj 598: p++;
1.50 ! vincent 599: if ((*p == WILL) || (*p == WONT))
1.24 ericj 600: obuf[1] = DONT;
1.50 ! vincent 601: if ((*p == DO) || (*p == DONT))
1.24 ericj 602: obuf[1] = WONT;
603: if (obuf) {
604: p++;
1.11 ericj 605: obuf[2] = *p;
1.24 ericj 606: obuf[3] = '\0';
1.21 ericj 607: if ((ret = atomicio(write , nfd, obuf, 3)) != 3)
608: warnx("Write Error!");
1.24 ericj 609: obuf[0] = '\0';
1.11 ericj 610: }
611: }
1.7 deraadt 612: }
613:
1.11 ericj 614: /*
1.21 ericj 615: * build_ports()
616: * Build an array or ports in portlist[], listing each port
617: * that we should try to connect too.
1.11 ericj 618: */
1.21 ericj 619: void
1.37 jakob 620: build_ports(char *p)
1.6 deraadt 621: {
1.26 ericj 622: char *n, *endp;
1.21 ericj 623: int hi, lo, cp;
624: int x = 0;
625:
626: if ((n = strchr(p, '-')) != NULL) {
627: if (lflag)
628: errx(1, "Cannot use -l with multiple ports!");
629:
630: *n = '\0';
631: n++;
632:
633: /* Make sure the ports are in order: lowest->highest */
1.26 ericj 634: hi = (int)strtoul(n, &endp, 10);
1.31 ericj 635: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 636: errx(1, "port range not valid");
637: lo = (int)strtoul(p, &endp, 10);
1.31 ericj 638: if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
1.26 ericj 639: errx(1, "port range not valid");
1.21 ericj 640:
641: if (lo > hi) {
642: cp = hi;
643: hi = lo;
644: lo = cp;
645: }
646:
647: /* Load ports sequentially */
648: for (cp = lo; cp <= hi; cp++) {
1.33 ericj 649: portlist[x] = calloc(1, PORT_MAX);
1.48 deraadt 650: snprintf(portlist[x], PORT_MAX, "%d", cp);
1.21 ericj 651: x++;
652: }
653:
654: /* Randomly swap ports */
655: if (rflag) {
656: int y;
657: char *c;
658:
659: for (x = 0; x <= (hi - lo); x++) {
660: y = (arc4random() & 0xFFFF) % (hi - lo);
661: c = portlist[x];
662: portlist[x] = portlist[y];
663: portlist[y] = c;
1.6 deraadt 664: }
1.11 ericj 665: }
1.21 ericj 666: } else {
1.26 ericj 667: hi = (int)strtoul(p, &endp, 10);
1.31 ericj 668: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 669: errx(1, "port range not valid");
1.33 ericj 670: portlist[0] = calloc(1, PORT_MAX);
1.21 ericj 671: portlist[0] = p;
1.11 ericj 672: }
1.13 ericj 673: }
674:
675: /*
1.21 ericj 676: * udptest()
677: * Do a few writes to see if the UDP port is there.
678: * XXX - Better way of doing this? Doesn't work for IPv6
679: * Also fails after around 100 ports checked.
1.13 ericj 680: */
1.21 ericj 681: int
1.37 jakob 682: udptest(int s)
1.13 ericj 683: {
1.21 ericj 684: int i, rv, ret;
1.13 ericj 685:
1.21 ericj 686: for (i=0; i <= 3; i++) {
687: if ((rv = write(s, "X", 1)) == 1)
688: ret = 1;
1.14 ericj 689: else
1.21 ericj 690: ret = -1;
1.14 ericj 691: }
1.21 ericj 692: return (ret);
1.7 deraadt 693: }
1.1 deraadt 694:
1.11 ericj 695: void
1.21 ericj 696: help()
1.1 deraadt 697: {
1.21 ericj 698: usage(0);
699: fprintf(stderr, "\tCommand Summary:\n\
700: \t-4 Use IPv4\n\
701: \t-6 Use IPv6\n\
1.42 ericj 702: \t-U Use UNIX domain socket\n\
1.21 ericj 703: \t-h This help text\n\
704: \t-i secs\t Delay interval for lines sent, ports scanned\n\
705: \t-k Keep inbound sockets open for multiple connects\n\
706: \t-l Listen mode, for inbound connects\n\
1.22 jasoni 707: \t-n Suppress name/port resolutions\n\
1.36 jakob 708: \t-p port\t Specify local port for remote connects\n\
1.21 ericj 709: \t-r Randomize remote ports\n\
710: \t-s addr\t Local source address\n\
711: \t-t Answer TELNET negotiation\n\
712: \t-u UDP mode\n\
713: \t-v Verbose\n\
714: \t-w secs\t Timeout for connects and final net reads\n\
1.34 jakob 715: \t-x addr[:port]\tSpecify socks5 proxy address and port\n\
1.21 ericj 716: \t-z Zero-I/O mode [used for scanning]\n\
717: Port numbers can be individual or ranges: lo-hi [inclusive]\n");
718: exit(1);
1.11 ericj 719: }
720:
721: void
1.37 jakob 722: usage(int ret)
1.11 ericj 723: {
1.43 ericj 724: fprintf(stderr, "usage: nc [-46Uhklnrtuvz] [-i interval] [-p source port]\n");
1.36 jakob 725: fprintf(stderr, "\t [-s ip address] [-w timeout] [-x proxy address [:port]]\n");
726: fprintf(stderr, "\t [hostname] [port[s...]]\n");
1.21 ericj 727: if (ret)
728: exit(1);
1.7 deraadt 729: }