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