blob: 4c24b6f7f2f1a48e47cec06f0bd3904259acdc94 [file] [log] [blame]
Nick Kraleviche4e83f82011-10-24 15:44:27 -07001/* $OpenBSD: netcat.c,v 1.103 2011/10/04 08:34:34 fgsch Exp $ */
2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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 */
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080028
Nick Kraleviche4e83f82011-10-24 15:44:27 -070029/*
30 * Re-written nc(1) for OpenBSD. Original implementation by
31 * *Hobbit* <hobbit@avian.org>.
32 */
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080033
Nick Kraleviche4e83f82011-10-24 15:44:27 -070034#include <sys/types.h>
35#include <sys/socket.h>
36#include <sys/time.h>
37#include <sys/un.h>
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080038
Nick Kraleviche4e83f82011-10-24 15:44:27 -070039#include <netinet/in.h>
40#include <netinet/in_systm.h>
41#include <netinet/tcp.h>
42#include <netinet/ip.h>
43#include <arpa/telnet.h>
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080044
Nick Kraleviche4e83f82011-10-24 15:44:27 -070045#include <err.h>
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080046#include <errno.h>
Nick Kraleviche4e83f82011-10-24 15:44:27 -070047#include <netdb.h>
48#include <poll.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <limits.h>
56#include "atomicio.h"
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080057
Nick Kraleviche4e83f82011-10-24 15:44:27 -070058#ifndef SUN_LEN
59#define SUN_LEN(su) \
60 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080061#endif
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080062
Nick Kraleviche4e83f82011-10-24 15:44:27 -070063#define PORT_MAX 65535
64#define PORT_MAX_LEN 6
65#define UNIX_DG_TMP_SOCKET_SIZE 19
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080066
Nick Kraleviche4e83f82011-10-24 15:44:27 -070067/* Command Line Options */
68int dflag; /* detached, no stdin */
69unsigned int iflag; /* Interval Flag */
70#ifdef ANDROID
71int jflag = 0;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080072#else
Nick Kraleviche4e83f82011-10-24 15:44:27 -070073int jflag; /* use jumbo frames if we can */
74#endif /* !ANDROID */
75int kflag; /* More than one connect */
76int lflag; /* Bind to local port */
77int nflag; /* Don't do name look up */
78char *Pflag; /* Proxy username */
79char *pflag; /* Localport flag */
80int rflag; /* Random ports flag */
81char *sflag; /* Source Address */
82int tflag; /* Telnet Emulation */
83int uflag; /* UDP - Default to TCP */
84int vflag; /* Verbosity */
85#ifndef ANDROID
86int xflag; /* Socks proxy */
87#endif /* !ANDROID */
88int zflag; /* Port Scan Flag */
89int Dflag; /* sodebug */
90int Iflag; /* TCP receive buffer size */
91int Oflag; /* TCP send buffer size */
92#ifndef ANDROID
93int Sflag; /* TCP MD5 signature option */
94int Tflag = -1; /* IP Type of Service */
95u_int rtableid;
96#endif /* !ANDROID */
The Android Open Source Project5e0936b2009-03-03 19:30:07 -080097
Nick Kraleviche4e83f82011-10-24 15:44:27 -070098int timeout = -1;
99int family = AF_UNSPEC;
100char *portlist[PORT_MAX+1];
101char *unix_dg_tmp_socket;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800102
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700103void atelnet(int, unsigned char *, unsigned int);
104void build_ports(char *);
105void help(void);
106int local_listen(char *, char *, struct addrinfo);
107void readwrite(int);
108int remote_connect(const char *, const char *, struct addrinfo);
109int timeout_connect(int, const struct sockaddr *, socklen_t);
110#ifndef ANDROID
111int socks_connect(const char *, const char *, struct addrinfo,
112 const char *, const char *, struct addrinfo, int, const char *);
113#endif /* !ANDROID */
114int udptest(int);
115int unix_bind(char *);
116int unix_connect(char *);
117int unix_listen(char *);
118void set_common_sockopts(int);
119int map_tos(char *, int *);
120void usage(int);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800121
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700122int
123main(int argc, char *argv[])
124{
125 int ch, s, ret, socksv;
126 char *host, *uport;
127 struct addrinfo hints;
128 struct servent *sv;
129 socklen_t len;
130 struct sockaddr_storage cliaddr;
131 char *proxy;
132 const char *errstr, *proxyhost = "", *proxyport = NULL;
133 struct addrinfo proxyhints;
134 char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
135
136 ret = 1;
137 s = 0;
138 socksv = 5;
139 host = NULL;
140 uport = NULL;
141 sv = NULL;
142
143 while ((ch = getopt(argc, argv,
144 "46DdhI:i:jklnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
145 switch (ch) {
146 case '4':
147 family = AF_INET;
148 break;
149 case '6':
150 family = AF_INET6;
151 break;
152 case 'U':
153 family = AF_UNIX;
154 break;
155 case 'X':
156 if (strcasecmp(optarg, "connect") == 0)
157 socksv = -1; /* HTTP proxy CONNECT */
158 else if (strcmp(optarg, "4") == 0)
159 socksv = 4; /* SOCKS v.4 */
160 else if (strcmp(optarg, "5") == 0)
161 socksv = 5; /* SOCKS v.5 */
162 else
163 errx(1, "unsupported proxy protocol");
164 break;
165 case 'd':
166 dflag = 1;
167 break;
168 case 'h':
169 help();
170 break;
171 case 'i':
172#ifdef ANDROID
173 iflag = atoi(optarg);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800174#else
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700175 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
176 if (errstr)
177 errx(1, "interval %s: %s", errstr, optarg);
178#endif /* ANDROID */
179 break;
180#ifndef ANDROID
181 case 'j':
182 jflag = 1;
183 break;
184#endif /* !ANDROID */
185 case 'k':
186 kflag = 1;
187 break;
188 case 'l':
189 lflag = 1;
190 break;
191 case 'n':
192 nflag = 1;
193 break;
194 case 'P':
195 Pflag = optarg;
196 break;
197 case 'p':
198 pflag = optarg;
199 break;
200 case 'r':
201 rflag = 1;
202 break;
203 case 's':
204 sflag = optarg;
205 break;
206 case 't':
207 tflag = 1;
208 break;
209 case 'u':
210 uflag = 1;
211 break;
212#ifndef ANDROID
213 case 'V':
214 rtableid = (unsigned int)strtonum(optarg, 0,
215 RT_TABLEID_MAX, &errstr);
216 if (errstr)
217 errx(1, "rtable %s: %s", errstr, optarg);
218 break;
219#endif /* !ANDROID */
220 case 'v':
221 vflag = 1;
222 break;
223 case 'w':
224#ifdef ANDROID
225 timeout = atoi(optarg);
226#else
227 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
228 if (errstr)
229 errx(1, "timeout %s: %s", errstr, optarg);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800230#endif
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700231 timeout *= 1000;
232 break;
233#ifndef ANDROID
234 case 'x':
235 xflag = 1;
236 if ((proxy = strdup(optarg)) == NULL)
237 err(1, NULL);
238 break;
239#endif /* !ANDROID */
240 case 'z':
241 zflag = 1;
242 break;
243 case 'D':
244 Dflag = 1;
245 break;
246 case 'I':
247#ifdef ANDROID
248 Iflag = atoi(optarg);
249#else
250 Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
251 if (errstr != NULL)
252 errx(1, "TCP receive window %s: %s",
253 errstr, optarg);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800254#endif
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700255 break;
256 case 'O':
257#ifdef ANDROID
258 Oflag = atoi(optarg);
259#else
260 Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
261 if (errstr != NULL)
262 errx(1, "TCP send window %s: %s",
263 errstr, optarg);
264#endif
265 break;
266#ifndef ANDROID
267 case 'S':
268 Sflag = 1;
269 break;
270 case 'T':
271 errstr = NULL;
272 errno = 0;
273 if (map_tos(optarg, &Tflag))
274 break;
275 if (strlen(optarg) > 1 && optarg[0] == '0' &&
276 optarg[1] == 'x')
277 Tflag = (int)strtol(optarg, NULL, 16);
278 else
279 Tflag = (int)strtonum(optarg, 0, 255,
280 &errstr);
281 if (Tflag < 0 || Tflag > 255 || errstr || errno)
282 errx(1, "illegal tos value %s", optarg);
283 break;
284#endif /* !ANDROID */
285 default:
286 usage(1);
287 }
288 }
289 argc -= optind;
290 argv += optind;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800291
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700292 /* Cruft to make sure options are clean, and used properly. */
293 if (argv[0] && !argv[1] && family == AF_UNIX) {
294 host = argv[0];
295 uport = NULL;
296 } else if (argv[0] && !argv[1]) {
297 if (!lflag)
298 usage(1);
299 uport = argv[0];
300 host = NULL;
301 } else if (argv[0] && argv[1]) {
302 host = argv[0];
303 uport = argv[1];
304 } else
305 usage(1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800306
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700307 if (lflag && sflag)
308 errx(1, "cannot use -s and -l");
309 if (lflag && pflag)
310 errx(1, "cannot use -p and -l");
311 if (lflag && zflag)
312 errx(1, "cannot use -z and -l");
313 if (!lflag && kflag)
314 errx(1, "must use -l with -k");
315
316 /* Get name of temporary socket for unix datagram client */
317 if ((family == AF_UNIX) && uflag && !lflag) {
318 if (sflag) {
319 unix_dg_tmp_socket = sflag;
320 } else {
321 strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
322 UNIX_DG_TMP_SOCKET_SIZE);
323 if (mktemp(unix_dg_tmp_socket_buf) == NULL)
324 err(1, "mktemp");
325 unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
326 }
327 }
328
329 /* Initialize addrinfo structure. */
330 if (family != AF_UNIX) {
331 memset(&hints, 0, sizeof(struct addrinfo));
332 hints.ai_family = family;
333 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
334 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
335 if (nflag)
336 hints.ai_flags |= AI_NUMERICHOST;
337 }
338
339#ifndef ANDROID
340 if (xflag) {
341 if (uflag)
342 errx(1, "no proxy support for UDP mode");
343
344 if (lflag)
345 errx(1, "no proxy support for listen");
346
347 if (family == AF_UNIX)
348 errx(1, "no proxy support for unix sockets");
349
350 /* XXX IPv6 transport to proxy would probably work */
351 if (family == AF_INET6)
352 errx(1, "no proxy support for IPv6");
353
354 if (sflag)
355 errx(1, "no proxy support for local source address");
356
357 proxyhost = strsep(&proxy, ":");
358 proxyport = proxy;
359
360 memset(&proxyhints, 0, sizeof(struct addrinfo));
361 proxyhints.ai_family = family;
362 proxyhints.ai_socktype = SOCK_STREAM;
363 proxyhints.ai_protocol = IPPROTO_TCP;
364 if (nflag)
365 proxyhints.ai_flags |= AI_NUMERICHOST;
366 }
367#endif /* !ANDROID */
368
369 if (lflag) {
370 int connfd;
371 ret = 0;
372
373 if (family == AF_UNIX) {
374 if (uflag)
375 s = unix_bind(host);
376 else
377 s = unix_listen(host);
378 }
379
380 /* Allow only one connection at a time, but stay alive. */
381 for (;;) {
382 if (family != AF_UNIX)
383 s = local_listen(host, uport, hints);
384 if (s < 0)
385 err(1, NULL);
386 /*
387 * For UDP, we will use recvfrom() initially
388 * to wait for a caller, then use the regular
389 * functions to talk to the caller.
390 */
391 if (uflag) {
392 int rv, plen;
393 char buf[16384];
394 struct sockaddr_storage z;
395
396 len = sizeof(z);
397 plen = jflag ? 16384 : 2048;
398 rv = recvfrom(s, buf, plen, MSG_PEEK,
399 (struct sockaddr *)&z, &len);
400 if (rv < 0)
401 err(1, "recvfrom");
402
403 rv = connect(s, (struct sockaddr *)&z, len);
404 if (rv < 0)
405 err(1, "connect");
406
407 readwrite(s);
408 } else {
409 len = sizeof(cliaddr);
410 connfd = accept(s, (struct sockaddr *)&cliaddr,
411 &len);
412 readwrite(connfd);
413 close(connfd);
414 }
415
416 if (family != AF_UNIX)
417 close(s);
418 else if (uflag) {
419 if (connect(s, NULL, 0) < 0)
420 err(1, "connect");
421 }
422
423 if (!kflag)
424 break;
425 }
426 } else if (family == AF_UNIX) {
427 ret = 0;
428
429 if ((s = unix_connect(host)) > 0 && !zflag) {
430 readwrite(s);
431 close(s);
432 } else
433 ret = 1;
434
435 if (uflag)
436 unlink(unix_dg_tmp_socket);
437 exit(ret);
438
439 } else {
440 int i = 0;
441
442 /* Construct the portlist[] array. */
443 build_ports(uport);
444
445 /* Cycle through portlist, connecting to each port. */
446 for (i = 0; portlist[i] != NULL; i++) {
447 if (s)
448 close(s);
449
450#ifndef ANDROID
451 if (xflag)
452 s = socks_connect(host, portlist[i], hints,
453 proxyhost, proxyport, proxyhints, socksv,
454 Pflag);
455 else
456#endif /* !ANDROID */
457 s = remote_connect(host, portlist[i], hints);
458
459 if (s < 0)
460 continue;
461
462 ret = 0;
463 if (vflag || zflag) {
464 /* For UDP, make sure we are connected. */
465 if (uflag) {
466 if (udptest(s) == -1) {
467 ret = 1;
468 continue;
469 }
470 }
471
472 /* Don't look up port if -n. */
473 if (nflag)
474 sv = NULL;
475 else {
476 sv = getservbyport(
477 ntohs(atoi(portlist[i])),
478 uflag ? "udp" : "tcp");
479 }
480
481 fprintf(stderr,
482 "Connection to %s %s port [%s/%s] "
483 "succeeded!\n", host, portlist[i],
484 uflag ? "udp" : "tcp",
485 sv ? sv->s_name : "*");
486 }
487 if (!zflag)
488 readwrite(s);
489 }
490 }
491
492 if (s)
493 close(s);
494
495 exit(ret);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800496}
497
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700498/*
499 * unix_bind()
500 * Returns a unix socket bound to the given path
501 */
502int
503unix_bind(char *path)
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800504{
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700505 struct sockaddr_un sun;
506 int s;
507
508 /* Create unix domain socket. */
509 if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
510 0)) < 0)
511 return (-1);
512
513 memset(&sun, 0, sizeof(struct sockaddr_un));
514 sun.sun_family = AF_UNIX;
515
516 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
517 sizeof(sun.sun_path)) {
518 close(s);
519 errno = ENAMETOOLONG;
520 return (-1);
521 }
522
523 if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
524 close(s);
525 return (-1);
526 }
527 return (s);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800528}
529
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700530/*
531 * unix_connect()
532 * Returns a socket connected to a local unix socket. Returns -1 on failure.
533 */
534int
535unix_connect(char *path)
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800536{
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700537 struct sockaddr_un sun;
538 int s;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800539
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700540 if (uflag) {
541 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
542 return (-1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800543 } else {
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700544 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
545 return (-1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800546 }
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700547 (void)fcntl(s, F_SETFD, 1);
548
549 memset(&sun, 0, sizeof(struct sockaddr_un));
550 sun.sun_family = AF_UNIX;
551
552 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
553 sizeof(sun.sun_path)) {
554 close(s);
555 errno = ENAMETOOLONG;
556 return (-1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800557 }
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700558 if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
559 close(s);
560 return (-1);
561 }
562 return (s);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800563
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700564}
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800565
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700566/*
567 * unix_listen()
568 * Create a unix domain socket, and listen on it.
569 */
570int
571unix_listen(char *path)
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800572{
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700573 int s;
574 if ((s = unix_bind(path)) < 0)
575 return (-1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800576
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700577 if (listen(s, 5) < 0) {
578 close(s);
579 return (-1);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800580 }
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700581 return (s);
582}
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800583
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700584/*
585 * remote_connect()
586 * Returns a socket connected to a remote host. Properly binds to a local
587 * port or source address if needed. Returns -1 on failure.
588 */
589int
590remote_connect(const char *host, const char *port, struct addrinfo hints)
591{
592 struct addrinfo *res, *res0;
593 int s, error, on = 1;
594
595 if ((error = getaddrinfo(host, port, &hints, &res)))
596 errx(1, "getaddrinfo: %s", gai_strerror(error));
597
598 res0 = res;
599 do {
600 if ((s = socket(res0->ai_family, res0->ai_socktype,
601 res0->ai_protocol)) < 0)
602 continue;
603
604#ifndef ANDROID
605 if (rtableid) {
606 if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
607 sizeof(rtableid)) == -1)
608 err(1, "setsockopt SO_RTABLE");
609 }
610#endif /* !ANDROID */
611
612 /* Bind to a local port or source address if specified. */
613 if (sflag || pflag) {
614 struct addrinfo ahints, *ares;
615
616#ifndef ANDROID
617 /* try SO_BINDANY, but don't insist */
618 setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
619#endif /* !ANDROID */
620 memset(&ahints, 0, sizeof(struct addrinfo));
621 ahints.ai_family = res0->ai_family;
622 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
623 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
624 ahints.ai_flags = AI_PASSIVE;
625 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
626 errx(1, "getaddrinfo: %s", gai_strerror(error));
627
628 if (bind(s, (struct sockaddr *)ares->ai_addr,
629 ares->ai_addrlen) < 0)
630 errx(1, "bind failed: %s", strerror(errno));
631 freeaddrinfo(ares);
632 }
633
634 set_common_sockopts(s);
635
636 if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
637 break;
638 else if (vflag)
639 warn("connect to %s port %s (%s) failed", host, port,
640 uflag ? "udp" : "tcp");
641
642 close(s);
643 s = -1;
644 } while ((res0 = res0->ai_next) != NULL);
645
646 freeaddrinfo(res);
647
648 return (s);
649}
650
651int
652timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
653{
654 struct pollfd pfd;
655 socklen_t optlen;
656 int flags, optval;
657 int ret;
658
659 if (timeout != -1) {
660 flags = fcntl(s, F_GETFL, 0);
661 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
662 err(1, "set non-blocking mode");
663 }
664
665 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
666 pfd.fd = s;
667 pfd.events = POLLOUT;
668 if ((ret = poll(&pfd, 1, timeout)) == 1) {
669 optlen = sizeof(optval);
670 if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
671 &optval, &optlen)) == 0) {
672 errno = optval;
673 ret = optval == 0 ? 0 : -1;
674 }
675 } else if (ret == 0) {
676 errno = ETIMEDOUT;
677 ret = -1;
678 } else
679 err(1, "poll failed");
680 }
681
682 if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
683 err(1, "restoring flags");
684
685 return (ret);
686}
687
688/*
689 * local_listen()
690 * Returns a socket listening on a local port, binds to specified source
691 * address. Returns -1 on failure.
692 */
693int
694local_listen(char *host, char *port, struct addrinfo hints)
695{
696 struct addrinfo *res, *res0;
697 int s, ret, x = 1;
698 int error;
699
700 /* Allow nodename to be null. */
701 hints.ai_flags |= AI_PASSIVE;
702
703 /*
704 * In the case of binding to a wildcard address
705 * default to binding to an ipv4 address.
706 */
707 if (host == NULL && hints.ai_family == AF_UNSPEC)
708 hints.ai_family = AF_INET;
709
710 if ((error = getaddrinfo(host, port, &hints, &res)))
711 errx(1, "getaddrinfo: %s", gai_strerror(error));
712
713 res0 = res;
714 do {
715 if ((s = socket(res0->ai_family, res0->ai_socktype,
716 res0->ai_protocol)) < 0)
717 continue;
718
719#ifndef ANDROID
720 if (rtableid) {
721 if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid,
722 sizeof(rtableid)) == -1)
723 err(1, "setsockopt SO_RTABLE");
724 }
725#endif /* !ANDROID */
726
727#ifdef ANDROID
728 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800729#else
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700730 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800731#endif
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700732 if (ret == -1)
733 err(1, NULL);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800734
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700735 set_common_sockopts(s);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800736
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700737 if (bind(s, (struct sockaddr *)res0->ai_addr,
738 res0->ai_addrlen) == 0)
739 break;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800740
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700741 close(s);
742 s = -1;
743 } while ((res0 = res0->ai_next) != NULL);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800744
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700745 if (!uflag && s != -1) {
746 if (listen(s, 1) < 0)
747 err(1, "listen");
748 }
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800749
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700750 freeaddrinfo(res);
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800751
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700752 return (s);
753}
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800754
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700755/*
756 * readwrite()
757 * Loop that polls on the network file descriptor and stdin.
758 */
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800759void
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700760readwrite(int nfd)
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800761{
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700762 struct pollfd pfd[2];
763 unsigned char buf[16384];
764 int n, wfd = fileno(stdin);
765 int lfd = fileno(stdout);
766 int plen;
The Android Open Source Project5e0936b2009-03-03 19:30:07 -0800767
Nick Kraleviche4e83f82011-10-24 15:44:27 -0700768 plen = jflag ? 16384 : 2048;
769
770 /* Setup Network FD */
771 pfd[0].fd = nfd;
772 pfd[0].events = POLLIN;
773
774 /* Set up STDIN FD. */
775 pfd[1].fd = wfd;
776 pfd[1].events = POLLIN;
777
778 while (pfd[0].fd != -1) {
779 if (iflag)
780 sleep(iflag);
781
782 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
783 close(nfd);
784 err(1, "Polling Error");
785 }
786
787 if (n == 0)
788 return;
789
790 if (pfd[0].revents & POLLIN) {
791 if ((n = read(nfd, buf, plen)) < 0)
792 return;
793 else if (n == 0) {
794 shutdown(nfd, SHUT_RD);
795 pfd[0].fd = -1;
796 pfd[0].events = 0;
797 } else {
798 if (tflag)
799 atelnet(nfd, buf, n);
800 if (atomicio(vwrite, lfd, buf, n) != n)
801 return;
802 }
803 }
804
805 if (!dflag && pfd[1].revents & POLLIN) {
806 if ((n = read(wfd, buf, plen)) < 0)
807 return;
808 else if (n == 0) {
809 shutdown(nfd, SHUT_WR);
810 pfd[1].fd = -1;
811 pfd[1].events = 0;
812 } else {
813 if (atomicio(vwrite, nfd, buf, n) != n)
814 return;
815 }
816 }
817 }
818}
819
820/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
821void
822atelnet(int nfd, unsigned char *buf, unsigned int size)
823{
824 unsigned char *p, *end;
825 unsigned char obuf[4];
826
827 if (size < 3)
828 return;
829 end = buf + size - 2;
830
831 for (p = buf; p < end; p++) {
832 if (*p != IAC)
833 continue;
834
835 obuf[0] = IAC;
836 p++;
837 if ((*p == WILL) || (*p == WONT))
838 obuf[1] = DONT;
839 else if ((*p == DO) || (*p == DONT))
840 obuf[1] = WONT;
841 else
842 continue;
843
844 p++;
845 obuf[2] = *p;
846 if (atomicio(vwrite, nfd, obuf, 3) != 3)
847 warn("Write Error!");
848 }
849}
850
851/*
852 * build_ports()
853 * Build an array or ports in portlist[], listing each port
854 * that we should try to connect to.
855 */
856void
857build_ports(char *p)
858{
859 const char *errstr;
860 char *n;
861 int hi, lo, cp;
862 int x = 0;
863
864 if ((n = strchr(p, '-')) != NULL) {
865 if (lflag)
866 errx(1, "Cannot use -l with multiple ports!");
867
868 *n = '\0';
869 n++;
870
871 /* Make sure the ports are in order: lowest->highest. */
872#ifdef ANDROID
873 hi = atoi(n);
874#else
875 hi = strtonum(n, 1, PORT_MAX, &errstr);
876 if (errstr)
877 errx(1, "port number %s: %s", errstr, n);
878#endif
879#ifdef ANDROID
880 lo = atoi(p);
881#else
882 lo = strtonum(p, 1, PORT_MAX, &errstr);
883 if (errstr)
884 errx(1, "port number %s: %s", errstr, p);
885#endif
886
887 if (lo > hi) {
888 cp = hi;
889 hi = lo;
890 lo = cp;
891 }
892
893 /* Load ports sequentially. */
894 for (cp = lo; cp <= hi; cp++) {
895 portlist[x] = calloc(1, PORT_MAX_LEN);
896 if (portlist[x] == NULL)
897 err(1, NULL);
898 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
899 x++;
900 }
901
902 /* Randomly swap ports. */
903 if (rflag) {
904 int y;
905 char *c;
906
907 for (x = 0; x <= (hi - lo); x++) {
908 y = (arc4random() & 0xFFFF) % (hi - lo);
909 c = portlist[x];
910 portlist[x] = portlist[y];
911 portlist[y] = c;
912 }
913 }
914 } else {
915#ifdef ANDROID
916 hi = atoi(p);
917#else
918 hi = strtonum(p, 1, PORT_MAX, &errstr);
919 if (errstr)
920 errx(1, "port number %s: %s", errstr, p);
921#endif
922 portlist[0] = strdup(p);
923 if (portlist[0] == NULL)
924 err(1, NULL);
925 }
926}
927
928/*
929 * udptest()
930 * Do a few writes to see if the UDP port is there.
931 * XXX - Better way of doing this? Doesn't work for IPv6.
932 * Also fails after around 100 ports checked.
933 */
934int
935udptest(int s)
936{
937 int i, ret;
938
939 for (i = 0; i <= 3; i++) {
940 if (write(s, "X", 1) == 1)
941 ret = 1;
942 else
943 ret = -1;
944 }
945 return (ret);
946}
947
948void
949set_common_sockopts(int s)
950{
951 int x = 1;
952
953#ifndef ANDROID
954 if (Sflag) {
955 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
956 &x, sizeof(x)) == -1)
957 err(1, NULL);
958 }
959#endif
960 if (Dflag) {
961 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
962 &x, sizeof(x)) == -1)
963 err(1, NULL);
964 }
965#ifndef ANDROID
966 if (jflag) {
967 if (setsockopt(s, SOL_SOCKET, SO_JUMBO,
968 &x, sizeof(x)) == -1)
969 err(1, NULL);
970 }
971 if (Tflag != -1) {
972 if (setsockopt(s, IPPROTO_IP, IP_TOS,
973 &Tflag, sizeof(Tflag)) == -1)
974 err(1, "set IP ToS");
975 }
976#endif
977 if (Iflag) {
978 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
979 &Iflag, sizeof(Iflag)) == -1)
980 err(1, "set TCP receive buffer size");
981 }
982 if (Oflag) {
983 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
984 &Oflag, sizeof(Oflag)) == -1)
985 err(1, "set TCP send buffer size");
986 }
987}
988
989#ifndef ANDROID
990int
991map_tos(char *s, int *val)
992{
993 /* DiffServ Codepoints and other TOS mappings */
994 const struct toskeywords {
995 const char *keyword;
996 int val;
997 } *t, toskeywords[] = {
998 { "af11", IPTOS_DSCP_AF11 },
999 { "af12", IPTOS_DSCP_AF12 },
1000 { "af13", IPTOS_DSCP_AF13 },
1001 { "af21", IPTOS_DSCP_AF21 },
1002 { "af22", IPTOS_DSCP_AF22 },
1003 { "af23", IPTOS_DSCP_AF23 },
1004 { "af31", IPTOS_DSCP_AF31 },
1005 { "af32", IPTOS_DSCP_AF32 },
1006 { "af33", IPTOS_DSCP_AF33 },
1007 { "af41", IPTOS_DSCP_AF41 },
1008 { "af42", IPTOS_DSCP_AF42 },
1009 { "af43", IPTOS_DSCP_AF43 },
1010 { "critical", IPTOS_PREC_CRITIC_ECP },
1011 { "cs0", IPTOS_DSCP_CS0 },
1012 { "cs1", IPTOS_DSCP_CS1 },
1013 { "cs2", IPTOS_DSCP_CS2 },
1014 { "cs3", IPTOS_DSCP_CS3 },
1015 { "cs4", IPTOS_DSCP_CS4 },
1016 { "cs5", IPTOS_DSCP_CS5 },
1017 { "cs6", IPTOS_DSCP_CS6 },
1018 { "cs7", IPTOS_DSCP_CS7 },
1019 { "ef", IPTOS_DSCP_EF },
1020 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
1021 { "lowdelay", IPTOS_LOWDELAY },
1022 { "netcontrol", IPTOS_PREC_NETCONTROL },
1023 { "reliability", IPTOS_RELIABILITY },
1024 { "throughput", IPTOS_THROUGHPUT },
1025 { NULL, -1 },
1026 };
1027
1028 for (t = toskeywords; t->keyword != NULL; t++) {
1029 if (strcmp(s, t->keyword) == 0) {
1030 *val = t->val;
1031 return (1);
1032 }
1033 }
1034
1035 return (0);
1036}
1037#endif
1038
1039void
1040help(void)
1041{
1042 usage(0);
1043 fprintf(stderr, "\tCommand Summary:\n\
1044 \t-4 Use IPv4\n\
1045 \t-6 Use IPv6\n\
1046 \t-D Enable the debug socket option\n\
1047 \t-d Detach from stdin\n\
1048 \t-h This help text\n\
1049 \t-I length TCP receive buffer length\n\
1050 \t-i secs\t Delay interval for lines sent, ports scanned\n\
1051 \t-k Keep inbound sockets open for multiple connects\n\
1052 \t-l Listen mode, for inbound connects\n\
1053 \t-n Suppress name/port resolutions\n\
1054 \t-O length TCP send buffer length\n\
1055 \t-P proxyuser\tUsername for proxy authentication\n\
1056 \t-p port\t Specify local port for remote connects\n\
1057 \t-r Randomize remote ports\n\
1058 \t-S Enable the TCP MD5 signature option\n\
1059 \t-s addr\t Local source address\n\
1060 \t-T toskeyword\tSet IP Type of Service\n\
1061 \t-t Answer TELNET negotiation\n\
1062 \t-U Use UNIX domain socket\n\
1063 \t-u UDP mode\n\
1064 \t-V rtable Specify alternate routing table\n\
1065 \t-v Verbose\n\
1066 \t-w secs\t Timeout for connects and final net reads\n\
1067 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1068 \t-x addr[:port]\tSpecify proxy address and port\n\
1069 \t-z Zero-I/O mode [used for scanning]\n\
1070 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1071 exit(1);
1072}
1073
1074void
1075usage(int ret)
1076{
1077 fprintf(stderr,
1078 "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
1079 "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1080 "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1081 "\t [-x proxy_address[:port]] [destination] [port]\n");
1082 if (ret)
1083 exit(1);
1084}