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