Annotation of src/usr.bin/nc/netcat.c, Revision 1.47
1.47 ! ericj 1: /* $OpenBSD: netcat.c,v 1.46 2002/02/28 18:05:36 markus 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:
69: int timeout;
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.21 ericj 163: break;
1.34 jakob 164: case 'x':
165: xflag = 1;
166: proxy = strdup(optarg);
167: break;
1.21 ericj 168: case 'z':
169: zflag = 1;
170: break;
171: default:
172: usage(1);
173: }
174: }
175: argc -= optind;
176: argv += optind;
1.11 ericj 177:
1.21 ericj 178: /* Cruft to make sure options are clean, and used properly. */
1.42 ericj 179: if (argv[0] && !argv[1] && family == AF_UNIX) {
180: if (uflag)
181: errx(1, "cannot use -u and -U");
182: host = argv[0];
183: uport = NULL;
184: } else if (argv[0] && !argv[1]) {
1.21 ericj 185: if (!lflag)
186: usage(1);
187: uport = argv[0];
188: host = NULL;
189: } else if (argv[0] && argv[1]) {
190: host = argv[0];
191: uport = argv[1];
192: } else
193: usage(1);
1.1 deraadt 194:
1.21 ericj 195: if (lflag && sflag)
196: errx(1, "cannot use -s and -l");
197: if (lflag && pflag)
198: errx(1, "cannot use -p and -l");
199: if (lflag && zflag)
1.32 ericj 200: errx(1, "cannot use -z and -l");
1.21 ericj 201: if (!lflag && kflag)
1.32 ericj 202: errx(1, "must use -l with -k");
1.21 ericj 203:
204: /* Initialize addrinfo structure */
1.42 ericj 205: if (family != AF_UNIX) {
206: memset(&hints, 0, sizeof(struct addrinfo));
207: hints.ai_family = family;
208: hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
209: hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
210: if (nflag)
211: hints.ai_flags |= AI_NUMERICHOST;
212: }
213:
1.1 deraadt 214:
1.34 jakob 215: if (xflag) {
216: if (uflag)
217: errx(1, "no proxy support for UDP mode");
218:
219: if (lflag)
220: errx(1, "no proxy support for listen");
221:
1.42 ericj 222: if (family == AF_UNIX)
223: errx(1, "no proxy support for unix sockets");
224:
1.34 jakob 225: /* XXX IPv6 transport to proxy would probably work */
226: if (family == AF_INET6)
227: errx(1, "no proxy support for IPv6");
228:
229: if (sflag)
230: errx(1, "no proxy support for local source address");
231:
232: proxyhost = strsep(&proxy, ":");
233: proxyport = proxy;
234:
235: memset(&proxyhints, 0, sizeof(struct addrinfo));
236: proxyhints.ai_family = family;
237: proxyhints.ai_socktype = SOCK_STREAM;
238: proxyhints.ai_protocol = IPPROTO_TCP;
239: if (nflag)
240: proxyhints.ai_flags |= AI_NUMERICHOST;
241: }
242:
1.21 ericj 243: if (lflag) {
244: int connfd;
1.27 ericj 245: ret = 0;
1.1 deraadt 246:
1.42 ericj 247: if (family == AF_UNIX)
248: s = unix_listen(host);
249:
1.21 ericj 250: /* Allow only one connection at a time, but stay alive */
251: for (;;) {
1.42 ericj 252: if (family != AF_UNIX)
253: s = local_listen(host, uport, hints);
254: if (s < 0)
1.30 smart 255: err(1, NULL);
1.21 ericj 256: /*
257: * For UDP, we will use recvfrom() initially
258: * to wait for a caller, then use the regular
259: * functions to talk to the caller.
260: */
261: if (uflag) {
1.23 ericj 262: int rv;
1.21 ericj 263: char buf[1024];
264: struct sockaddr_storage z;
265:
266: len = sizeof(z);
1.23 ericj 267: rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
1.37 jakob 268: (struct sockaddr *)&z, &len);
1.23 ericj 269: if (rv < 0)
1.21 ericj 270: errx(1, "%s", strerror(errno));
271:
1.37 jakob 272: rv = connect(s, (struct sockaddr *)&z, len);
1.23 ericj 273: if (rv < 0)
1.21 ericj 274: errx(1, "%s", strerror(errno));
1.1 deraadt 275:
1.21 ericj 276: connfd = s;
277: } else {
278: connfd = accept(s, (struct sockaddr *)&cliaddr,
1.37 jakob 279: &len);
1.21 ericj 280: }
1.1 deraadt 281:
1.21 ericj 282: readwrite(connfd);
283: close(connfd);
1.42 ericj 284: if (family != AF_UNIX)
285: close(s);
1.27 ericj 286:
1.21 ericj 287: if (!kflag)
288: break;
1.11 ericj 289: }
1.42 ericj 290: } else if (family == AF_UNIX) {
291: ret = 0;
292:
293: if ((s = unix_connect(host)) > 0 && !zflag) {
294: readwrite(s);
295: close(s);
296: } else
297: ret = 1;
298:
299: exit(ret);
300:
1.21 ericj 301: } else {
302: int i = 0;
1.6 deraadt 303:
1.21 ericj 304: /* construct the portlist[] array */
305: build_ports(uport);
1.1 deraadt 306:
1.21 ericj 307: /* Cycle through portlist, connecting to each port */
308: for (i = 0; portlist[i] != NULL; i++) {
309:
310: if (s)
311: close(s);
1.34 jakob 312:
313: if (xflag)
314: s = socks_connect(host, portlist[i], hints,
1.46 markus 315: proxyhost, proxyport, proxyhints, socksv);
1.34 jakob 316: else
317: s = remote_connect(host, portlist[i], hints);
318:
319: if (s < 0)
1.21 ericj 320: continue;
1.1 deraadt 321:
1.21 ericj 322: ret = 0;
323: if (vflag || zflag) {
324: /* For UDP, make sure we are connected */
325: if (uflag) {
326: if ((udptest(s)) == -1) {
327: ret = 1;
328: continue;
329: }
330: }
1.1 deraadt 331:
1.21 ericj 332: /* Don't lookup port if -n */
333: if (nflag)
334: sv = NULL;
335: else {
336: sv = getservbyport(
1.37 jakob 337: ntohs(atoi(portlist[i])),
338: uflag ? "udp" : "tcp");
1.21 ericj 339: }
340:
341: printf("Connection to %s %s port [%s/%s] succeeded!\n",
1.37 jakob 342: host, portlist[i], uflag ? "udp" : "tcp",
343: sv ? sv->s_name : "*");
1.21 ericj 344: }
345: if (!zflag)
346: readwrite(s);
1.7 deraadt 347: }
1.11 ericj 348: }
1.1 deraadt 349:
1.21 ericj 350: if (s)
351: close(s);
352:
353: exit(ret);
1.7 deraadt 354: }
1.1 deraadt 355:
1.11 ericj 356: /*
1.42 ericj 357: * unix_connect()
358: * Return's a socket connected to a local unix socket. Return's -1 on failure.
359: */
360: int
361: unix_connect(char *path)
362: {
363: struct sockaddr_un sun;
364: int s;
365:
366: if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
367: return (-1);
368: (void)fcntl(s, F_SETFD, 1);
369:
370: memset(&sun, 0, sizeof(struct sockaddr_un));
371: sun.sun_len = sizeof(path);
372: sun.sun_family = AF_UNIX;
373: strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
374:
375: if (connect(s, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
376: close(s);
377: return (-1);
378: }
379: return (s);
380:
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:
397: sun.sun_family = AF_UNIX;
398: strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
399:
1.45 ericj 400: if (bind(s, (struct sockaddr *)&sun, sizeof(sun)) < 0) {
1.42 ericj 401: close(s);
402: return (-1);
403: }
404:
405: if (listen(s, 5) < 0) {
406: close(s);
407: return (-1);
408: }
409: return (s);
410: }
411:
412: /*
1.21 ericj 413: * remote_connect()
414: * Return's a socket connected to a remote host. Properly bind's to a local
415: * port or source address if needed. Return's -1 on failure.
1.11 ericj 416: */
1.21 ericj 417: int
1.37 jakob 418: remote_connect(char *host, char *port, struct addrinfo hints)
1.21 ericj 419: {
420: struct addrinfo *res, *res0;
421: int s, error;
422:
423: if ((error = getaddrinfo(host, port, &hints, &res)))
424: errx(1, "%s", gai_strerror(error));
425:
426: res0 = res;
427: do {
428: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.37 jakob 429: res0->ai_protocol)) < 0)
1.21 ericj 430: continue;
431:
432: /* Bind to a local port or source address if specified */
433: if (sflag || pflag) {
434: struct addrinfo ahints, *ares;
435:
436: if (!(sflag && pflag)) {
437: if (!sflag)
438: sflag = NULL;
439: else
440: pflag = NULL;
441: }
1.6 deraadt 442:
1.21 ericj 443: memset(&ahints, 0, sizeof(struct addrinfo));
444: ahints.ai_family = res0->ai_family;
445: ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
446: ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
1.25 ericj 447: ahints.ai_flags = AI_PASSIVE;
1.38 jakob 448: if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
1.21 ericj 449: errx(1, "%s", gai_strerror(error));
450:
451: if (bind(s, (struct sockaddr *)ares->ai_addr,
1.37 jakob 452: ares->ai_addrlen) < 0) {
1.21 ericj 453: errx(1, "bind failed: %s", strerror(errno));
454: freeaddrinfo(ares);
455: continue;
456: }
457: freeaddrinfo(ares);
1.6 deraadt 458: }
459:
1.21 ericj 460: if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
1.6 deraadt 461: break;
1.34 jakob 462:
1.21 ericj 463: close(s);
464: s = -1;
465: } while ((res0 = res0->ai_next) != NULL);
466:
467: freeaddrinfo(res);
1.1 deraadt 468:
1.21 ericj 469: return (s);
1.7 deraadt 470: }
1.1 deraadt 471:
1.11 ericj 472: /*
1.21 ericj 473: * local_listen()
474: * Return's a socket listening on a local port, binds to specified source
475: * address. Return's -1 on failure.
1.11 ericj 476: */
1.21 ericj 477: int
1.37 jakob 478: local_listen(char *host, char *port, struct addrinfo hints)
1.21 ericj 479: {
480: struct addrinfo *res, *res0;
481: int s, ret, x = 1;
482: int error;
1.6 deraadt 483:
1.21 ericj 484: /* Allow nodename to be null */
485: hints.ai_flags |= AI_PASSIVE;
1.7 deraadt 486:
1.21 ericj 487: /*
488: * In the case of binding to a wildcard address
489: * default to binding to an ipv4 address.
490: */
491: if (host == NULL && hints.ai_family == AF_UNSPEC)
492: hints.ai_family = AF_INET;
1.1 deraadt 493:
1.21 ericj 494: if ((error = getaddrinfo(host, port, &hints, &res)))
495: errx(1, "%s", gai_strerror(error));
1.14 ericj 496:
1.21 ericj 497: res0 = res;
498: do {
499: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.37 jakob 500: res0->ai_protocol)) == 0)
1.21 ericj 501: continue;
1.1 deraadt 502:
1.21 ericj 503: ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
504: if (ret == -1)
1.30 smart 505: err(1, NULL);
1.1 deraadt 506:
1.21 ericj 507: if (bind(s, (struct sockaddr *)res0->ai_addr,
1.37 jakob 508: res0->ai_addrlen) == 0)
1.21 ericj 509: break;
1.1 deraadt 510:
1.21 ericj 511: close(s);
512: s = -1;
513: } while ((res0 = res0->ai_next) != NULL);
1.1 deraadt 514:
1.47 ! ericj 515: if (!uflag && s != -1) {
1.21 ericj 516: if (listen(s, 1) < 0)
517: errx(1, "%s", strerror(errno));
1.12 ericj 518: }
1.1 deraadt 519:
1.21 ericj 520: freeaddrinfo(res);
1.1 deraadt 521:
1.21 ericj 522: return (s);
1.7 deraadt 523: }
524:
1.11 ericj 525: /*
1.21 ericj 526: * readwrite()
527: * Loop that polls on the network file descriptor and stdin.
1.11 ericj 528: */
1.21 ericj 529: void
1.37 jakob 530: readwrite(int nfd)
1.6 deraadt 531: {
1.21 ericj 532: struct pollfd *pfd;
533: char buf[BUFSIZ];
534: int wfd = fileno(stdin), n, ret;
535: int lfd = fileno(stdout);
536:
537: pfd = malloc(2 * sizeof(struct pollfd));
538:
539: /* Setup Network FD */
540: pfd[0].fd = nfd;
541: pfd[0].events = POLLIN;
542:
543: /* Setup STDIN FD */
544: pfd[1].fd = wfd;
545: pfd[1].events = POLLIN;
546:
547: for (;;) {
548: if (iflag)
549: sleep(iflag);
550:
551: if (poll(pfd, 2, timeout) < 0) {
552: close(nfd);
553: close(wfd);
554: free(pfd);
555: errx(1, "Polling Error");
556: }
557:
558: if (pfd[0].revents & POLLIN) {
559: if ((n = read(nfd, buf, sizeof(buf))) <= 0) {
560: return;
561: } else {
562: if (tflag)
563: atelnet(nfd, buf, n);
564: if ((ret = atomicio(write, lfd, buf, n)) != n)
565: return;
1.6 deraadt 566: }
1.21 ericj 567: }
568:
569: if (pfd[1].revents & POLLIN) {
1.41 ericj 570: if ((n = read(wfd, buf, sizeof(buf))) < 0) {
1.21 ericj 571: return;
572: } else
573: if((ret = atomicio(write, nfd, buf, n)) != n)
574: return;
575: }
1.11 ericj 576: }
1.7 deraadt 577: }
1.24 ericj 578: /* Deal with RFC854 WILL/WONT DO/DONT negotiation */
1.21 ericj 579: void
1.37 jakob 580: atelnet(int nfd, unsigned char *buf, unsigned int size)
1.6 deraadt 581: {
1.28 ericj 582: int ret;
1.24 ericj 583: unsigned char *p, *end;
584: unsigned char obuf[4];
585:
586: end = buf + size;
587: obuf[0] = '\0';
588:
589: for (p = buf; p < end; p++) {
1.21 ericj 590: if (*p != IAC)
1.24 ericj 591: break;
592:
1.25 ericj 593: obuf[0] = IAC;
1.24 ericj 594: p++;
595: if ((*p == WILL) || (*p == WONT)) {
596: obuf[1] = DONT;
597: }
598: if ((*p == DO) || (*p == DONT)) {
599: obuf[1] = WONT;
600: }
601: if (obuf) {
602: p++;
1.11 ericj 603: obuf[2] = *p;
1.24 ericj 604: obuf[3] = '\0';
1.21 ericj 605: if ((ret = atomicio(write , nfd, obuf, 3)) != 3)
606: warnx("Write Error!");
1.24 ericj 607: obuf[0] = '\0';
1.11 ericj 608: }
609: }
1.7 deraadt 610: }
611:
1.11 ericj 612: /*
1.21 ericj 613: * build_ports()
614: * Build an array or ports in portlist[], listing each port
615: * that we should try to connect too.
1.11 ericj 616: */
1.21 ericj 617: void
1.37 jakob 618: build_ports(char *p)
1.6 deraadt 619: {
1.26 ericj 620: char *n, *endp;
1.21 ericj 621: int hi, lo, cp;
622: int x = 0;
623:
624: if ((n = strchr(p, '-')) != NULL) {
625: if (lflag)
626: errx(1, "Cannot use -l with multiple ports!");
627:
628: *n = '\0';
629: n++;
630:
631: /* Make sure the ports are in order: lowest->highest */
1.26 ericj 632: hi = (int)strtoul(n, &endp, 10);
1.31 ericj 633: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 634: errx(1, "port range not valid");
635: lo = (int)strtoul(p, &endp, 10);
1.31 ericj 636: if (lo <= 0 || lo > PORT_MAX || *endp != '\0')
1.26 ericj 637: errx(1, "port range not valid");
1.21 ericj 638:
639: if (lo > hi) {
640: cp = hi;
641: hi = lo;
642: lo = cp;
643: }
644:
645: /* Load ports sequentially */
646: for (cp = lo; cp <= hi; cp++) {
1.33 ericj 647: portlist[x] = calloc(1, PORT_MAX);
1.21 ericj 648: sprintf(portlist[x], "%d", cp);
649: x++;
650: }
651:
652: /* Randomly swap ports */
653: if (rflag) {
654: int y;
655: char *c;
656:
657: for (x = 0; x <= (hi - lo); x++) {
658: y = (arc4random() & 0xFFFF) % (hi - lo);
659: c = portlist[x];
660: portlist[x] = portlist[y];
661: portlist[y] = c;
1.6 deraadt 662: }
1.11 ericj 663: }
1.21 ericj 664: } else {
1.26 ericj 665: hi = (int)strtoul(p, &endp, 10);
1.31 ericj 666: if (hi <= 0 || hi > PORT_MAX || *endp != '\0')
1.26 ericj 667: errx(1, "port range not valid");
1.33 ericj 668: portlist[0] = calloc(1, PORT_MAX);
1.21 ericj 669: portlist[0] = p;
1.11 ericj 670: }
1.13 ericj 671: }
672:
673: /*
1.21 ericj 674: * udptest()
675: * Do a few writes to see if the UDP port is there.
676: * XXX - Better way of doing this? Doesn't work for IPv6
677: * Also fails after around 100 ports checked.
1.13 ericj 678: */
1.21 ericj 679: int
1.37 jakob 680: udptest(int s)
1.13 ericj 681: {
1.21 ericj 682: int i, rv, ret;
1.13 ericj 683:
1.21 ericj 684: for (i=0; i <= 3; i++) {
685: if ((rv = write(s, "X", 1)) == 1)
686: ret = 1;
1.14 ericj 687: else
1.21 ericj 688: ret = -1;
1.14 ericj 689: }
1.21 ericj 690: return (ret);
1.7 deraadt 691: }
1.1 deraadt 692:
1.11 ericj 693: void
1.21 ericj 694: help()
1.1 deraadt 695: {
1.21 ericj 696: usage(0);
697: fprintf(stderr, "\tCommand Summary:\n\
698: \t-4 Use IPv4\n\
699: \t-6 Use IPv6\n\
1.42 ericj 700: \t-U Use UNIX domain socket\n\
1.21 ericj 701: \t-h This help text\n\
702: \t-i secs\t Delay interval for lines sent, ports scanned\n\
703: \t-k Keep inbound sockets open for multiple connects\n\
704: \t-l Listen mode, for inbound connects\n\
1.22 jasoni 705: \t-n Suppress name/port resolutions\n\
1.36 jakob 706: \t-p port\t Specify local port for remote connects\n\
1.21 ericj 707: \t-r Randomize remote ports\n\
708: \t-s addr\t Local source address\n\
709: \t-t Answer TELNET negotiation\n\
710: \t-u UDP mode\n\
711: \t-v Verbose\n\
712: \t-w secs\t Timeout for connects and final net reads\n\
1.34 jakob 713: \t-x addr[:port]\tSpecify socks5 proxy address and port\n\
1.21 ericj 714: \t-z Zero-I/O mode [used for scanning]\n\
715: Port numbers can be individual or ranges: lo-hi [inclusive]\n");
716: exit(1);
1.11 ericj 717: }
718:
719: void
1.37 jakob 720: usage(int ret)
1.11 ericj 721: {
1.43 ericj 722: fprintf(stderr, "usage: nc [-46Uhklnrtuvz] [-i interval] [-p source port]\n");
1.36 jakob 723: fprintf(stderr, "\t [-s ip address] [-w timeout] [-x proxy address [:port]]\n");
724: fprintf(stderr, "\t [hostname] [port[s...]]\n");
1.21 ericj 725: if (ret)
726: exit(1);
1.7 deraadt 727: }