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