diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1 --- a/contrib/netcat/nc.1 +++ b/contrib/netcat/nc.1 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 10, 2020 +.Dd January 17, 2023 .Dt NC 1 .Os .Sh NAME @@ -47,6 +47,7 @@ .Op Fl p Ar source_port .Op Fl s Ar source .Op Fl T Ar toskeyword +.Op Fl -tun Ar tundev .Op Fl V Ar rtable .Op Fl w Ar timeout .Op Fl X Ar proxy_protocol @@ -240,6 +241,12 @@ This makes it possible to use .Nm to script telnet sessions. +.It Fl -tun Ar tundev +Causes +.Nm +to use the provided +.Xr tun 4 +for input and output rather than the default of stdin and stdout. .It Fl U Specifies to use .Ux Ns -domain diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c --- a/contrib/netcat/netcat.c +++ b/contrib/netcat/netcat.c @@ -112,6 +112,7 @@ int timeout = -1; int family = AF_UNSPEC; +int tun_fd = -1; char *portlist[PORT_MAX+1]; char *unix_dg_tmp_socket; @@ -144,6 +145,10 @@ char *ipsec_policy[2]; #endif +enum { + FREEBSD_TUN = CHAR_MAX, /* avoid collision with return values from getopt */ +}; + int main(int argc, char *argv[]) { @@ -156,12 +161,13 @@ socklen_t len; struct sockaddr_storage cliaddr; char *proxy; - const char *errstr, *proxyhost = "", *proxyport = NULL; + const char *errstr, *proxyhost = "", *proxyport = NULL, *tundev = NULL; struct addrinfo proxyhints; char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; struct option longopts[] = { { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 }, { "sctp", no_argument, &FreeBSD_sctp, 1 }, + { "tun", required_argument, NULL, FREEBSD_TUN }, { NULL, 0, NULL, 0 } }; @@ -326,6 +332,9 @@ if (Tflag < 0 || Tflag > 255 || errstr || errno) errx(1, "illegal tos value %s", optarg); break; + case FREEBSD_TUN: + tundev = optarg; + break; case 0: /* Long option. */ break; @@ -365,6 +374,13 @@ if (family == AF_UNIX) errx(1, "cannot use -U and --sctp"); } + if (tundev != NULL) { + if (!uflag) + errx(1, "must use --tun with -u"); + tun_fd = open(tundev, O_RDWR); + if (tun_fd == -1) + errx(1, "unable to open tun device %s", tundev); + } /* Get name of temporary socket for unix datagram client */ if ((family == AF_UNIX) && uflag && !lflag) { @@ -564,6 +580,8 @@ if (s) close(s); + if (tun_fd != -1) + close(tun_fd); exit(ret); } @@ -840,7 +858,7 @@ stdin_fd = -1; /* stdin */ - pfd[POLL_STDIN].fd = stdin_fd; + pfd[POLL_STDIN].fd = (tun_fd != -1) ? tun_fd : stdin_fd; pfd[POLL_STDIN].events = POLLIN; /* network out */ @@ -852,7 +870,7 @@ pfd[POLL_NETIN].events = POLLIN; /* stdout */ - pfd[POLL_STDOUT].fd = stdout_fd; + pfd[POLL_STDOUT].fd = (tun_fd != -1) ? tun_fd : stdout_fd; pfd[POLL_STDOUT].events = 0; while (1) { @@ -1440,6 +1458,7 @@ \t-n Suppress name/port resolutions\n\ \t--no-tcpopt Disable TCP options\n\ \t--sctp\t SCTP mode\n\ + \t--tun tundev Use tun device rather than stdio\n\ \t-O length TCP send buffer length\n\ \t-P proxyuser\tUsername for proxy authentication\n\ \t-p port\t Specify local port for remote connects\n\ @@ -1500,7 +1519,7 @@ #endif "\t [--no-tcpopt] [--sctp]\n" "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" - "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" + "\t [--tun tundev] [-V rtable] [-w timeout] [-X proxy_protocol]\n" "\t [-x proxy_address[:port]] [destination] [port]\n"); if (ret) exit(1);