Annotation of src/usr.bin/nc/netcat.c, Revision 1.101
1.101 ! mikeb 1: /* $OpenBSD: netcat.c,v 1.100 2011/01/09 22:16:46 jeremy 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.83 dtucker 40: #include <netinet/in_systm.h>
1.65 markus 41: #include <netinet/tcp.h>
1.83 dtucker 42: #include <netinet/ip.h>
1.21 ericj 43: #include <arpa/telnet.h>
1.29 smart 44:
1.11 ericj 45: #include <err.h>
1.7 deraadt 46: #include <errno.h>
1.21 ericj 47: #include <netdb.h>
48: #include <poll.h>
1.13 ericj 49: #include <stdarg.h>
1.21 ericj 50: #include <stdio.h>
1.1 deraadt 51: #include <stdlib.h>
1.21 ericj 52: #include <string.h>
1.5 art 53: #include <unistd.h>
1.42 ericj 54: #include <fcntl.h>
1.85 millert 55: #include <limits.h>
1.79 avsm 56: #include "atomicio.h"
1.51 vincent 57:
58: #ifndef SUN_LEN
59: #define SUN_LEN(su) \
60: (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
61: #endif
1.1 deraadt 62:
1.55 fgsch 63: #define PORT_MAX 65535
64: #define PORT_MAX_LEN 6
1.99 jeremy 65: #define UNIX_DG_TMP_SOCKET_SIZE 19
1.31 ericj 66:
1.21 ericj 67: /* Command Line Options */
1.68 tedu 68: int dflag; /* detached, no stdin */
1.88 ray 69: unsigned int iflag; /* Interval Flag */
1.80 mcbride 70: int jflag; /* use jumbo frames if we can */
1.21 ericj 71: int kflag; /* More than one connect */
72: int lflag; /* Bind to local port */
1.67 jmc 73: int nflag; /* Don't do name look up */
1.86 djm 74: char *Pflag; /* Proxy username */
1.21 ericj 75: char *pflag; /* Localport flag */
76: int rflag; /* Random ports flag */
77: char *sflag; /* Source Address */
78: int tflag; /* Telnet Emulation */
79: int uflag; /* UDP - Default to TCP */
80: int vflag; /* Verbosity */
1.34 jakob 81: int xflag; /* Socks proxy */
1.21 ericj 82: int zflag; /* Port Scan Flag */
1.73 markus 83: int Dflag; /* sodebug */
1.90 djm 84: int Iflag; /* TCP receive buffer size */
85: int Oflag; /* TCP send buffer size */
1.65 markus 86: int Sflag; /* TCP MD5 signature option */
1.83 dtucker 87: int Tflag = -1; /* IP Type of Service */
1.98 guenther 88: u_int rtableid;
1.21 ericj 89:
1.49 hugh 90: int timeout = -1;
1.21 ericj 91: int family = AF_UNSPEC;
1.63 miod 92: char *portlist[PORT_MAX+1];
1.99 jeremy 93: char *unix_dg_tmp_socket;
1.21 ericj 94:
1.40 millert 95: void atelnet(int, unsigned char *, unsigned int);
96: void build_ports(char *);
97: void help(void);
98: int local_listen(char *, char *, struct addrinfo);
99: void readwrite(int);
1.77 otto 100: int remote_connect(const char *, const char *, struct addrinfo);
1.86 djm 101: int socks_connect(const char *, const char *, struct addrinfo,
102: const char *, const char *, struct addrinfo, int, const char *);
1.40 millert 103: int udptest(int);
1.99 jeremy 104: int unix_bind(char *);
1.42 ericj 105: int unix_connect(char *);
106: int unix_listen(char *);
1.84 dtucker 107: void set_common_sockopts(int);
1.83 dtucker 108: int parse_iptos(char *);
1.40 millert 109: void usage(int);
1.1 deraadt 110:
1.21 ericj 111: int
1.37 jakob 112: main(int argc, char *argv[])
1.21 ericj 113: {
1.46 markus 114: int ch, s, ret, socksv;
1.88 ray 115: char *host, *uport;
1.21 ericj 116: struct addrinfo hints;
1.29 smart 117: struct servent *sv;
1.21 ericj 118: socklen_t len;
1.76 hshoexer 119: struct sockaddr_storage cliaddr;
1.34 jakob 120: char *proxy;
1.88 ray 121: const char *errstr, *proxyhost = "", *proxyport = NULL;
1.34 jakob 122: struct addrinfo proxyhints;
1.99 jeremy 123: char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
1.11 ericj 124:
1.29 smart 125: ret = 1;
126: s = 0;
1.46 markus 127: socksv = 5;
1.29 smart 128: host = NULL;
129: uport = NULL;
130: sv = NULL;
131:
1.80 mcbride 132: while ((ch = getopt(argc, argv,
1.93 claudio 133: "46DdhI:i:jklnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
1.21 ericj 134: switch (ch) {
135: case '4':
136: family = AF_INET;
137: break;
138: case '6':
139: family = AF_INET6;
140: break;
1.42 ericj 141: case 'U':
142: family = AF_UNIX;
143: break;
1.46 markus 144: case 'X':
1.75 djm 145: if (strcasecmp(optarg, "connect") == 0)
146: socksv = -1; /* HTTP proxy CONNECT */
147: else if (strcmp(optarg, "4") == 0)
148: socksv = 4; /* SOCKS v.4 */
149: else if (strcmp(optarg, "5") == 0)
150: socksv = 5; /* SOCKS v.5 */
151: else
152: errx(1, "unsupported proxy protocol");
1.46 markus 153: break;
1.68 tedu 154: case 'd':
155: dflag = 1;
156: break;
1.21 ericj 157: case 'h':
158: help();
159: break;
160: case 'i':
1.88 ray 161: iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
162: if (errstr)
163: errx(1, "interval %s: %s", errstr, optarg);
1.21 ericj 164: break;
1.80 mcbride 165: case 'j':
166: jflag = 1;
167: break;
1.21 ericj 168: case 'k':
169: kflag = 1;
170: break;
171: case 'l':
172: lflag = 1;
173: break;
174: case 'n':
175: nflag = 1;
176: break;
1.86 djm 177: case 'P':
178: Pflag = optarg;
179: break;
1.21 ericj 180: case 'p':
181: pflag = optarg;
182: break;
183: case 'r':
184: rflag = 1;
185: break;
186: case 's':
187: sflag = optarg;
188: break;
189: case 't':
190: tflag = 1;
191: break;
192: case 'u':
193: uflag = 1;
194: break;
1.93 claudio 195: case 'V':
1.98 guenther 196: rtableid = (unsigned int)strtonum(optarg, 0,
1.93 claudio 197: RT_TABLEID_MAX, &errstr);
198: if (errstr)
1.98 guenther 199: errx(1, "rtable %s: %s", errstr, optarg);
1.93 claudio 200: break;
1.21 ericj 201: case 'v':
202: vflag = 1;
203: break;
1.70 deraadt 204: case 'w':
1.88 ray 205: timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
206: if (errstr)
207: errx(1, "timeout %s: %s", errstr, optarg);
1.49 hugh 208: timeout *= 1000;
1.21 ericj 209: break;
1.34 jakob 210: case 'x':
211: xflag = 1;
1.64 deraadt 212: if ((proxy = strdup(optarg)) == NULL)
213: err(1, NULL);
1.34 jakob 214: break;
1.21 ericj 215: case 'z':
216: zflag = 1;
217: break;
1.73 markus 218: case 'D':
219: Dflag = 1;
220: break;
1.90 djm 221: case 'I':
222: Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
223: if (errstr != NULL)
224: errx(1, "TCP receive window %s: %s",
225: errstr, optarg);
226: break;
227: case 'O':
228: Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
229: if (errstr != NULL)
230: errx(1, "TCP send window %s: %s",
231: errstr, optarg);
232: break;
1.65 markus 233: case 'S':
234: Sflag = 1;
235: break;
1.83 dtucker 236: case 'T':
237: Tflag = parse_iptos(optarg);
238: break;
1.21 ericj 239: default:
240: usage(1);
241: }
242: }
243: argc -= optind;
244: argv += optind;
1.11 ericj 245:
1.21 ericj 246: /* Cruft to make sure options are clean, and used properly. */
1.42 ericj 247: if (argv[0] && !argv[1] && family == AF_UNIX) {
248: host = argv[0];
249: uport = NULL;
250: } else if (argv[0] && !argv[1]) {
1.21 ericj 251: if (!lflag)
252: usage(1);
253: uport = argv[0];
254: host = NULL;
255: } else if (argv[0] && argv[1]) {
256: host = argv[0];
257: uport = argv[1];
258: } else
259: usage(1);
1.1 deraadt 260:
1.21 ericj 261: if (lflag && sflag)
262: errx(1, "cannot use -s and -l");
263: if (lflag && pflag)
264: errx(1, "cannot use -p and -l");
265: if (lflag && zflag)
1.32 ericj 266: errx(1, "cannot use -z and -l");
1.21 ericj 267: if (!lflag && kflag)
1.32 ericj 268: errx(1, "must use -l with -k");
1.21 ericj 269:
1.99 jeremy 270: /* Get name of temporary socket for unix datagram client */
271: if ((family == AF_UNIX) && uflag && !lflag) {
272: if (sflag) {
273: unix_dg_tmp_socket = sflag;
274: } else {
275: strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
276: UNIX_DG_TMP_SOCKET_SIZE);
277: if (mktemp(unix_dg_tmp_socket_buf) == NULL)
278: err(1, "mktemp");
279: unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
280: }
281: }
282:
1.67 jmc 283: /* Initialize addrinfo structure. */
1.42 ericj 284: if (family != AF_UNIX) {
285: memset(&hints, 0, sizeof(struct addrinfo));
286: hints.ai_family = family;
287: hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
288: hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
289: if (nflag)
290: hints.ai_flags |= AI_NUMERICHOST;
291: }
1.1 deraadt 292:
1.34 jakob 293: if (xflag) {
294: if (uflag)
295: errx(1, "no proxy support for UDP mode");
296:
297: if (lflag)
298: errx(1, "no proxy support for listen");
299:
1.42 ericj 300: if (family == AF_UNIX)
301: errx(1, "no proxy support for unix sockets");
302:
1.34 jakob 303: /* XXX IPv6 transport to proxy would probably work */
304: if (family == AF_INET6)
305: errx(1, "no proxy support for IPv6");
306:
307: if (sflag)
308: errx(1, "no proxy support for local source address");
309:
310: proxyhost = strsep(&proxy, ":");
311: proxyport = proxy;
312:
313: memset(&proxyhints, 0, sizeof(struct addrinfo));
314: proxyhints.ai_family = family;
315: proxyhints.ai_socktype = SOCK_STREAM;
316: proxyhints.ai_protocol = IPPROTO_TCP;
317: if (nflag)
318: proxyhints.ai_flags |= AI_NUMERICHOST;
319: }
320:
1.21 ericj 321: if (lflag) {
322: int connfd;
1.27 ericj 323: ret = 0;
1.1 deraadt 324:
1.99 jeremy 325: if (family == AF_UNIX) {
326: if (uflag)
327: s = unix_bind(host);
328: else
329: s = unix_listen(host);
330: }
1.42 ericj 331:
1.67 jmc 332: /* Allow only one connection at a time, but stay alive. */
1.21 ericj 333: for (;;) {
1.42 ericj 334: if (family != AF_UNIX)
335: s = local_listen(host, uport, hints);
336: if (s < 0)
1.30 smart 337: err(1, NULL);
1.21 ericj 338: /*
339: * For UDP, we will use recvfrom() initially
340: * to wait for a caller, then use the regular
341: * functions to talk to the caller.
342: */
343: if (uflag) {
1.80 mcbride 344: int rv, plen;
1.97 nicm 345: char buf[16384];
1.21 ericj 346: struct sockaddr_storage z;
347:
348: len = sizeof(z);
1.97 nicm 349: plen = jflag ? 16384 : 2048;
1.80 mcbride 350: rv = recvfrom(s, buf, plen, MSG_PEEK,
1.37 jakob 351: (struct sockaddr *)&z, &len);
1.23 ericj 352: if (rv < 0)
1.57 stevesk 353: err(1, "recvfrom");
1.21 ericj 354:
1.37 jakob 355: rv = connect(s, (struct sockaddr *)&z, len);
1.23 ericj 356: if (rv < 0)
1.57 stevesk 357: err(1, "connect");
1.1 deraadt 358:
1.99 jeremy 359: readwrite(s);
1.21 ericj 360: } else {
1.78 otto 361: len = sizeof(cliaddr);
1.21 ericj 362: connfd = accept(s, (struct sockaddr *)&cliaddr,
1.37 jakob 363: &len);
1.99 jeremy 364: readwrite(connfd);
365: close(connfd);
1.21 ericj 366: }
1.1 deraadt 367:
1.42 ericj 368: if (family != AF_UNIX)
369: close(s);
1.99 jeremy 370: else if (uflag) {
371: if (connect(s, NULL, 0) < 0)
372: err(1, "connect");
373: }
1.27 ericj 374:
1.21 ericj 375: if (!kflag)
376: break;
1.11 ericj 377: }
1.42 ericj 378: } else if (family == AF_UNIX) {
379: ret = 0;
380:
381: if ((s = unix_connect(host)) > 0 && !zflag) {
382: readwrite(s);
383: close(s);
384: } else
385: ret = 1;
386:
1.99 jeremy 387: if (uflag)
388: unlink(unix_dg_tmp_socket);
1.42 ericj 389: exit(ret);
390:
1.21 ericj 391: } else {
392: int i = 0;
1.6 deraadt 393:
1.67 jmc 394: /* Construct the portlist[] array. */
1.21 ericj 395: build_ports(uport);
1.1 deraadt 396:
1.67 jmc 397: /* Cycle through portlist, connecting to each port. */
1.21 ericj 398: for (i = 0; portlist[i] != NULL; i++) {
399: if (s)
400: close(s);
1.34 jakob 401:
402: if (xflag)
403: s = socks_connect(host, portlist[i], hints,
1.86 djm 404: proxyhost, proxyport, proxyhints, socksv,
405: Pflag);
1.34 jakob 406: else
407: s = remote_connect(host, portlist[i], hints);
408:
409: if (s < 0)
1.21 ericj 410: continue;
1.1 deraadt 411:
1.21 ericj 412: ret = 0;
413: if (vflag || zflag) {
1.67 jmc 414: /* For UDP, make sure we are connected. */
1.21 ericj 415: if (uflag) {
1.50 vincent 416: if (udptest(s) == -1) {
1.21 ericj 417: ret = 1;
418: continue;
419: }
420: }
1.1 deraadt 421:
1.67 jmc 422: /* Don't look up port if -n. */
1.21 ericj 423: if (nflag)
424: sv = NULL;
425: else {
426: sv = getservbyport(
1.37 jakob 427: ntohs(atoi(portlist[i])),
428: uflag ? "udp" : "tcp");
1.21 ericj 429: }
1.50 vincent 430:
1.94 mpf 431: fprintf(stderr,
432: "Connection to %s %s port [%s/%s] "
433: "succeeded!\n", host, portlist[i],
434: uflag ? "udp" : "tcp",
1.37 jakob 435: sv ? sv->s_name : "*");
1.21 ericj 436: }
437: if (!zflag)
438: readwrite(s);
1.7 deraadt 439: }
1.11 ericj 440: }
1.1 deraadt 441:
1.21 ericj 442: if (s)
443: close(s);
444:
445: exit(ret);
1.7 deraadt 446: }
1.1 deraadt 447:
1.11 ericj 448: /*
1.99 jeremy 449: * unix_bind()
450: * Returns a unix socket bound to the given path
1.42 ericj 451: */
452: int
1.99 jeremy 453: unix_bind(char *path)
1.42 ericj 454: {
455: struct sockaddr_un sun;
456: int s;
457:
1.99 jeremy 458: /* Create unix domain socket. */
459: if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
460: 0)) < 0)
1.50 vincent 461: return (-1);
1.42 ericj 462:
463: memset(&sun, 0, sizeof(struct sockaddr_un));
464: sun.sun_family = AF_UNIX;
1.60 avsm 465:
466: if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
467: sizeof(sun.sun_path)) {
468: close(s);
469: errno = ENAMETOOLONG;
470: return (-1);
471: }
1.99 jeremy 472:
473: if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
1.50 vincent 474: close(s);
475: return (-1);
1.42 ericj 476: }
477: return (s);
478: }
479:
480: /*
1.99 jeremy 481: * unix_connect()
482: * Returns a socket connected to a local unix socket. Returns -1 on failure.
1.42 ericj 483: */
484: int
1.99 jeremy 485: unix_connect(char *path)
1.42 ericj 486: {
487: struct sockaddr_un sun;
488: int s;
489:
1.99 jeremy 490: if (uflag) {
491: if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
492: return (-1);
493: } else {
494: if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
495: return (-1);
496: }
497: (void)fcntl(s, F_SETFD, 1);
1.42 ericj 498:
1.60 avsm 499: memset(&sun, 0, sizeof(struct sockaddr_un));
1.42 ericj 500: sun.sun_family = AF_UNIX;
1.60 avsm 501:
502: if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
503: sizeof(sun.sun_path)) {
504: close(s);
505: errno = ENAMETOOLONG;
506: return (-1);
507: }
1.99 jeremy 508: if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
1.42 ericj 509: close(s);
510: return (-1);
511: }
1.99 jeremy 512: return (s);
513:
514: }
515:
516: /*
517: * unix_listen()
518: * Create a unix domain socket, and listen on it.
519: */
520: int
521: unix_listen(char *path)
522: {
523: int s;
524: if ((s = unix_bind(path)) < 0)
525: return (-1);
1.42 ericj 526:
527: if (listen(s, 5) < 0) {
528: close(s);
529: return (-1);
530: }
531: return (s);
532: }
533:
534: /*
1.21 ericj 535: * remote_connect()
1.67 jmc 536: * Returns a socket connected to a remote host. Properly binds to a local
537: * port or source address if needed. Returns -1 on failure.
1.11 ericj 538: */
1.21 ericj 539: int
1.77 otto 540: remote_connect(const char *host, const char *port, struct addrinfo hints)
1.21 ericj 541: {
542: struct addrinfo *res, *res0;
1.91 markus 543: int s, error, on = 1;
1.21 ericj 544:
545: if ((error = getaddrinfo(host, port, &hints, &res)))
1.56 stevesk 546: errx(1, "getaddrinfo: %s", gai_strerror(error));
1.21 ericj 547:
548: res0 = res;
549: do {
550: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.37 jakob 551: res0->ai_protocol)) < 0)
1.21 ericj 552: continue;
553:
1.98 guenther 554: if (rtableid) {
1.101 ! mikeb 555: if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
1.98 guenther 556: sizeof(rtableid)) == -1)
557: err(1, "setsockopt SO_RTABLE");
1.93 claudio 558: }
559:
1.67 jmc 560: /* Bind to a local port or source address if specified. */
1.21 ericj 561: if (sflag || pflag) {
562: struct addrinfo ahints, *ares;
1.6 deraadt 563:
1.91 markus 564: /* try SO_BINDANY, but don't insist */
565: setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
1.21 ericj 566: memset(&ahints, 0, sizeof(struct addrinfo));
567: ahints.ai_family = res0->ai_family;
568: ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
569: ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
1.25 ericj 570: ahints.ai_flags = AI_PASSIVE;
1.38 jakob 571: if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
1.56 stevesk 572: errx(1, "getaddrinfo: %s", gai_strerror(error));
1.21 ericj 573:
574: if (bind(s, (struct sockaddr *)ares->ai_addr,
1.62 millert 575: ares->ai_addrlen) < 0)
1.21 ericj 576: errx(1, "bind failed: %s", strerror(errno));
577: freeaddrinfo(ares);
1.6 deraadt 578: }
1.81 marius 579:
580: set_common_sockopts(s);
1.6 deraadt 581:
1.21 ericj 582: if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
1.6 deraadt 583: break;
1.71 mcbride 584: else if (vflag)
585: warn("connect to %s port %s (%s) failed", host, port,
586: uflag ? "udp" : "tcp");
1.34 jakob 587:
1.21 ericj 588: close(s);
589: s = -1;
590: } while ((res0 = res0->ai_next) != NULL);
591:
592: freeaddrinfo(res);
1.1 deraadt 593:
1.21 ericj 594: return (s);
1.7 deraadt 595: }
1.1 deraadt 596:
1.11 ericj 597: /*
1.21 ericj 598: * local_listen()
1.67 jmc 599: * Returns a socket listening on a local port, binds to specified source
600: * address. Returns -1 on failure.
1.11 ericj 601: */
1.21 ericj 602: int
1.37 jakob 603: local_listen(char *host, char *port, struct addrinfo hints)
1.21 ericj 604: {
605: struct addrinfo *res, *res0;
606: int s, ret, x = 1;
607: int error;
1.6 deraadt 608:
1.67 jmc 609: /* Allow nodename to be null. */
1.21 ericj 610: hints.ai_flags |= AI_PASSIVE;
1.7 deraadt 611:
1.21 ericj 612: /*
613: * In the case of binding to a wildcard address
614: * default to binding to an ipv4 address.
615: */
616: if (host == NULL && hints.ai_family == AF_UNSPEC)
617: hints.ai_family = AF_INET;
1.1 deraadt 618:
1.21 ericj 619: if ((error = getaddrinfo(host, port, &hints, &res)))
1.70 deraadt 620: errx(1, "getaddrinfo: %s", gai_strerror(error));
1.14 ericj 621:
1.21 ericj 622: res0 = res;
623: do {
624: if ((s = socket(res0->ai_family, res0->ai_socktype,
1.82 marius 625: res0->ai_protocol)) < 0)
1.21 ericj 626: continue;
1.1 deraadt 627:
1.98 guenther 628: if (rtableid) {
629: if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid,
630: sizeof(rtableid)) == -1)
631: err(1, "setsockopt SO_RTABLE");
1.93 claudio 632: }
633:
1.21 ericj 634: ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
635: if (ret == -1)
1.30 smart 636: err(1, NULL);
1.81 marius 637:
638: set_common_sockopts(s);
1.1 deraadt 639:
1.21 ericj 640: if (bind(s, (struct sockaddr *)res0->ai_addr,
1.37 jakob 641: res0->ai_addrlen) == 0)
1.21 ericj 642: break;
1.1 deraadt 643:
1.21 ericj 644: close(s);
645: s = -1;
646: } while ((res0 = res0->ai_next) != NULL);
1.1 deraadt 647:
1.47 ericj 648: if (!uflag && s != -1) {
1.21 ericj 649: if (listen(s, 1) < 0)
1.57 stevesk 650: err(1, "listen");
1.12 ericj 651: }
1.1 deraadt 652:
1.21 ericj 653: freeaddrinfo(res);
1.1 deraadt 654:
1.21 ericj 655: return (s);
1.7 deraadt 656: }
657:
1.11 ericj 658: /*
1.21 ericj 659: * readwrite()
660: * Loop that polls on the network file descriptor and stdin.
1.11 ericj 661: */
1.21 ericj 662: void
1.37 jakob 663: readwrite(int nfd)
1.6 deraadt 664: {
1.52 vincent 665: struct pollfd pfd[2];
1.97 nicm 666: unsigned char buf[16384];
1.79 avsm 667: int n, wfd = fileno(stdin);
1.21 ericj 668: int lfd = fileno(stdout);
1.80 mcbride 669: int plen;
670:
1.97 nicm 671: plen = jflag ? 16384 : 2048;
1.21 ericj 672:
673: /* Setup Network FD */
674: pfd[0].fd = nfd;
675: pfd[0].events = POLLIN;
676:
1.67 jmc 677: /* Set up STDIN FD. */
1.21 ericj 678: pfd[1].fd = wfd;
679: pfd[1].events = POLLIN;
680:
1.54 aaron 681: while (pfd[0].fd != -1) {
1.21 ericj 682: if (iflag)
683: sleep(iflag);
684:
1.68 tedu 685: if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
1.21 ericj 686: close(nfd);
1.52 vincent 687: err(1, "Polling Error");
1.21 ericj 688: }
1.49 hugh 689:
690: if (n == 0)
691: return;
1.21 ericj 692:
693: if (pfd[0].revents & POLLIN) {
1.80 mcbride 694: if ((n = read(nfd, buf, plen)) < 0)
1.21 ericj 695: return;
1.52 vincent 696: else if (n == 0) {
697: shutdown(nfd, SHUT_RD);
698: pfd[0].fd = -1;
699: pfd[0].events = 0;
1.21 ericj 700: } else {
701: if (tflag)
702: atelnet(nfd, buf, n);
1.79 avsm 703: if (atomicio(vwrite, lfd, buf, n) != n)
1.21 ericj 704: return;
1.6 deraadt 705: }
1.21 ericj 706: }
707:
1.68 tedu 708: if (!dflag && pfd[1].revents & POLLIN) {
1.80 mcbride 709: if ((n = read(wfd, buf, plen)) < 0)
1.21 ericj 710: return;
1.52 vincent 711: else if (n == 0) {
712: shutdown(nfd, SHUT_WR);
713: pfd[1].fd = -1;
714: pfd[1].events = 0;
715: } else {
1.79 avsm 716: if (atomicio(vwrite, nfd, buf, n) != n)
1.21 ericj 717: return;
1.50 vincent 718: }
1.21 ericj 719: }
1.11 ericj 720: }
1.7 deraadt 721: }
1.50 vincent 722:
1.67 jmc 723: /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
1.21 ericj 724: void
1.37 jakob 725: atelnet(int nfd, unsigned char *buf, unsigned int size)
1.6 deraadt 726: {
1.24 ericj 727: unsigned char *p, *end;
728: unsigned char obuf[4];
729:
1.95 nicm 730: if (size < 3)
731: return;
732: end = buf + size - 2;
1.24 ericj 733:
734: for (p = buf; p < end; p++) {
1.21 ericj 735: if (*p != IAC)
1.95 nicm 736: continue;
1.24 ericj 737:
1.25 ericj 738: obuf[0] = IAC;
1.24 ericj 739: p++;
1.50 vincent 740: if ((*p == WILL) || (*p == WONT))
1.24 ericj 741: obuf[1] = DONT;
1.95 nicm 742: else if ((*p == DO) || (*p == DONT))
1.24 ericj 743: obuf[1] = WONT;
1.95 nicm 744: else
745: continue;
746:
747: p++;
748: obuf[2] = *p;
749: if (atomicio(vwrite, nfd, obuf, 3) != 3)
750: warn("Write Error!");
1.11 ericj 751: }
1.7 deraadt 752: }
753:
1.11 ericj 754: /*
1.21 ericj 755: * build_ports()
756: * Build an array or ports in portlist[], listing each port
1.67 jmc 757: * that we should try to connect to.
1.11 ericj 758: */
1.21 ericj 759: void
1.37 jakob 760: build_ports(char *p)
1.6 deraadt 761: {
1.88 ray 762: const char *errstr;
763: char *n;
1.21 ericj 764: int hi, lo, cp;
765: int x = 0;
766:
767: if ((n = strchr(p, '-')) != NULL) {
768: if (lflag)
769: errx(1, "Cannot use -l with multiple ports!");
770:
771: *n = '\0';
772: n++;
773:
1.67 jmc 774: /* Make sure the ports are in order: lowest->highest. */
1.88 ray 775: hi = strtonum(n, 1, PORT_MAX, &errstr);
776: if (errstr)
777: errx(1, "port number %s: %s", errstr, n);
778: lo = strtonum(p, 1, PORT_MAX, &errstr);
779: if (errstr)
780: errx(1, "port number %s: %s", errstr, p);
1.21 ericj 781:
782: if (lo > hi) {
783: cp = hi;
784: hi = lo;
785: lo = cp;
786: }
787:
1.67 jmc 788: /* Load ports sequentially. */
1.21 ericj 789: for (cp = lo; cp <= hi; cp++) {
1.55 fgsch 790: portlist[x] = calloc(1, PORT_MAX_LEN);
791: if (portlist[x] == NULL)
792: err(1, NULL);
793: snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
1.21 ericj 794: x++;
795: }
796:
1.67 jmc 797: /* Randomly swap ports. */
1.21 ericj 798: if (rflag) {
799: int y;
800: char *c;
801:
802: for (x = 0; x <= (hi - lo); x++) {
803: y = (arc4random() & 0xFFFF) % (hi - lo);
804: c = portlist[x];
805: portlist[x] = portlist[y];
806: portlist[y] = c;
1.6 deraadt 807: }
1.11 ericj 808: }
1.21 ericj 809: } else {
1.88 ray 810: hi = strtonum(p, 1, PORT_MAX, &errstr);
811: if (errstr)
812: errx(1, "port number %s: %s", errstr, p);
1.96 nicm 813: portlist[0] = strdup(p);
1.55 fgsch 814: if (portlist[0] == NULL)
815: err(1, NULL);
1.11 ericj 816: }
1.13 ericj 817: }
818:
819: /*
1.21 ericj 820: * udptest()
821: * Do a few writes to see if the UDP port is there.
1.67 jmc 822: * XXX - Better way of doing this? Doesn't work for IPv6.
1.21 ericj 823: * Also fails after around 100 ports checked.
1.13 ericj 824: */
1.21 ericj 825: int
1.37 jakob 826: udptest(int s)
1.13 ericj 827: {
1.74 deraadt 828: int i, ret;
1.13 ericj 829:
1.52 vincent 830: for (i = 0; i <= 3; i++) {
1.74 deraadt 831: if (write(s, "X", 1) == 1)
1.21 ericj 832: ret = 1;
1.14 ericj 833: else
1.21 ericj 834: ret = -1;
1.14 ericj 835: }
1.21 ericj 836: return (ret);
1.81 marius 837: }
838:
1.84 dtucker 839: void
1.81 marius 840: set_common_sockopts(int s)
841: {
842: int x = 1;
843:
844: if (Sflag) {
845: if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
846: &x, sizeof(x)) == -1)
847: err(1, NULL);
848: }
849: if (Dflag) {
850: if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
851: &x, sizeof(x)) == -1)
852: err(1, NULL);
853: }
854: if (jflag) {
855: if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
856: &x, sizeof(x)) == -1)
857: err(1, NULL);
858: }
1.83 dtucker 859: if (Tflag != -1) {
860: if (setsockopt(s, IPPROTO_IP, IP_TOS,
861: &Tflag, sizeof(Tflag)) == -1)
862: err(1, "set IP ToS");
863: }
1.90 djm 864: if (Iflag) {
865: if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
866: &Iflag, sizeof(Iflag)) == -1)
867: err(1, "set TCP receive buffer size");
868: }
869: if (Oflag) {
870: if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
871: &Oflag, sizeof(Oflag)) == -1)
872: err(1, "set TCP send buffer size");
873: }
1.83 dtucker 874: }
875:
876: int
877: parse_iptos(char *s)
878: {
879: int tos = -1;
880:
881: if (strcmp(s, "lowdelay") == 0)
882: return (IPTOS_LOWDELAY);
883: if (strcmp(s, "throughput") == 0)
884: return (IPTOS_THROUGHPUT);
885: if (strcmp(s, "reliability") == 0)
886: return (IPTOS_RELIABILITY);
887:
888: if (sscanf(s, "0x%x", &tos) != 1 || tos < 0 || tos > 0xff)
889: errx(1, "invalid IP Type of Service");
890: return (tos);
1.7 deraadt 891: }
1.1 deraadt 892:
1.11 ericj 893: void
1.58 deraadt 894: help(void)
1.1 deraadt 895: {
1.21 ericj 896: usage(0);
897: fprintf(stderr, "\tCommand Summary:\n\
898: \t-4 Use IPv4\n\
899: \t-6 Use IPv6\n\
1.73 markus 900: \t-D Enable the debug socket option\n\
1.69 tedu 901: \t-d Detach from stdin\n\
1.21 ericj 902: \t-h This help text\n\
1.90 djm 903: \t-I length TCP receive buffer length\n\
1.21 ericj 904: \t-i secs\t Delay interval for lines sent, ports scanned\n\
905: \t-k Keep inbound sockets open for multiple connects\n\
906: \t-l Listen mode, for inbound connects\n\
1.22 jasoni 907: \t-n Suppress name/port resolutions\n\
1.90 djm 908: \t-O length TCP send buffer length\n\
1.86 djm 909: \t-P proxyuser\tUsername for proxy authentication\n\
1.36 jakob 910: \t-p port\t Specify local port for remote connects\n\
1.21 ericj 911: \t-r Randomize remote ports\n\
1.67 jmc 912: \t-S Enable the TCP MD5 signature option\n\
1.21 ericj 913: \t-s addr\t Local source address\n\
1.83 dtucker 914: \t-T ToS\t Set IP Type of Service\n\
1.21 ericj 915: \t-t Answer TELNET negotiation\n\
1.67 jmc 916: \t-U Use UNIX domain socket\n\
1.21 ericj 917: \t-u UDP mode\n\
1.98 guenther 918: \t-V rtable Specify alternate routing table\n\
1.21 ericj 919: \t-v Verbose\n\
920: \t-w secs\t Timeout for connects and final net reads\n\
1.75 djm 921: \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
922: \t-x addr[:port]\tSpecify proxy address and port\n\
1.21 ericj 923: \t-z Zero-I/O mode [used for scanning]\n\
924: Port numbers can be individual or ranges: lo-hi [inclusive]\n");
925: exit(1);
1.11 ericj 926: }
927:
928: void
1.37 jakob 929: usage(int ret)
1.11 ericj 930: {
1.92 sobrado 931: fprintf(stderr,
932: "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
1.100 jeremy 933: "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1.98 guenther 934: "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1.100 jeremy 935: "\t [-x proxy_address[:port]] [destination] [port]\n");
1.21 ericj 936: if (ret)
937: exit(1);
1.7 deraadt 938: }