]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - contrib/netcat/netcat.c
MFstable10 273998:
[FreeBSD/releng/10.1.git] / contrib / netcat / netcat.c
1 /* $OpenBSD: netcat.c,v 1.117 2013/10/26 21:33:29 sthen 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  *
28  * $FreeBSD$
29  */
30
31 /*
32  * Re-written nc(1) for OpenBSD. Original implementation by
33  * *Hobbit* <hobbit@avian.org>.
34  */
35
36 #include <sys/limits.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/sysctl.h>
40 #include <sys/time.h>
41 #include <sys/uio.h>
42 #include <sys/un.h>
43
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46 #ifdef IPSEC
47 #include <netipsec/ipsec.h>
48 #endif
49 #include <netinet/tcp.h>
50 #include <netinet/ip.h>
51 #include <arpa/telnet.h>
52
53 #include <err.h>
54 #include <errno.h>
55 #include <getopt.h>
56 #include <netdb.h>
57 #include <poll.h>
58 #include <stdarg.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <fcntl.h>
64 #include <limits.h>
65 #include "atomicio.h"
66
67 #ifndef SUN_LEN
68 #define SUN_LEN(su) \
69         (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
70 #endif
71
72 #define PORT_MAX        65535
73 #define PORT_MAX_LEN    6
74 #define UNIX_DG_TMP_SOCKET_SIZE 19
75
76 /* Command Line Options */
77 int     dflag;                                  /* detached, no stdin */
78 int     Fflag;                                  /* fdpass sock to stdout */
79 unsigned int iflag;                             /* Interval Flag */
80 int     kflag;                                  /* More than one connect */
81 int     lflag;                                  /* Bind to local port */
82 int     Nflag;                                  /* shutdown() network socket */
83 int     nflag;                                  /* Don't do name look up */
84 int     FreeBSD_Oflag;                          /* Do not use TCP options */
85 char   *Pflag;                                  /* Proxy username */
86 char   *pflag;                                  /* Localport flag */
87 int     rflag;                                  /* Random ports flag */
88 char   *sflag;                                  /* Source Address */
89 int     tflag;                                  /* Telnet Emulation */
90 int     uflag;                                  /* UDP - Default to TCP */
91 int     vflag;                                  /* Verbosity */
92 int     xflag;                                  /* Socks proxy */
93 int     zflag;                                  /* Port Scan Flag */
94 int     Dflag;                                  /* sodebug */
95 int     Iflag;                                  /* TCP receive buffer size */
96 int     Oflag;                                  /* TCP send buffer size */
97 int     Sflag;                                  /* TCP MD5 signature option */
98 int     Tflag = -1;                             /* IP Type of Service */
99 int     rtableid = -1;
100
101 int timeout = -1;
102 int family = AF_UNSPEC;
103 char *portlist[PORT_MAX+1];
104 char *unix_dg_tmp_socket;
105
106 void    atelnet(int, unsigned char *, unsigned int);
107 void    build_ports(char *);
108 void    help(void);
109 int     local_listen(char *, char *, struct addrinfo);
110 void    readwrite(int);
111 void    fdpass(int nfd) __attribute__((noreturn));
112 int     remote_connect(const char *, const char *, struct addrinfo);
113 int     timeout_connect(int, const struct sockaddr *, socklen_t);
114 int     socks_connect(const char *, const char *, struct addrinfo,
115             const char *, const char *, struct addrinfo, int, const char *);
116 int     udptest(int);
117 int     unix_bind(char *);
118 int     unix_connect(char *);
119 int     unix_listen(char *);
120 void    set_common_sockopts(int);
121 int     map_tos(char *, int *);
122 void    report_connect(const struct sockaddr *, socklen_t);
123 void    usage(int);
124
125 #ifdef IPSEC
126 void    add_ipsec_policy(int, char *);
127
128 char    *ipsec_policy[2];
129 #endif
130
131 int
132 main(int argc, char *argv[])
133 {
134         int ch, s, ret, socksv, ipsec_count;
135         int numfibs;
136         size_t intsize = sizeof(int);
137         char *host, *uport;
138         struct addrinfo hints;
139         struct servent *sv;
140         socklen_t len;
141         struct sockaddr_storage cliaddr;
142         char *proxy;
143         const char *errstr, *proxyhost = "", *proxyport = NULL;
144         struct addrinfo proxyhints;
145         char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
146         struct option longopts[] = {
147                 { "no-tcpopt",  no_argument,    &FreeBSD_Oflag, 1 },
148                 { NULL,         0,              NULL,           0 }
149         };
150
151         ret = 1;
152         ipsec_count = 0;
153         s = 0;
154         socksv = 5;
155         host = NULL;
156         uport = NULL;
157         sv = NULL;
158 #if 0
159         rtableid = getrtable();
160 #endif
161
162         while ((ch = getopt_long(argc, argv,
163             "46DdEe:FhI:i:klNnoO:P:p:rSs:tT:UuV:vw:X:x:z",
164             longopts, NULL)) != -1) {
165                 switch (ch) {
166                 case '4':
167                         family = AF_INET;
168                         break;
169                 case '6':
170                         family = AF_INET6;
171                         break;
172                 case 'U':
173                         family = AF_UNIX;
174                         break;
175                 case 'X':
176                         if (strcasecmp(optarg, "connect") == 0)
177                                 socksv = -1; /* HTTP proxy CONNECT */
178                         else if (strcmp(optarg, "4") == 0)
179                                 socksv = 4; /* SOCKS v.4 */
180                         else if (strcmp(optarg, "5") == 0)
181                                 socksv = 5; /* SOCKS v.5 */
182                         else
183                                 errx(1, "unsupported proxy protocol");
184                         break;
185                 case 'd':
186                         dflag = 1;
187                         break;
188                 case 'e':
189 #ifdef IPSEC
190                         ipsec_policy[ipsec_count++ % 2] = optarg;
191 #else
192                         errx(1, "IPsec support unavailable.");
193 #endif
194                         break;
195                 case 'E':
196 #ifdef IPSEC
197                         ipsec_policy[0] = "in  ipsec esp/transport//require";
198                         ipsec_policy[1] = "out ipsec esp/transport//require";
199 #else
200                         errx(1, "IPsec support unavailable.");
201 #endif
202                         break;
203                 case 'F':
204                         Fflag = 1;
205                         break;
206                 case 'h':
207                         help();
208                         break;
209                 case 'i':
210                         iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
211                         if (errstr)
212                                 errx(1, "interval %s: %s", errstr, optarg);
213                         break;
214                 case 'k':
215                         kflag = 1;
216                         break;
217                 case 'l':
218                         lflag = 1;
219                         break;
220                 case 'N':
221                         Nflag = 1;
222                         break;
223                 case 'n':
224                         nflag = 1;
225                         break;
226                 case 'o':
227                         fprintf(stderr, "option -o is deprecated.\n");
228                         break;
229                 case 'P':
230                         Pflag = optarg;
231                         break;
232                 case 'p':
233                         pflag = optarg;
234                         break;
235                 case 'r':
236                         rflag = 1;
237                         break;
238                 case 's':
239                         sflag = optarg;
240                         break;
241                 case 't':
242                         tflag = 1;
243                         break;
244                 case 'u':
245                         uflag = 1;
246                         break;
247                 case 'V':
248                         if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
249                                 errx(1, "Multiple FIBS not supported");
250                         rtableid = (int)strtonum(optarg, 0,
251                             numfibs - 1, &errstr);
252                         if (errstr)
253                                 errx(1, "rtable %s: %s", errstr, optarg);
254                         break;
255                 case 'v':
256                         vflag = 1;
257                         break;
258                 case 'w':
259                         timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
260                         if (errstr)
261                                 errx(1, "timeout %s: %s", errstr, optarg);
262                         timeout *= 1000;
263                         break;
264                 case 'x':
265                         xflag = 1;
266                         if ((proxy = strdup(optarg)) == NULL)
267                                 err(1, NULL);
268                         break;
269                 case 'z':
270                         zflag = 1;
271                         break;
272                 case 'D':
273                         Dflag = 1;
274                         break;
275                 case 'I':
276                         Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
277                         if (errstr != NULL)
278                                 errx(1, "TCP receive window %s: %s",
279                                     errstr, optarg);
280                         break;
281                 case 'O':
282                         Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
283                         if (errstr != NULL) {
284                             if (strcmp(errstr, "invalid") != 0)
285                                 errx(1, "TCP send window %s: %s",
286                                     errstr, optarg);
287                         }
288                         break;
289                 case 'S':
290                         Sflag = 1;
291                         break;
292                 case 'T':
293                         errstr = NULL;
294                         errno = 0;
295                         if (map_tos(optarg, &Tflag))
296                                 break;
297                         if (strlen(optarg) > 1 && optarg[0] == '0' &&
298                             optarg[1] == 'x')
299                                 Tflag = (int)strtol(optarg, NULL, 16);
300                         else
301                                 Tflag = (int)strtonum(optarg, 0, 255,
302                                     &errstr);
303                         if (Tflag < 0 || Tflag > 255 || errstr || errno)
304                                 errx(1, "illegal tos value %s", optarg);
305                         break;
306                 default:
307                         usage(1);
308                 }
309         }
310         argc -= optind;
311         argv += optind;
312
313         /* Cruft to make sure options are clean, and used properly. */
314         if (argv[0] && !argv[1] && family == AF_UNIX) {
315                 host = argv[0];
316                 uport = NULL;
317         } else if (argv[0] && !argv[1]) {
318                 if  (!lflag)
319                         usage(1);
320                 uport = argv[0];
321                 host = NULL;
322         } else if (argv[0] && argv[1]) {
323                 host = argv[0];
324                 uport = argv[1];
325         } else
326                 usage(1);
327
328         if (lflag && sflag)
329                 errx(1, "cannot use -s and -l");
330         if (lflag && pflag)
331                 errx(1, "cannot use -p and -l");
332         if (lflag && zflag)
333                 errx(1, "cannot use -z and -l");
334         if (!lflag && kflag)
335                 errx(1, "must use -l with -k");
336
337         /* Get name of temporary socket for unix datagram client */
338         if ((family == AF_UNIX) && uflag && !lflag) {
339                 if (sflag) {
340                         unix_dg_tmp_socket = sflag;
341                 } else {
342                         strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
343                                 UNIX_DG_TMP_SOCKET_SIZE);
344                         if (mktemp(unix_dg_tmp_socket_buf) == NULL)
345                                 err(1, "mktemp");
346                         unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
347                 }
348         }
349
350         /* Initialize addrinfo structure. */
351         if (family != AF_UNIX) {
352                 memset(&hints, 0, sizeof(struct addrinfo));
353                 hints.ai_family = family;
354                 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
355                 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
356                 if (nflag)
357                         hints.ai_flags |= AI_NUMERICHOST;
358         }
359
360         if (xflag) {
361                 if (uflag)
362                         errx(1, "no proxy support for UDP mode");
363
364                 if (lflag)
365                         errx(1, "no proxy support for listen");
366
367                 if (family == AF_UNIX)
368                         errx(1, "no proxy support for unix sockets");
369
370                 /* XXX IPv6 transport to proxy would probably work */
371                 if (family == AF_INET6)
372                         errx(1, "no proxy support for IPv6");
373
374                 if (sflag)
375                         errx(1, "no proxy support for local source address");
376
377                 proxyhost = strsep(&proxy, ":");
378                 proxyport = proxy;
379
380                 memset(&proxyhints, 0, sizeof(struct addrinfo));
381                 proxyhints.ai_family = family;
382                 proxyhints.ai_socktype = SOCK_STREAM;
383                 proxyhints.ai_protocol = IPPROTO_TCP;
384                 if (nflag)
385                         proxyhints.ai_flags |= AI_NUMERICHOST;
386         }
387
388         if (lflag) {
389                 int connfd;
390                 ret = 0;
391
392                 if (family == AF_UNIX) {
393                         if (uflag)
394                                 s = unix_bind(host);
395                         else
396                                 s = unix_listen(host);
397                 }
398
399                 /* Allow only one connection at a time, but stay alive. */
400                 for (;;) {
401                         if (family != AF_UNIX)
402                                 s = local_listen(host, uport, hints);
403                         if (s < 0)
404                                 err(1, NULL);
405                         /*
406                          * For UDP and -k, don't connect the socket, let it
407                          * receive datagrams from multiple socket pairs.
408                          */
409                         if (uflag && kflag)
410                                 readwrite(s);
411                         /*
412                          * For UDP and not -k, we will use recvfrom() initially
413                          * to wait for a caller, then use the regular functions
414                          * to talk to the caller.
415                          */
416                         else if (uflag && !kflag) {
417                                 int rv, plen;
418                                 char buf[16384];
419                                 struct sockaddr_storage z;
420
421                                 len = sizeof(z);
422                                 plen = 2048;
423                                 rv = recvfrom(s, buf, plen, MSG_PEEK,
424                                     (struct sockaddr *)&z, &len);
425                                 if (rv < 0)
426                                         err(1, "recvfrom");
427
428                                 rv = connect(s, (struct sockaddr *)&z, len);
429                                 if (rv < 0)
430                                         err(1, "connect");
431
432                                 if (vflag)
433                                         report_connect((struct sockaddr *)&z, len);
434
435                                 readwrite(s);
436                         } else {
437                                 len = sizeof(cliaddr);
438                                 connfd = accept(s, (struct sockaddr *)&cliaddr,
439                                     &len);
440                                 if (connfd == -1) {
441                                         /* For now, all errnos are fatal */
442                                         err(1, "accept");
443                                 }
444                                 if (vflag)
445                                         report_connect((struct sockaddr *)&cliaddr, len);
446
447                                 readwrite(connfd);
448                                 close(connfd);
449                         }
450
451                         if (family != AF_UNIX)
452                                 close(s);
453                         else if (uflag) {
454                                 if (connect(s, NULL, 0) < 0)
455                                         err(1, "connect");
456                         }
457
458                         if (!kflag)
459                                 break;
460                 }
461         } else if (family == AF_UNIX) {
462                 ret = 0;
463
464                 if ((s = unix_connect(host)) > 0 && !zflag) {
465                         readwrite(s);
466                         close(s);
467                 } else
468                         ret = 1;
469
470                 if (uflag)
471                         unlink(unix_dg_tmp_socket);
472                 exit(ret);
473
474         } else {
475                 int i = 0;
476
477                 /* Construct the portlist[] array. */
478                 build_ports(uport);
479
480                 /* Cycle through portlist, connecting to each port. */
481                 for (i = 0; portlist[i] != NULL; i++) {
482                         if (s)
483                                 close(s);
484
485                         if (xflag)
486                                 s = socks_connect(host, portlist[i], hints,
487                                     proxyhost, proxyport, proxyhints, socksv,
488                                     Pflag);
489                         else
490                                 s = remote_connect(host, portlist[i], hints);
491
492                         if (s < 0)
493                                 continue;
494
495                         ret = 0;
496                         if (vflag || zflag) {
497                                 /* For UDP, make sure we are connected. */
498                                 if (uflag) {
499                                         if (udptest(s) == -1) {
500                                                 ret = 1;
501                                                 continue;
502                                         }
503                                 }
504
505                                 /* Don't look up port if -n. */
506                                 if (nflag)
507                                         sv = NULL;
508                                 else {
509                                         sv = getservbyport(
510                                             ntohs(atoi(portlist[i])),
511                                             uflag ? "udp" : "tcp");
512                                 }
513
514                                 fprintf(stderr,
515                                     "Connection to %s %s port [%s/%s] "
516                                     "succeeded!\n", host, portlist[i],
517                                     uflag ? "udp" : "tcp",
518                                     sv ? sv->s_name : "*");
519                         }
520                         if (Fflag)
521                                 fdpass(s);
522                         else if (!zflag)
523                                 readwrite(s);
524                 }
525         }
526
527         if (s)
528                 close(s);
529
530         exit(ret);
531 }
532
533 /*
534  * unix_bind()
535  * Returns a unix socket bound to the given path
536  */
537 int
538 unix_bind(char *path)
539 {
540         struct sockaddr_un sun;
541         int s;
542
543         /* Create unix domain socket. */
544         if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
545              0)) < 0)
546                 return (-1);
547
548         memset(&sun, 0, sizeof(struct sockaddr_un));
549         sun.sun_family = AF_UNIX;
550
551         if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
552             sizeof(sun.sun_path)) {
553                 close(s);
554                 errno = ENAMETOOLONG;
555                 return (-1);
556         }
557
558         if (bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
559                 close(s);
560                 return (-1);
561         }
562         return (s);
563 }
564
565 /*
566  * unix_connect()
567  * Returns a socket connected to a local unix socket. Returns -1 on failure.
568  */
569 int
570 unix_connect(char *path)
571 {
572         struct sockaddr_un sun;
573         int s;
574
575         if (uflag) {
576                 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
577                         return (-1);
578         } else {
579                 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
580                         return (-1);
581         }
582         (void)fcntl(s, F_SETFD, FD_CLOEXEC);
583
584         memset(&sun, 0, sizeof(struct sockaddr_un));
585         sun.sun_family = AF_UNIX;
586
587         if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
588             sizeof(sun.sun_path)) {
589                 close(s);
590                 errno = ENAMETOOLONG;
591                 return (-1);
592         }
593         if (connect(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
594                 close(s);
595                 return (-1);
596         }
597         return (s);
598
599 }
600
601 /*
602  * unix_listen()
603  * Create a unix domain socket, and listen on it.
604  */
605 int
606 unix_listen(char *path)
607 {
608         int s;
609         if ((s = unix_bind(path)) < 0)
610                 return (-1);
611
612         if (listen(s, 5) < 0) {
613                 close(s);
614                 return (-1);
615         }
616         return (s);
617 }
618
619 /*
620  * remote_connect()
621  * Returns a socket connected to a remote host. Properly binds to a local
622  * port or source address if needed. Returns -1 on failure.
623  */
624 int
625 remote_connect(const char *host, const char *port, struct addrinfo hints)
626 {
627         struct addrinfo *res, *res0;
628         int s, error, on = 1;
629
630         if ((error = getaddrinfo(host, port, &hints, &res)))
631                 errx(1, "getaddrinfo: %s", gai_strerror(error));
632
633         res0 = res;
634         do {
635                 if ((s = socket(res0->ai_family, res0->ai_socktype,
636                     res0->ai_protocol)) < 0)
637                         continue;
638 #ifdef IPSEC
639                 if (ipsec_policy[0] != NULL)
640                         add_ipsec_policy(s, ipsec_policy[0]);
641                 if (ipsec_policy[1] != NULL)
642                         add_ipsec_policy(s, ipsec_policy[1]);
643 #endif
644
645                 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_SETFIB,
646                     &rtableid, sizeof(rtableid)) == -1))
647                         err(1, "setsockopt SO_SETFIB");
648
649                 /* Bind to a local port or source address if specified. */
650                 if (sflag || pflag) {
651                         struct addrinfo ahints, *ares;
652
653                         /* try IP_BINDANY, but don't insist */
654                         setsockopt(s, IPPROTO_IP, IP_BINDANY, &on, sizeof(on));
655                         memset(&ahints, 0, sizeof(struct addrinfo));
656                         ahints.ai_family = res0->ai_family;
657                         ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
658                         ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
659                         ahints.ai_flags = AI_PASSIVE;
660                         if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
661                                 errx(1, "getaddrinfo: %s", gai_strerror(error));
662
663                         if (bind(s, (struct sockaddr *)ares->ai_addr,
664                             ares->ai_addrlen) < 0)
665                                 errx(1, "bind failed: %s", strerror(errno));
666                         freeaddrinfo(ares);
667                 }
668
669                 set_common_sockopts(s);
670
671                 if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
672                         break;
673                 else if (vflag)
674                         warn("connect to %s port %s (%s) failed", host, port,
675                             uflag ? "udp" : "tcp");
676
677                 close(s);
678                 s = -1;
679         } while ((res0 = res0->ai_next) != NULL);
680
681         freeaddrinfo(res);
682
683         return (s);
684 }
685
686 int
687 timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
688 {
689         struct pollfd pfd;
690         socklen_t optlen;
691         int flags, optval;
692         int ret;
693
694         if (timeout != -1) {
695                 flags = fcntl(s, F_GETFL, 0);
696                 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
697                         err(1, "set non-blocking mode");
698         }
699
700         if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
701                 pfd.fd = s;
702                 pfd.events = POLLOUT;
703                 if ((ret = poll(&pfd, 1, timeout)) == 1) {
704                         optlen = sizeof(optval);
705                         if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
706                             &optval, &optlen)) == 0) {
707                                 errno = optval;
708                                 ret = optval == 0 ? 0 : -1;
709                         }
710                 } else if (ret == 0) {
711                         errno = ETIMEDOUT;
712                         ret = -1;
713                 } else
714                         err(1, "poll failed");
715         }
716
717         if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
718                 err(1, "restoring flags");
719
720         return (ret);
721 }
722
723 /*
724  * local_listen()
725  * Returns a socket listening on a local port, binds to specified source
726  * address. Returns -1 on failure.
727  */
728 int
729 local_listen(char *host, char *port, struct addrinfo hints)
730 {
731         struct addrinfo *res, *res0;
732         int s, ret, x = 1;
733         int error;
734
735         /* Allow nodename to be null. */
736         hints.ai_flags |= AI_PASSIVE;
737
738         /*
739          * In the case of binding to a wildcard address
740          * default to binding to an ipv4 address.
741          */
742         if (host == NULL && hints.ai_family == AF_UNSPEC)
743                 hints.ai_family = AF_INET;
744
745         if ((error = getaddrinfo(host, port, &hints, &res)))
746                 errx(1, "getaddrinfo: %s", gai_strerror(error));
747
748         res0 = res;
749         do {
750                 if ((s = socket(res0->ai_family, res0->ai_socktype,
751                     res0->ai_protocol)) < 0)
752                         continue;
753
754                 if (rtableid >= 0 && (setsockopt(s, IPPROTO_IP, SO_SETFIB,
755                     &rtableid, sizeof(rtableid)) == -1))
756                         err(1, "setsockopt SO_SETFIB");
757
758                 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
759                 if (ret == -1)
760                         err(1, NULL);
761 #ifdef IPSEC
762                 if (ipsec_policy[0] != NULL)
763                         add_ipsec_policy(s, ipsec_policy[0]);
764                 if (ipsec_policy[1] != NULL)
765                         add_ipsec_policy(s, ipsec_policy[1]);
766 #endif
767                 if (FreeBSD_Oflag) {
768                         if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
769                             &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
770                                 err(1, "disable TCP options");
771                 }
772
773                 if (bind(s, (struct sockaddr *)res0->ai_addr,
774                     res0->ai_addrlen) == 0)
775                         break;
776
777                 close(s);
778                 s = -1;
779         } while ((res0 = res0->ai_next) != NULL);
780
781         if (!uflag && s != -1) {
782                 if (listen(s, 1) < 0)
783                         err(1, "listen");
784         }
785
786         freeaddrinfo(res);
787
788         return (s);
789 }
790
791 /*
792  * readwrite()
793  * Loop that polls on the network file descriptor and stdin.
794  */
795 void
796 readwrite(int nfd)
797 {
798         struct pollfd pfd[2];
799         unsigned char buf[16384];
800         int n, wfd = fileno(stdin);
801         int lfd = fileno(stdout);
802         int plen;
803
804         plen = 2048;
805
806         /* Setup Network FD */
807         pfd[0].fd = nfd;
808         pfd[0].events = POLLIN;
809
810         /* Set up STDIN FD. */
811         pfd[1].fd = wfd;
812         pfd[1].events = POLLIN;
813
814         while (pfd[0].fd != -1) {
815                 if (iflag)
816                         sleep(iflag);
817
818                 if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
819                         close(nfd);
820                         err(1, "Polling Error");
821                 }
822
823                 if (n == 0)
824                         return;
825
826                 if (pfd[0].revents & POLLIN) {
827                         if ((n = read(nfd, buf, plen)) < 0)
828                                 return;
829                         else if (n == 0) {
830                                 shutdown(nfd, SHUT_RD);
831                                 pfd[0].fd = -1;
832                                 pfd[0].events = 0;
833                         } else {
834                                 if (tflag)
835                                         atelnet(nfd, buf, n);
836                                 if (atomicio(vwrite, lfd, buf, n) != n)
837                                         return;
838                         }
839                 }
840
841                 if (!dflag && pfd[1].revents & POLLIN) {
842                         if ((n = read(wfd, buf, plen)) < 0)
843                                 return;
844                         else if (n == 0) {
845                                 if (Nflag)
846                                         shutdown(nfd, SHUT_WR);
847                                 pfd[1].fd = -1;
848                                 pfd[1].events = 0;
849                         } else {
850                                 if (atomicio(vwrite, nfd, buf, n) != n)
851                                         return;
852                         }
853                 }
854         }
855 }
856
857 /*
858  * fdpass()
859  * Pass the connected file descriptor to stdout and exit.
860  */
861 void
862 fdpass(int nfd)
863 {
864         struct msghdr mh;
865         union {
866                 struct cmsghdr hdr;
867                 char buf[CMSG_SPACE(sizeof(int))];
868         } cmsgbuf;
869         struct cmsghdr *cmsg;
870         struct iovec iov;
871         char c = '\0';
872         ssize_t r;
873         struct pollfd pfd;
874
875         /* Avoid obvious stupidity */
876         if (isatty(STDOUT_FILENO))
877                 errx(1, "Cannot pass file descriptor to tty");
878
879         bzero(&mh, sizeof(mh));
880         bzero(&cmsgbuf, sizeof(cmsgbuf));
881         bzero(&iov, sizeof(iov));
882         bzero(&pfd, sizeof(pfd));
883
884         mh.msg_control = (caddr_t)&cmsgbuf.buf;
885         mh.msg_controllen = sizeof(cmsgbuf.buf);
886         cmsg = CMSG_FIRSTHDR(&mh);
887         cmsg->cmsg_len = CMSG_LEN(sizeof(int));
888         cmsg->cmsg_level = SOL_SOCKET;
889         cmsg->cmsg_type = SCM_RIGHTS;
890         *(int *)CMSG_DATA(cmsg) = nfd;
891
892         iov.iov_base = &c;
893         iov.iov_len = 1;
894         mh.msg_iov = &iov;
895         mh.msg_iovlen = 1;
896
897         bzero(&pfd, sizeof(pfd));
898         pfd.fd = STDOUT_FILENO;
899         for (;;) {
900                 r = sendmsg(STDOUT_FILENO, &mh, 0);
901                 if (r == -1) {
902                         if (errno == EAGAIN || errno == EINTR) {
903                                 pfd.events = POLLOUT;
904                                 if (poll(&pfd, 1, -1) == -1)
905                                         err(1, "poll");
906                                 continue;
907                         }
908                         err(1, "sendmsg");
909                 } else if (r == -1)
910                         errx(1, "sendmsg: unexpected return value %zd", r);
911                 else
912                         break;
913         }
914         exit(0);
915 }
916
917 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
918 void
919 atelnet(int nfd, unsigned char *buf, unsigned int size)
920 {
921         unsigned char *p, *end;
922         unsigned char obuf[4];
923
924         if (size < 3)
925                 return;
926         end = buf + size - 2;
927
928         for (p = buf; p < end; p++) {
929                 if (*p != IAC)
930                         continue;
931
932                 obuf[0] = IAC;
933                 p++;
934                 if ((*p == WILL) || (*p == WONT))
935                         obuf[1] = DONT;
936                 else if ((*p == DO) || (*p == DONT))
937                         obuf[1] = WONT;
938                 else
939                         continue;
940
941                 p++;
942                 obuf[2] = *p;
943                 if (atomicio(vwrite, nfd, obuf, 3) != 3)
944                         warn("Write Error!");
945         }
946 }
947
948 /*
949  * build_ports()
950  * Build an array of ports in portlist[], listing each port
951  * that we should try to connect to.
952  */
953 void
954 build_ports(char *p)
955 {
956         const char *errstr;
957         char *n;
958         int hi, lo, cp;
959         int x = 0;
960
961         if ((n = strchr(p, '-')) != NULL) {
962                 *n = '\0';
963                 n++;
964
965                 /* Make sure the ports are in order: lowest->highest. */
966                 hi = strtonum(n, 1, PORT_MAX, &errstr);
967                 if (errstr)
968                         errx(1, "port number %s: %s", errstr, n);
969                 lo = strtonum(p, 1, PORT_MAX, &errstr);
970                 if (errstr)
971                         errx(1, "port number %s: %s", errstr, p);
972
973                 if (lo > hi) {
974                         cp = hi;
975                         hi = lo;
976                         lo = cp;
977                 }
978
979                 /* Load ports sequentially. */
980                 for (cp = lo; cp <= hi; cp++) {
981                         portlist[x] = calloc(1, PORT_MAX_LEN);
982                         if (portlist[x] == NULL)
983                                 err(1, NULL);
984                         snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
985                         x++;
986                 }
987
988                 /* Randomly swap ports. */
989                 if (rflag) {
990                         int y;
991                         char *c;
992
993                         for (x = 0; x <= (hi - lo); x++) {
994                                 y = (arc4random() & 0xFFFF) % (hi - lo);
995                                 c = portlist[x];
996                                 portlist[x] = portlist[y];
997                                 portlist[y] = c;
998                         }
999                 }
1000         } else {
1001                 hi = strtonum(p, 1, PORT_MAX, &errstr);
1002                 if (errstr)
1003                         errx(1, "port number %s: %s", errstr, p);
1004                 portlist[0] = strdup(p);
1005                 if (portlist[0] == NULL)
1006                         err(1, NULL);
1007         }
1008 }
1009
1010 /*
1011  * udptest()
1012  * Do a few writes to see if the UDP port is there.
1013  * Fails once PF state table is full.
1014  */
1015 int
1016 udptest(int s)
1017 {
1018         int i, ret;
1019
1020         for (i = 0; i <= 3; i++) {
1021                 if (write(s, "X", 1) == 1)
1022                         ret = 1;
1023                 else
1024                         ret = -1;
1025         }
1026         return (ret);
1027 }
1028
1029 void
1030 set_common_sockopts(int s)
1031 {
1032         int x = 1;
1033
1034         if (Sflag) {
1035                 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
1036                         &x, sizeof(x)) == -1)
1037                         err(1, NULL);
1038         }
1039         if (Dflag) {
1040                 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
1041                         &x, sizeof(x)) == -1)
1042                         err(1, NULL);
1043         }
1044         if (Tflag != -1) {
1045                 if (setsockopt(s, IPPROTO_IP, IP_TOS,
1046                     &Tflag, sizeof(Tflag)) == -1)
1047                         err(1, "set IP ToS");
1048         }
1049         if (Iflag) {
1050                 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
1051                     &Iflag, sizeof(Iflag)) == -1)
1052                         err(1, "set TCP receive buffer size");
1053         }
1054         if (Oflag) {
1055                 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1056                     &Oflag, sizeof(Oflag)) == -1)
1057                         err(1, "set TCP send buffer size");
1058         }
1059         if (FreeBSD_Oflag) {
1060                 if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
1061                     &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
1062                         err(1, "disable TCP options");
1063         }
1064 }
1065
1066 int
1067 map_tos(char *s, int *val)
1068 {
1069         /* DiffServ Codepoints and other TOS mappings */
1070         const struct toskeywords {
1071                 const char      *keyword;
1072                 int              val;
1073         } *t, toskeywords[] = {
1074                 { "af11",               IPTOS_DSCP_AF11 },
1075                 { "af12",               IPTOS_DSCP_AF12 },
1076                 { "af13",               IPTOS_DSCP_AF13 },
1077                 { "af21",               IPTOS_DSCP_AF21 },
1078                 { "af22",               IPTOS_DSCP_AF22 },
1079                 { "af23",               IPTOS_DSCP_AF23 },
1080                 { "af31",               IPTOS_DSCP_AF31 },
1081                 { "af32",               IPTOS_DSCP_AF32 },
1082                 { "af33",               IPTOS_DSCP_AF33 },
1083                 { "af41",               IPTOS_DSCP_AF41 },
1084                 { "af42",               IPTOS_DSCP_AF42 },
1085                 { "af43",               IPTOS_DSCP_AF43 },
1086                 { "critical",           IPTOS_PREC_CRITIC_ECP },
1087                 { "cs0",                IPTOS_DSCP_CS0 },
1088                 { "cs1",                IPTOS_DSCP_CS1 },
1089                 { "cs2",                IPTOS_DSCP_CS2 },
1090                 { "cs3",                IPTOS_DSCP_CS3 },
1091                 { "cs4",                IPTOS_DSCP_CS4 },
1092                 { "cs5",                IPTOS_DSCP_CS5 },
1093                 { "cs6",                IPTOS_DSCP_CS6 },
1094                 { "cs7",                IPTOS_DSCP_CS7 },
1095                 { "ef",                 IPTOS_DSCP_EF },
1096                 { "inetcontrol",        IPTOS_PREC_INTERNETCONTROL },
1097                 { "lowdelay",           IPTOS_LOWDELAY },
1098                 { "netcontrol",         IPTOS_PREC_NETCONTROL },
1099                 { "reliability",        IPTOS_RELIABILITY },
1100                 { "throughput",         IPTOS_THROUGHPUT },
1101                 { NULL,                 -1 },
1102         };
1103
1104         for (t = toskeywords; t->keyword != NULL; t++) {
1105                 if (strcmp(s, t->keyword) == 0) {
1106                         *val = t->val;
1107                         return (1);
1108                 }
1109         }
1110
1111         return (0);
1112 }
1113
1114 void
1115 report_connect(const struct sockaddr *sa, socklen_t salen)
1116 {
1117         char remote_host[NI_MAXHOST];
1118         char remote_port[NI_MAXSERV];
1119         int herr;
1120         int flags = NI_NUMERICSERV;
1121         
1122         if (nflag)
1123                 flags |= NI_NUMERICHOST;
1124         
1125         if ((herr = getnameinfo(sa, salen,
1126             remote_host, sizeof(remote_host),
1127             remote_port, sizeof(remote_port),
1128             flags)) != 0) {
1129                 if (herr == EAI_SYSTEM)
1130                         err(1, "getnameinfo");
1131                 else
1132                         errx(1, "getnameinfo: %s", gai_strerror(herr));
1133         }
1134         
1135         fprintf(stderr,
1136             "Connection from %s %s "
1137             "received!\n", remote_host, remote_port);
1138 }
1139
1140 void
1141 help(void)
1142 {
1143         usage(0);
1144         fprintf(stderr, "\tCommand Summary:\n\
1145         \t-4            Use IPv4\n\
1146         \t-6            Use IPv6\n\
1147         \t-D            Enable the debug socket option\n\
1148         \t-d            Detach from stdin\n");
1149 #ifdef IPSEC
1150         fprintf(stderr, "\
1151         \t-E            Use IPsec ESP\n\
1152         \t-e policy     Use specified IPsec policy\n");
1153 #endif
1154         fprintf(stderr, "\
1155         \t-F            Pass socket fd\n\
1156         \t-h            This help text\n\
1157         \t-I length     TCP receive buffer length\n\
1158         \t-i secs\t     Delay interval for lines sent, ports scanned\n\
1159         \t-k            Keep inbound sockets open for multiple connects\n\
1160         \t-l            Listen mode, for inbound connects\n\
1161         \t-N            Shutdown the network socket after EOF on stdin\n\
1162         \t-n            Suppress name/port resolutions\n\
1163         \t--no-tcpopt   Disable TCP options\n\
1164         \t-O length     TCP send buffer length\n\
1165         \t-P proxyuser\tUsername for proxy authentication\n\
1166         \t-p port\t     Specify local port for remote connects\n\
1167         \t-r            Randomize remote ports\n\
1168         \t-S            Enable the TCP MD5 signature option\n\
1169         \t-s addr\t     Local source address\n\
1170         \t-T toskeyword\tSet IP Type of Service\n\
1171         \t-t            Answer TELNET negotiation\n\
1172         \t-U            Use UNIX domain socket\n\
1173         \t-u            UDP mode\n\
1174         \t-V rtable     Specify alternate routing table\n\
1175         \t-v            Verbose\n\
1176         \t-w secs\t     Timeout for connects and final net reads\n\
1177         \t-X proto      Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1178         \t-x addr[:port]\tSpecify proxy address and port\n\
1179         \t-z            Zero-I/O mode [used for scanning]\n\
1180         Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1181 #ifdef IPSEC
1182         fprintf(stderr, "See ipsec_set_policy(3) for -e argument format\n");
1183 #endif
1184         exit(1);
1185 }
1186
1187 #ifdef IPSEC
1188 void
1189 add_ipsec_policy(int s, char *policy)
1190 {
1191         char *raw;
1192         int e;
1193
1194         raw = ipsec_set_policy(policy, strlen(policy));
1195         if (raw == NULL)
1196                 errx(1, "ipsec_set_policy `%s': %s", policy,
1197                      ipsec_strerror());
1198         e = setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY, raw,
1199                         ipsec_get_policylen(raw));
1200         if (e < 0)
1201                 err(1, "ipsec policy cannot be configured");
1202         free(raw);
1203         if (vflag)
1204                 fprintf(stderr, "ipsec policy configured: `%s'\n", policy);
1205         return;
1206 }
1207 #endif /* IPSEC */
1208
1209 void
1210 usage(int ret)
1211 {
1212         fprintf(stderr,
1213 #ifdef IPSEC
1214             "usage: nc [-46DdEFhklNnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
1215 #else
1216             "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
1217 #endif
1218             "\t  [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1219             "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1220             "\t  [-x proxy_address[:port]] [destination] [port]\n");
1221         if (ret)
1222                 exit(1);
1223 }