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 November 16, 2022 .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 @@ -94,6 +94,7 @@ int nflag; /* Don't do name look up */ int FreeBSD_Oflag; /* Do not use TCP options */ int FreeBSD_sctp; /* Use SCTP */ +int FreeBSD_tun; /* Use tun interface instead of stdio*/ char *Pflag; /* Proxy username */ char *pflag; /* Localport flag */ int rflag; /* Random ports flag */ @@ -112,6 +113,7 @@ int timeout = -1; int family = AF_UNSPEC; +int tun_fd = -1; char *portlist[PORT_MAX+1]; char *unix_dg_tmp_socket; @@ -144,6 +146,10 @@ char *ipsec_policy[2]; #endif +enum { + FREEBSD_TUN = 1000, /* avoid collision with return values from getopt */ +}; + int main(int argc, char *argv[]) { @@ -155,13 +161,14 @@ struct servent *sv; socklen_t len; struct sockaddr_storage cliaddr; - char *proxy; + char *proxy, *tundev; const char *errstr, *proxyhost = "", *proxyport = 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 +333,11 @@ if (Tflag < 0 || Tflag > 255 || errstr || errno) errx(1, "illegal tos value %s", optarg); break; + case FREEBSD_TUN: + if ((tundev = strdup(optarg)) == NULL) + err(1, NULL); + FreeBSD_tun = 1; + break; case 0: /* Long option. */ break; @@ -365,6 +377,13 @@ if (family == AF_UNIX) errx(1, "cannot use -U and --sctp"); } + if (FreeBSD_tun) { + 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 +583,8 @@ if (s) close(s); + if (tun_fd) + close(tun_fd); exit(ret); } @@ -840,7 +861,7 @@ stdin_fd = -1; /* stdin */ - pfd[POLL_STDIN].fd = stdin_fd; + pfd[POLL_STDIN].fd = (FreeBSD_tun) ? tun_fd : stdin_fd; pfd[POLL_STDIN].events = POLLIN; /* network out */ @@ -852,7 +873,7 @@ pfd[POLL_NETIN].events = POLLIN; /* stdout */ - pfd[POLL_STDOUT].fd = stdout_fd; + pfd[POLL_STDOUT].fd = (FreeBSD_tun) ? tun_fd : stdout_fd; pfd[POLL_STDOUT].events = 0; while (1) { @@ -1440,6 +1461,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 +1522,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); diff --git a/tests/sys/net/if_tun_test.sh b/tests/sys/net/if_tun_test.sh --- a/tests/sys/net/if_tun_test.sh +++ b/tests/sys/net/if_tun_test.sh @@ -2,7 +2,7 @@ . $(atf_get_srcdir)/../common/vnet.subr -atf_test_case "235704" "cleanup" +atf_test_case "235704" "basic" "cleanup" 235704_head() { atf_set descr "Test PR #235704" @@ -24,7 +24,44 @@ vnet_cleanup } +basic_head() +{ + atf_set descr "Test if_tun using nc" + atf_set require.user root +} + +basic_body() +{ + vnet_init + + epair=$(vnet_mkepair) + + tun_duke=$(ifconfig tun create) + tun_bass=$(ifconfig tun create) + + vnet_mkjail duke ${epair}a ${tun_duke} + vnet_mkjail bass ${epair}b ${tun_bass} + + jexec duke ifconfig ${epair}a inet 10.0.0.1/24 up + jexec bass ifconfig ${epair}b inet 10.0.0.2/24 up + + jexec duke nc -u -l --tun /dev/${tun_duke} 10.0.0.1 2600 & + jexec bass nc -u --tun /dev/${tun_bass} 10.0.0.1 2600 & + + jexec duke ifconfig ${tun_duke} inet 10.100.0.1/24 10.100.0.2 up + jexec bass ifconfig ${tun_bass} inet 10.100.0.2/24 10.100.0.1 up + + atf_check -s exit:0 -o ignore \ + jexec bass ping -c 1 10.100.0.1 +} + +basic_clean() +{ + vnet_cleanup +} + atf_init_test_cases() { atf_add_test_case "235704" + atf_add_test_case "basic" }