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