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