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