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