Annotation of src/usr.bin/nc/netcat.c, Revision 1.25
1.25 ! ericj 1: /* $OpenBSD: netcat.c,v 1.24 2001/06/26 20:53:14 ericj Exp $ */
1.21 ericj 2: /*
3: * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
1.7 deraadt 4: *
1.21 ericj 5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
1.7 deraadt 8: *
1.21 ericj 9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. The name of the author may not be used to endorse or promote products
15: * derived from this software without specific prior written permission.
1.7 deraadt 16: *
1.21 ericj 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
1.1 deraadt 28:
1.24 ericj 29: /*
30: * Re-written nc(1) for OpenBSD. Original implementation by
1.21 ericj 31: * *Hobbit* <hobbit@avian.org>.
32: */
1.1 deraadt 33:
1.7 deraadt 34: #include <sys/types.h>
1.21 ericj 35: #include <sys/socket.h>
1.7 deraadt 36: #include <sys/time.h>
1.21 ericj 37:
1.7 deraadt 38: #include <netinet/in.h>
1.21 ericj 39: #include <arpa/telnet.h>
1.11 ericj 40: #include <err.h>
1.7 deraadt 41: #include <errno.h>
1.21 ericj 42: #include <netdb.h>
43: #include <poll.h>
1.13 ericj 44: #include <stdarg.h>
1.21 ericj 45: #include <stdio.h>
1.1 deraadt 46: #include <stdlib.h>
1.21 ericj 47: #include <string.h>
1.5 art 48: #include <unistd.h>
1.1 deraadt 49:
1.21 ericj 50: /* Command Line Options */
51: int iflag; /* Interval Flag */
52: int kflag; /* More than one connect */
53: int lflag; /* Bind to local port */
54: int nflag; /* Dont do name lookup */
55: char *pflag; /* Localport flag */
56: int rflag; /* Random ports flag */
57: char *sflag; /* Source Address */
58: int tflag; /* Telnet Emulation */
59: int uflag; /* UDP - Default to TCP */
60: int vflag; /* Verbosity */
61: int zflag; /* Port Scan Flag */
62:
63: int timeout;
64: int family = AF_UNSPEC;
65: char *portlist[65535];
66:
67: void atelnet __P((int, unsigned char *, unsigned int));
68: void build_ports __P((char *));
69: void help __P((void));
70: int local_listen __P((char *, char *, struct addrinfo));
71: void readwrite __P((int));
72: int remote_connect __P((char *, char *, struct addrinfo));
73: int udptest __P((int));
74: void usage __P((int));
1.1 deraadt 75:
1.21 ericj 76: int
77: main(argc, argv)
78: int argc;
79: char *argv[];
80: {
81: int ch, s, ret = 1;
82: char *host, *uport;
83: struct addrinfo hints;
84: struct servent *sv = 0;
85: socklen_t len;
86: struct sockaddr *cliaddr;
1.11 ericj 87:
1.21 ericj 88: while ((ch = getopt(argc, argv, "46hi:klnp:rs:tuvw:z")) != -1) {
89: switch (ch) {
90: case '4':
91: family = AF_INET;
92: break;
93: case '6':
94: family = AF_INET6;
95: break;
96: case 'h':
97: help();
98: break;
99: case 'i':
100: iflag = atoi(optarg);
101: break;
102: case 'k':
103: kflag = 1;
104: break;
105: case 'l':
106: lflag = 1;
107: break;
108: case 'n':
109: nflag = 1;
110: break;
111: case 'p':
112: pflag = optarg;
113: break;
114: case 'r':
115: rflag = 1;
116: break;
117: case 's':
118: sflag = optarg;
119: break;
120: case 't':
121: tflag = 1;
122: break;
123: case 'u':
124: uflag = 1;
125: break;
126: case 'v':
127: vflag = 1;
128: break;
129: case 'w':
130: timeout = atoi(optarg);
131: break;
132: case 'z':
133: zflag = 1;
134: break;
135: default:
136: usage(1);
137: }
138: }
139: argc -= optind;
140: argv += optind;
1.11 ericj 141:
1.21 ericj 142: /* Cruft to make sure options are clean, and used properly. */
143: if (argv[0] && !argv[1]) {
144: if (!lflag)
145: usage(1);
146: uport = argv[0];
147: host = NULL;
148: } else if (argv[0] && argv[1]) {
149: host = argv[0];
150: uport = argv[1];
151: } else
152: usage(1);
1.1 deraadt 153:
1.21 ericj 154: if (lflag && sflag)
155: errx(1, "cannot use -s and -l");
156: if (lflag && pflag)
157: errx(1, "cannot use -p and -l");
158: if (lflag && zflag)
159: errx(1, "cannot use -p and -l");
160: if (!lflag && kflag)
161: errx(1, "must use -k with -l");
162:
163: /* Initialize addrinfo structure */
164: memset(&hints, 0, sizeof(struct addrinfo));
165: hints.ai_family = family;
166: hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
167: hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
168: if (nflag)
169: hints.ai_flags |= AI_NUMERICHOST;
1.1 deraadt 170:
1.21 ericj 171: if (lflag) {
172: int connfd;
173:
174: if ((s = local_listen(host, uport, hints)) < 0)
175: errx(1, NULL);
1.1 deraadt 176:
1.21 ericj 177: ret = 0;
178: /* Allow only one connection at a time, but stay alive */
179: for (;;) {
180: /*
181: * For UDP, we will use recvfrom() initially
182: * to wait for a caller, then use the regular
183: * functions to talk to the caller.
184: */
185: if (uflag) {
1.23 ericj 186: int rv;
1.21 ericj 187: char buf[1024];
188: char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
189: struct sockaddr_storage z;
190:
191: len = sizeof(z);
1.23 ericj 192: rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK,
1.21 ericj 193: (struct sockaddr *)&z, &len);
1.23 ericj 194: if (rv < 0)
1.21 ericj 195: errx(1, "%s", strerror(errno));
196:
1.23 ericj 197: rv = connect(s, (struct sockaddr *)&z,
1.21 ericj 198: len);
1.23 ericj 199: if (rv < 0)
1.21 ericj 200: errx(1, "%s", strerror(errno));
1.1 deraadt 201:
1.21 ericj 202: connfd = s;
203: } else {
204: connfd = accept(s, (struct sockaddr *)&cliaddr,
205: &len);
206: }
1.1 deraadt 207:
1.21 ericj 208: readwrite(connfd);
209: close(connfd);
210: if (!kflag)
211: break;
1.11 ericj 212: }
1.21 ericj 213: } else {
214: int i = 0;
1.6 deraadt 215:
1.21 ericj 216: /* construct the portlist[] array */
217: build_ports(uport);
1.1 deraadt 218:
1.21 ericj 219: /* Cycle through portlist, connecting to each port */
220: for (i = 0; portlist[i] != NULL; i++) {
221:
222: if (s)
223: close(s);
224:
225: if ((s = remote_connect(host, portlist[i], hints)) < 0)
226: continue;
1.1 deraadt 227:
1.21 ericj 228: ret = 0;
229: if (vflag || zflag) {
230: /* For UDP, make sure we are connected */
231: if (uflag) {
232: if ((udptest(s)) == -1) {
233: ret = 1;
234: continue;
235: }
236: }
1.1 deraadt 237:
1.21 ericj 238: /* Don't lookup port if -n */
239: if (nflag)
240: sv = NULL;
241: else {
242: sv = getservbyport(
243: ntohs(atoi(portlist[i])),
244: uflag ? "udp" : "tcp");
245: }
246:
247: printf("Connection to %s %s port [%s/%s] succeeded!\n",
248: host, portlist[i], uflag ? "udp" : "tcp",
249: sv ? sv->s_name : "*");
250: }
251: if (!zflag)
252: readwrite(s);
1.7 deraadt 253: }
1.11 ericj 254: }
1.1 deraadt 255:
1.21 ericj 256: if (s)
257: close(s);
258:
259: exit(ret);
1.7 deraadt 260: }
1.1 deraadt 261:
1.11 ericj 262: /*
1.21 ericj 263: * remote_connect()
264: * Return's a socket connected to a remote host. Properly bind's to a local
265: * port or source address if needed. Return's -1 on failure.
1.11 ericj 266: */
1.21 ericj 267: int
268: remote_connect(host, port, hints)
269: char *host, *port;
270: struct addrinfo hints;
271: {
272: struct addrinfo *res, *res0;
273: int s, error;
274:
275: if ((error = getaddrinfo(host, port, &hints, &res)))
276: errx(1, "%s", gai_strerror(error));
277:
278: res0 = res;
279: do {
280: if ((s = socket(res0->ai_family, res0->ai_socktype,
281: res0->ai_protocol)) < 0)
282: continue;
283:
284: /* Bind to a local port or source address if specified */
285: if (sflag || pflag) {
286: struct addrinfo ahints, *ares;
287:
288: if (!(sflag && pflag)) {
289: if (!sflag)
290: sflag = NULL;
291: else
292: pflag = NULL;
293: }
1.6 deraadt 294:
1.21 ericj 295: memset(&ahints, 0, sizeof(struct addrinfo));
296: ahints.ai_family = res0->ai_family;
297: ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
298: ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
1.25 ! ericj 299: ahints.ai_flags = AI_PASSIVE;
1.21 ericj 300: if (getaddrinfo(sflag, pflag, &ahints, &ares))
301: errx(1, "%s", gai_strerror(error));
302:
303: if (bind(s, (struct sockaddr *)ares->ai_addr,
304: ares->ai_addrlen) < 0) {
305: errx(1, "bind failed: %s", strerror(errno));
306: freeaddrinfo(ares);
307: continue;
308: }
309: freeaddrinfo(ares);
1.6 deraadt 310: }
311:
1.21 ericj 312: if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
1.6 deraadt 313: break;
1.21 ericj 314:
315: close(s);
316: s = -1;
317: } while ((res0 = res0->ai_next) != NULL);
318:
319: freeaddrinfo(res);
1.1 deraadt 320:
1.21 ericj 321: return (s);
1.7 deraadt 322: }
1.1 deraadt 323:
1.11 ericj 324: /*
1.21 ericj 325: * local_listen()
326: * Return's a socket listening on a local port, binds to specified source
327: * address. Return's -1 on failure.
1.11 ericj 328: */
1.21 ericj 329: int
330: local_listen(host, port, hints)
331: char *host, *port;
332: struct addrinfo hints;
333: {
334: struct addrinfo *res, *res0;
335: int s, ret, x = 1;
336: int error;
1.6 deraadt 337:
1.21 ericj 338: /* Allow nodename to be null */
339: hints.ai_flags |= AI_PASSIVE;
1.7 deraadt 340:
1.21 ericj 341: /*
342: * In the case of binding to a wildcard address
343: * default to binding to an ipv4 address.
344: */
345: if (host == NULL && hints.ai_family == AF_UNSPEC)
346: hints.ai_family = AF_INET;
1.1 deraadt 347:
1.21 ericj 348: if ((error = getaddrinfo(host, port, &hints, &res)))
349: errx(1, "%s", gai_strerror(error));
1.14 ericj 350:
1.21 ericj 351: res0 = res;
352: do {
353: if ((s = socket(res0->ai_family, res0->ai_socktype,
354: res0->ai_protocol)) == 0)
355: continue;
1.1 deraadt 356:
1.21 ericj 357: ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
358: if (ret == -1)
359: errx(1, NULL);
1.1 deraadt 360:
1.21 ericj 361: if (bind(s, (struct sockaddr *)res0->ai_addr,
362: res0->ai_addrlen) == 0)
363: break;
1.1 deraadt 364:
1.21 ericj 365: close(s);
366: s = -1;
367: } while ((res0 = res0->ai_next) != NULL);
1.1 deraadt 368:
1.21 ericj 369: if (!uflag) {
370: if (listen(s, 1) < 0)
371: errx(1, "%s", strerror(errno));
1.12 ericj 372: }
1.1 deraadt 373:
1.21 ericj 374: freeaddrinfo(res);
1.1 deraadt 375:
1.21 ericj 376: return (s);
1.7 deraadt 377: }
378:
1.11 ericj 379: /*
1.21 ericj 380: * readwrite()
381: * Loop that polls on the network file descriptor and stdin.
1.11 ericj 382: */
1.21 ericj 383: void
384: readwrite(nfd)
385: int nfd;
1.6 deraadt 386: {
1.21 ericj 387: struct pollfd *pfd;
388: char buf[BUFSIZ];
389: int wfd = fileno(stdin), n, ret;
390: int lfd = fileno(stdout);
391:
392: pfd = malloc(2 * sizeof(struct pollfd));
393:
394: /* Setup Network FD */
395: pfd[0].fd = nfd;
396: pfd[0].events = POLLIN;
397:
398: /* Setup STDIN FD */
399: pfd[1].fd = wfd;
400: pfd[1].events = POLLIN;
401:
402: for (;;) {
403: if (iflag)
404: sleep(iflag);
405:
406: if (poll(pfd, 2, timeout) < 0) {
407: close(nfd);
408: close(wfd);
409: free(pfd);
410: errx(1, "Polling Error");
411: }
412:
413: if (pfd[0].revents & POLLIN) {
414: if ((n = read(nfd, buf, sizeof(buf))) <= 0) {
415: return;
416: } else {
417: if (tflag)
418: atelnet(nfd, buf, n);
419: if ((ret = atomicio(write, lfd, buf, n)) != n)
420: return;
1.6 deraadt 421: }
1.21 ericj 422: }
423:
424: if (pfd[1].revents & POLLIN) {
425: if ((n = read(wfd, buf, sizeof(buf))) <= 0) {
426: return;
427: } else
428: if((ret = atomicio(write, nfd, buf, n)) != n)
429: return;
430: }
1.11 ericj 431: }
1.7 deraadt 432: }
1.24 ericj 433: /* Deal with RFC854 WILL/WONT DO/DONT negotiation */
1.21 ericj 434: void
435: atelnet(nfd, buf, size)
436: int nfd;
437: unsigned char *buf;
1.6 deraadt 438: unsigned int size;
439: {
1.24 ericj 440: int ret, pos = 0;
441: unsigned char *p, *end;
442: unsigned char obuf[4];
443:
444: end = buf + size;
445: obuf[0] = '\0';
446:
447: for (p = buf; p < end; p++) {
1.21 ericj 448: if (*p != IAC)
1.24 ericj 449: break;
450:
1.25 ! ericj 451: obuf[0] = IAC;
1.24 ericj 452: p++;
453: if ((*p == WILL) || (*p == WONT)) {
454: obuf[1] = DONT;
455: }
456: if ((*p == DO) || (*p == DONT)) {
457: obuf[1] = WONT;
458: }
459: if (obuf) {
460: p++;
1.11 ericj 461: obuf[2] = *p;
1.24 ericj 462: obuf[3] = '\0';
1.21 ericj 463: if ((ret = atomicio(write , nfd, obuf, 3)) != 3)
464: warnx("Write Error!");
1.24 ericj 465: obuf[0] = '\0';
1.11 ericj 466: }
467: }
1.7 deraadt 468: }
469:
1.11 ericj 470: /*
1.21 ericj 471: * build_ports()
472: * Build an array or ports in portlist[], listing each port
473: * that we should try to connect too.
1.11 ericj 474: */
1.21 ericj 475: void
476: build_ports(p)
477: char *p;
1.6 deraadt 478: {
1.21 ericj 479: char *n;
480: int hi, lo, cp;
481: int x = 0;
482:
483: if ((n = strchr(p, '-')) != NULL) {
484: if (lflag)
485: errx(1, "Cannot use -l with multiple ports!");
486:
487: *n = '\0';
488: n++;
489:
490: /* Make sure the ports are in order: lowest->highest */
491: hi = atoi(n);
492: lo = atoi(p);
493:
494: if (lo > hi) {
495: cp = hi;
496: hi = lo;
497: lo = cp;
498: }
499:
500: /* Load ports sequentially */
501: for (cp = lo; cp <= hi; cp++) {
502: portlist[x] = malloc(sizeof(65535));
503: sprintf(portlist[x], "%d", cp);
504: x++;
505: }
506:
507: /* Randomly swap ports */
508: if (rflag) {
509: int y;
510: char *c;
511:
512: for (x = 0; x <= (hi - lo); x++) {
513: y = (arc4random() & 0xFFFF) % (hi - lo);
514: c = portlist[x];
515: portlist[x] = portlist[y];
516: portlist[y] = c;
1.6 deraadt 517: }
1.11 ericj 518: }
1.21 ericj 519: } else {
520: portlist[0] = malloc(sizeof(65535));
521: portlist[0] = p;
1.11 ericj 522: }
1.13 ericj 523: }
524:
525: /*
1.21 ericj 526: * udptest()
527: * Do a few writes to see if the UDP port is there.
528: * XXX - Better way of doing this? Doesn't work for IPv6
529: * Also fails after around 100 ports checked.
1.13 ericj 530: */
1.21 ericj 531: int
532: udptest(s)
533: int s;
1.13 ericj 534: {
1.21 ericj 535: int i, rv, ret;
1.13 ericj 536:
1.21 ericj 537: for (i=0; i <= 3; i++) {
538: if ((rv = write(s, "X", 1)) == 1)
539: ret = 1;
1.14 ericj 540: else
1.21 ericj 541: ret = -1;
1.14 ericj 542: }
1.21 ericj 543: return (ret);
1.7 deraadt 544: }
1.1 deraadt 545:
1.11 ericj 546: void
1.21 ericj 547: help()
1.1 deraadt 548: {
1.21 ericj 549: usage(0);
550: fprintf(stderr, "\tCommand Summary:\n\
551: \t-4 Use IPv4\n\
552: \t-6 Use IPv6\n\
553: \t-h This help text\n\
554: \t-i secs\t Delay interval for lines sent, ports scanned\n\
555: \t-k Keep inbound sockets open for multiple connects\n\
556: \t-l Listen mode, for inbound connects\n\
1.22 jasoni 557: \t-n Suppress name/port resolutions\n\
1.21 ericj 558: \t-p Specify local port for remote connects\n\
559: \t-r Randomize remote ports\n\
560: \t-s addr\t Local source address\n\
561: \t-t Answer TELNET negotiation\n\
562: \t-u UDP mode\n\
563: \t-v Verbose\n\
564: \t-w secs\t Timeout for connects and final net reads\n\
565: \t-z Zero-I/O mode [used for scanning]\n\
566: Port numbers can be individual or ranges: lo-hi [inclusive]\n");
567: exit(1);
1.11 ericj 568: }
569:
570: void
1.21 ericj 571: usage(ret)
572: int ret;
1.11 ericj 573: {
1.21 ericj 574: fprintf(stderr, "usage: nc [-46hklnrtuvz] [-i interval] [-p source port]\n");
575: fprintf(stderr, "\t [-s ip address] [-w timeout] [hostname] [port[s...]]\n");
576: if (ret)
577: exit(1);
1.7 deraadt 578: }