Date: Wed, 8 May 2019 02:32:11 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r347241 - in head: . sbin/ifconfig share/man/man4 sys/amd64/conf sys/arm/conf sys/arm64/conf sys/conf sys/i386/conf sys/mips/conf sys/modules sys/modules/if_tap sys/modules/if_tun sys/m... Message-ID: <201905080232.x482WBXN088564@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Wed May 8 02:32:11 2019 New Revision: 347241 URL: https://svnweb.freebsd.org/changeset/base/347241 Log: tun/tap: merge and rename to `tuntap` tun(4) and tap(4) share the same general management interface and have a lot in common. Bugs exist in tap(4) that have been fixed in tun(4), and vice-versa. Let's reduce the maintenance requirements by merging them together and using flags to differentiate between the three interface types (tun, tap, vmnet). This fixes a couple of tap(4)/vmnet(4) issues right out of the gate: - tap devices may no longer be destroyed while they're open [0] - VIMAGE issues already addressed in tun by kp [0] emaste had removed an easy-panic-button in r240938 due to devdrn blocking. A naive glance over this leads me to believe that this isn't quite complete -- destroy_devl will only block while executing d_* functions, but doesn't block the device from being destroyed while a process has it open. The latter is the intent of the condvar in tun, so this is "fixed" (for certain definitions of the word -- it wasn't really broken in tap, it just wasn't quite ideal). ifconfig(8) also grew the ability to map an interface name to a kld, so that `ifconfig {tun,tap}0` can continue to autoload the correct module, and `ifconfig vmnet0 create` will now autoload the correct module. This is a low overhead addition. (MFC commentary) This may get MFC'd if many bugs in tun(4)/tap(4) are discovered after this, and how critical they are. Changes after this are likely easily MFC'd without taking this merge, but the merge will be easier. I have no plans to do this MFC as of now. Reviewed by: bcr (manpages), tuexen (testing, syzkaller/packetdrill) Input also from: melifaro Relnotes: yes Differential Revision: https://reviews.freebsd.org/D20044 Added: head/sys/modules/if_tuntap/ head/sys/modules/if_tuntap/Makefile (contents, props changed) head/sys/net/if_tuntap.c - copied, changed from r347240, head/sys/net/if_tun.c Deleted: head/sys/modules/if_tap/Makefile head/sys/modules/if_tun/Makefile head/sys/net/if_tap.c head/sys/net/if_tapvar.h head/sys/net/if_tun.c Modified: head/UPDATING head/sbin/ifconfig/ifconfig.c head/share/man/man4/tap.4 head/share/man/man4/tun.4 head/sys/amd64/conf/GENERIC head/sys/amd64/conf/MINIMAL head/sys/arm/conf/DOCKSTAR head/sys/arm/conf/DREAMPLUG-1001 head/sys/arm/conf/EFIKA_MX head/sys/arm/conf/IMX53 head/sys/arm/conf/IMX6 head/sys/arm/conf/TEGRA124 head/sys/arm64/conf/GENERIC head/sys/conf/NOTES head/sys/conf/files head/sys/i386/conf/GENERIC head/sys/i386/conf/MINIMAL head/sys/mips/conf/ERL head/sys/mips/conf/OCTEON1 head/sys/modules/Makefile head/sys/net/if_tap.h head/sys/powerpc/conf/GENERIC head/sys/powerpc/conf/GENERIC64 head/sys/powerpc/conf/MPC85XX head/sys/powerpc/conf/MPC85XXSPE head/sys/powerpc/conf/QORIQ64 head/sys/riscv/conf/GENERIC head/sys/sparc64/conf/GENERIC Modified: head/UPDATING ============================================================================== --- head/UPDATING Wed May 8 01:35:43 2019 (r347240) +++ head/UPDATING Wed May 8 02:32:11 2019 (r347241) @@ -31,6 +31,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20190507: + The tap(4) driver has been folded into tun(4), and the module has been + renamed to tuntap. You should update any kld_load="if_tap" or + kld_load="if_tun" entries in /etc/rc.conf, if_tap_load="YES" or + if_tun_load="YES" entries in /boot/loader.conf to load the if_tuntap + module instead, and "device tap" or "device tun" entries in kernel + config files to select the tuntap device instead. + 20190418: The following knobs have been added related to tradeoffs between safe use of the random device and availability in the absence of Modified: head/sbin/ifconfig/ifconfig.c ============================================================================== --- head/sbin/ifconfig/ifconfig.c Wed May 8 01:35:43 2019 (r347240) +++ head/sbin/ifconfig/ifconfig.c Wed May 8 02:32:11 2019 (r347241) @@ -130,6 +130,25 @@ struct ifa_order_elt { TAILQ_HEAD(ifa_queue, ifa_order_elt); +static struct module_map_entry { + const char *ifname; + const char *kldname; +} module_map[] = { + { + .ifname = "tun", + .kldname = "if_tuntap", + }, + { + .ifname = "tap", + .kldname = "if_tuntap", + }, + { + .ifname = "vmnet", + .kldname = "if_tuntap", + }, +}; + + void opt_register(struct option *p) { @@ -1413,9 +1432,10 @@ ifmaybeload(const char *name) { #define MOD_PREFIX_LEN 3 /* "if_" */ struct module_stat mstat; - int fileid, modid; - char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp; + int i, fileid, modid; + char ifname[IFNAMSIZ], *ifkind, *dp; const char *cp; + struct module_map_entry *mme; /* loading suppressed by the user */ if (noload) @@ -1429,10 +1449,27 @@ ifmaybeload(const char *name) break; } - /* turn interface and unit into module name */ - strlcpy(ifkind, "if_", sizeof(ifkind)); - strlcat(ifkind, ifname, sizeof(ifkind)); + /* Either derive it from the map or guess otherwise */ + ifkind = NULL; + for (i = 0; i < nitems(module_map); ++i) { + mme = &module_map[i]; + if (strcmp(mme->ifname, ifname) == 0) { + ifkind = strdup(mme->kldname); + if (ifkind == NULL) + err(EXIT_FAILURE, "ifmaybeload"); + break; + } + } + /* We didn't have an alias for it... we'll guess. */ + if (ifkind == NULL) { + ifkind = malloc(IFNAMSIZ + MOD_PREFIX_LEN); + + /* turn interface and unit into module name */ + strlcpy(ifkind, "if_", sizeof(ifkind)); + strlcat(ifkind, ifname, sizeof(ifkind)); + } + /* scan files in kernel */ mstat.version = sizeof(struct module_stat); for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { @@ -1450,7 +1487,7 @@ ifmaybeload(const char *name) /* already loaded? */ if (strcmp(ifname, cp) == 0 || strcmp(ifkind, cp) == 0) - return; + goto out; } } @@ -1459,6 +1496,8 @@ ifmaybeload(const char *name) * infer the names of all drivers (eg mlx4en(4)). */ (void) kldload(ifkind); +out: + free(ifkind); } static struct cmd basic_cmds[] = { Modified: head/share/man/man4/tap.4 ============================================================================== --- head/share/man/man4/tap.4 Wed May 8 01:35:43 2019 (r347240) +++ head/share/man/man4/tap.4 Wed May 8 02:32:11 2019 (r347241) @@ -1,14 +1,14 @@ .\" $FreeBSD$ .\" Based on PR#2411 .\" -.Dd November 29, 2017 +.Dd April 29, 2019 .Dt TAP 4 .Os .Sh NAME .Nm tap .Nd Ethernet tunnel software network interface .Sh SYNOPSIS -.Cd device tap +.Cd device tuntap .Sh DESCRIPTION The .Nm @@ -51,7 +51,7 @@ The network interfaces are named .Dq Li tap1 , etc., one for each control device that has been opened. These Ethernet network interfaces persist until -.Pa if_tap.ko +.Pa if_tuntap.ko module is unloaded, or until removed with "ifconfig destroy" (see below). .Pp .Nm @@ -96,7 +96,7 @@ It therefore defaults to being enabled until further n .Ef .Pp Control devices (once successfully opened) persist until -.Pa if_tap.ko +.Pa if_tuntap.ko is unloaded or the interface is destroyed. .Pp Each interface supports the usual Ethernet network interface @@ -296,27 +296,6 @@ device can also be used with the VMware port as a repl for the old .Em VMnet device driver. -The driver uses the minor number -to select between -.Nm -and -.Nm vmnet -devices. -.Em VMnet -minor numbers begin at -.Va 0x800000 -+ -.Va N ; -where -.Va N -is a -.Em VMnet -unit number. -In this case the control device is expected to be -.Pa /dev/vmnet Ns Sy N , -and the network interface will be -.Sy vmnet Ns Ar N . -Additionally, .Em VMnet devices do not .Xr ifconfig 8 Modified: head/share/man/man4/tun.4 ============================================================================== --- head/share/man/man4/tun.4 Wed May 8 01:35:43 2019 (r347240) +++ head/share/man/man4/tun.4 Wed May 8 02:32:11 2019 (r347241) @@ -2,14 +2,14 @@ .\" $FreeBSD$ .\" Based on PR#2411 .\" -.Dd November 29, 2017 +.Dd April 29, 2019 .Dt TUN 4 .Os .Sh NAME .Nm tun .Nd tunnel software network interface .Sh SYNOPSIS -.Cd device tun +.Cd device tuntap .Sh DESCRIPTION The .Nm @@ -52,7 +52,7 @@ The network interfaces are named .Dq Li tun1 , etc., one for each control device that has been opened. These network interfaces persist until the -.Pa if_tun.ko +.Pa if_tuntap.ko module is unloaded, or until removed with the .Xr ifconfig 8 command. @@ -99,7 +99,7 @@ It therefore defaults to being enabled until further n .Ef .Pp Control devices (once successfully opened) persist until -.Pa if_tun.ko +.Pa if_tuntap.ko is unloaded in the same way that network interfaces persist (see above). .Pp Each interface supports the usual network-interface Modified: head/sys/amd64/conf/GENERIC ============================================================================== --- head/sys/amd64/conf/GENERIC Wed May 8 01:35:43 2019 (r347240) +++ head/sys/amd64/conf/GENERIC Wed May 8 02:32:11 2019 (r347241) @@ -323,7 +323,7 @@ device padlock_rng # VIA Padlock RNG device rdrand_rng # Intel Bull Mountain RNG device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/amd64/conf/MINIMAL ============================================================================== --- head/sys/amd64/conf/MINIMAL Wed May 8 01:35:43 2019 (r347240) +++ head/sys/amd64/conf/MINIMAL Wed May 8 02:32:11 2019 (r347241) @@ -136,7 +136,7 @@ device padlock_rng # VIA Padlock RNG device rdrand_rng # Intel Bull Mountain RNG device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device gif # IPv6 and IPv4 tunneling # The `bpf' device enables the Berkeley Packet Filter. Modified: head/sys/arm/conf/DOCKSTAR ============================================================================== --- head/sys/arm/conf/DOCKSTAR Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/DOCKSTAR Wed May 8 02:32:11 2019 (r347241) @@ -69,7 +69,7 @@ device loop # Network loopback device md # Memory/malloc disk device pty # BSD-style compatibility pseudo ttys device random # Entropy device -device tun # Packet tunnel. +device tuntap # Packet tunnel. device ether # Required for all ethernet devices device vlan # 802.1Q VLAN support device wlan # 802.11 WLAN support Modified: head/sys/arm/conf/DREAMPLUG-1001 ============================================================================== --- head/sys/arm/conf/DREAMPLUG-1001 Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/DREAMPLUG-1001 Wed May 8 02:32:11 2019 (r347241) @@ -72,7 +72,7 @@ device loop # Network loopback device md # Memory/malloc disk device pty # BSD-style compatibility pseudo ttys device random # Entropy device -device tun # Packet tunnel. +device tuntap # Packet tunnel. device ether # Required for all ethernet devices device vlan # 802.1Q VLAN support device wlan # 802.11 WLAN support Modified: head/sys/arm/conf/EFIKA_MX ============================================================================== --- head/sys/arm/conf/EFIKA_MX Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/EFIKA_MX Wed May 8 02:32:11 2019 (r347241) @@ -60,7 +60,7 @@ device loop # Network loopback device random # Entropy device device ether # Ethernet support #device vlan # 802.1Q VLAN support -#device tun # Packet tunnel. +#device tuntap # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module Modified: head/sys/arm/conf/IMX53 ============================================================================== --- head/sys/arm/conf/IMX53 Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/IMX53 Wed May 8 02:32:11 2019 (r347241) @@ -47,7 +47,7 @@ device loop # Network loopback device random # Entropy device device ether # Ethernet support #device vlan # 802.1Q VLAN support -#device tun # Packet tunnel. +#device tuntap # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module Modified: head/sys/arm/conf/IMX6 ============================================================================== --- head/sys/arm/conf/IMX6 Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/IMX6 Wed May 8 02:32:11 2019 (r347241) @@ -51,7 +51,7 @@ device mpcore_timer device loop # Network loopback device random # Entropy device device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module Modified: head/sys/arm/conf/TEGRA124 ============================================================================== --- head/sys/arm/conf/TEGRA124 Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm/conf/TEGRA124 Wed May 8 02:32:11 2019 (r347241) @@ -45,7 +45,7 @@ device regulator device loop # Network loopback device random # Entropy device device vlan # 802.1Q VLAN support -#device tun # Packet tunnel. +#device tuntap # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/arm64/conf/GENERIC ============================================================================== --- head/sys/arm64/conf/GENERIC Wed May 8 01:35:43 2019 (r347240) +++ head/sys/arm64/conf/GENERIC Wed May 8 02:32:11 2019 (r347241) @@ -296,7 +296,7 @@ device loop # Network loopback device random # Entropy device device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/conf/NOTES ============================================================================== --- head/sys/conf/NOTES Wed May 8 01:35:43 2019 (r347240) +++ head/sys/conf/NOTES Wed May 8 02:32:11 2019 (r347241) @@ -898,11 +898,9 @@ device epair # which discards all packets sent and receives none. device edsc -# The `tap' device is a pty-like virtual Ethernet interface -device tap - -# The `tun' device implements (user-)ppp and nos-tun(8) -device tun +# The `tuntap' device implements (user-)ppp, nos-tun(8) and a pty-like virtual +# Ethernet interface +device tuntap # The `gif' device implements IPv6 over IP4 tunneling, # IPv4 over IPv6 tunneling, IPv4 over IPv4 tunneling and Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Wed May 8 01:35:43 2019 (r347240) +++ head/sys/conf/files Wed May 8 02:32:11 2019 (r347241) @@ -4079,8 +4079,7 @@ net/if_mib.c standard net/if_spppfr.c optional sppp | netgraph_sppp net/if_spppsubr.c optional sppp | netgraph_sppp net/if_stf.c optional stf inet inet6 -net/if_tun.c optional tun -net/if_tap.c optional tap +net/if_tuntap.c optional tuntap net/if_vlan.c optional vlan net/if_vxlan.c optional vxlan inet | vxlan inet6 net/ifdi_if.m optional ether pci iflib Modified: head/sys/i386/conf/GENERIC ============================================================================== --- head/sys/i386/conf/GENERIC Wed May 8 01:35:43 2019 (r347240) +++ head/sys/i386/conf/GENERIC Wed May 8 02:32:11 2019 (r347241) @@ -316,7 +316,7 @@ device padlock_rng # VIA Padlock RNG device rdrand_rng # Intel Bull Mountain RNG device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/i386/conf/MINIMAL ============================================================================== --- head/sys/i386/conf/MINIMAL Wed May 8 01:35:43 2019 (r347240) +++ head/sys/i386/conf/MINIMAL Wed May 8 02:32:11 2019 (r347241) @@ -137,7 +137,7 @@ device padlock_rng # VIA Padlock RNG device rdrand_rng # Intel Bull Mountain RNG device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device gif # IPv6 and IPv4 tunneling # The `bpf' device enables the Berkeley Packet Filter. Modified: head/sys/mips/conf/ERL ============================================================================== --- head/sys/mips/conf/ERL Wed May 8 01:35:43 2019 (r347240) +++ head/sys/mips/conf/ERL Wed May 8 02:32:11 2019 (r347241) @@ -152,7 +152,7 @@ device loop # Network loopback device random # Entropy device device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/mips/conf/OCTEON1 ============================================================================== --- head/sys/mips/conf/OCTEON1 Wed May 8 01:35:43 2019 (r347240) +++ head/sys/mips/conf/OCTEON1 Wed May 8 02:32:11 2019 (r347241) @@ -187,7 +187,7 @@ device loop # Network loopback device random # Entropy device device ether # Ethernet support device vlan # 802.1Q VLAN support -device tun # Packet tunnel. +device tuntap # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling device firmware # firmware assist module Modified: head/sys/modules/Makefile ============================================================================== --- head/sys/modules/Makefile Wed May 8 01:35:43 2019 (r347240) +++ head/sys/modules/Makefile Wed May 8 02:32:11 2019 (r347241) @@ -163,8 +163,7 @@ SUBDIR= \ if_lagg \ ${_if_ndis} \ ${_if_stf} \ - if_tap \ - if_tun \ + if_tuntap \ if_vlan \ if_vxlan \ iflib \ Added: head/sys/modules/if_tuntap/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/modules/if_tuntap/Makefile Wed May 8 02:32:11 2019 (r347241) @@ -0,0 +1,35 @@ +# $FreeBSD$ + +.PATH: ${SRCTOP}/sys/net + +KMOD= if_tuntap +SRCS= if_tuntap.c opt_inet.h opt_inet6.h + +# Symlink for backwards compatibility with systems installed at 12.0 or older +.if ${MACHINE_CPUARCH} != "powerpc" +SYMLINKS= ${KMOD}.ko ${KMODDIR}/if_tun.ko \ + ${KMOD}.ko ${KMODDIR}/if_tap.ko +.else +# Some PPC systems use msdosfs for /boot, which can't handle links or symlinks +afterinstall: alias alias_debug +alias: .PHONY + ${INSTALL} -T release -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \ + ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${KMODDIR}/if_tun.ko + ${INSTALL} -T release -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \ + ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${KMODDIR}/if_tap.ko +.if defined(DEBUG_FLAGS) && !defined(INSTALL_NODEBUG) && \ + "${MK_KERNEL_SYMBOLS}" != "no" +alias_debug: .PHONY + ${INSTALL} -T debug -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \ + ${_INSTALLFLAGS} ${PROG}.debug \ + ${DESTDIR}${KERN_DEBUGDIR}${KMODDIR}/if_tun.ko + ${INSTALL} -T debug -o ${KMODOWN} -g ${KMODGRP} -m ${KMODMODE} \ + ${_INSTALLFLAGS} ${PROG}.debug \ + ${DESTDIR}${KERN_DEBUGDIR}${KMODDIR}/if_tap.ko +.else +alias_debug: .PHONY +.endif +.endif + + +.include <bsd.kmod.mk> Modified: head/sys/net/if_tap.h ============================================================================== --- head/sys/net/if_tap.h Wed May 8 01:35:43 2019 (r347240) +++ head/sys/net/if_tap.h Wed May 8 02:32:11 2019 (r347241) @@ -40,23 +40,21 @@ #ifndef _NET_IF_TAP_H_ #define _NET_IF_TAP_H_ -/* refer to if_tapvar.h for the softc stuff */ +#include <net/if_tun.h> /* maximum receive packet size (hard limit) */ #define TAPMRU 16384 -struct tapinfo { - int baudrate; /* linespeed */ - short mtu; /* maximum transmission unit */ - u_char type; /* ethernet, tokenring, etc. */ - u_char dummy; /* place holder */ -}; +#define tapinfo tuninfo -/* ioctl's for get/set debug */ -#define TAPSDEBUG _IOW('t', 90, int) -#define TAPGDEBUG _IOR('t', 89, int) -#define TAPSIFINFO _IOW('t', 91, struct tapinfo) -#define TAPGIFINFO _IOR('t', 92, struct tapinfo) +/* + * ioctl's for get/set debug; these are aliases of TUN* ioctls, see net/if_tun.h + * for details. + */ +#define TAPSDEBUG TUNSDEBUG +#define TAPGDEBUG TUNGDEBUG +#define TAPSIFINFO TUNSIFINFO +#define TAPGIFINFO TUNGIFINFO #define TAPGIFNAME _IOR('t', 93, struct ifreq) /* VMware ioctl's */ Copied and modified: head/sys/net/if_tuntap.c (from r347240, head/sys/net/if_tun.c) ============================================================================== --- head/sys/net/if_tun.c Wed May 8 01:35:43 2019 (r347240, copy source) +++ head/sys/net/if_tuntap.c Wed May 8 02:32:11 2019 (r347241) @@ -1,6 +1,36 @@ /* $NetBSD: if_tun.c,v 1.14 1994/06/29 06:36:25 cgd Exp $ */ - /*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (C) 1999-2000 by Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * BASED ON: + * ------------------------------------------------------------------------- + * * Copyright (c) 1988, Julian Onions <jpo@cs.nott.ac.uk> * Nottingham University 1987. * @@ -45,9 +75,12 @@ #include <sys/random.h> #include <sys/ctype.h> +#include <net/ethernet.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_clone.h> +#include <net/if_dl.h> +#include <net/if_media.h> #include <net/if_types.h> #include <net/netisr.h> #include <net/route.h> @@ -56,20 +89,22 @@ #include <netinet/in.h> #endif #include <net/bpf.h> +#include <net/if_tap.h> #include <net/if_tun.h> #include <sys/queue.h> #include <sys/condvar.h> - #include <security/mac/mac_framework.h> +struct tuntap_driver; + /* * tun_list is protected by global tunmtx. Other mutable fields are * protected by tun->tun_mtx, or by their owning subsystem. tun_dev is * static for the duration of a tunnel interface. */ -struct tun_softc { - TAILQ_ENTRY(tun_softc) tun_list; +struct tuntap_softc { + TAILQ_ENTRY(tuntap_softc) tun_list; struct cdev *tun_dev; u_short tun_flags; /* misc flags */ #define TUN_OPEN 0x0001 @@ -82,60 +117,88 @@ struct tun_softc { #define TUN_ASYNC 0x0080 #define TUN_IFHEAD 0x0100 #define TUN_DYING 0x0200 +#define TUN_L2 0x0400 +#define TUN_VMNET 0x0800 #define TUN_READY (TUN_OPEN | TUN_INITED) pid_t tun_pid; /* owning pid */ struct ifnet *tun_ifp; /* the interface */ struct sigio *tun_sigio; /* information for async I/O */ + struct tuntap_driver *tun_drv; /* appropriate driver */ struct selinfo tun_rsel; /* read select */ struct mtx tun_mtx; /* protect mutable softc fields */ struct cv tun_cv; /* protect against ref'd dev destroy */ + struct ether_addr tun_ether; /* remote address */ }; #define TUN2IFP(sc) ((sc)->tun_ifp) #define TUNDEBUG if (tundebug) if_printf +#define TUN_LOCK(tp) mtx_lock(&(tp)->tun_mtx) +#define TUN_UNLOCK(tp) mtx_unlock(&(tp)->tun_mtx) + +#define TUN_VMIO_FLAG_MASK 0x0fff + /* * All mutable global variables in if_tun are locked using tunmtx, with - * the exception of tundebug, which is used unlocked, and tunclones, - * which is static after setup. + * the exception of tundebug, which is used unlocked, and the drivers' *clones, + * which are static after setup. */ static struct mtx tunmtx; static eventhandler_tag tag; static const char tunname[] = "tun"; +static const char tapname[] = "tap"; +static const char vmnetname[] = "vmnet"; static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); static int tundebug = 0; static int tundclone = 1; -static struct clonedevs *tunclones; -static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); +static int tap_allow_uopen = 0; /* allow user open() */ +static int tapuponopen = 0; /* IFF_UP on open() */ +static int tapdclone = 1; /* enable devfs cloning */ + +static TAILQ_HEAD(,tuntap_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); static struct sx tun_ioctl_sx; SX_SYSINIT(tun_ioctl_sx, &tun_ioctl_sx, "tun_ioctl"); SYSCTL_DECL(_net_link); +/* tun */ static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, "IP tunnel software network interface."); SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tundclone, 0, "Enable legacy devfs interface creation."); +/* tap */ +static SYSCTL_NODE(_net_link, OID_AUTO, tap, CTLFLAG_RW, 0, + "Ethernet tunnel software network interface"); +SYSCTL_INT(_net_link_tap, OID_AUTO, user_open, CTLFLAG_RW, &tap_allow_uopen, 0, + "Allow user to open /dev/tap (based on node permissions)"); +SYSCTL_INT(_net_link_tap, OID_AUTO, up_on_open, CTLFLAG_RW, &tapuponopen, 0, + "Bring interface up when /dev/tap is opened"); +SYSCTL_INT(_net_link_tap, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tapdclone, 0, + "Enable legacy devfs interface creation"); +SYSCTL_INT(_net_link_tap, OID_AUTO, debug, CTLFLAG_RW, &tundebug, 0, ""); + +static int tuntap_name2info(const char *name, int *unit, int *flags); static void tunclone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev); -static void tuncreate(const char *name, struct cdev *dev); +static void tuncreate(struct cdev *dev, struct tuntap_driver *); static int tunifioctl(struct ifnet *, u_long, caddr_t); static void tuninit(struct ifnet *); -static int tunmodevent(module_t, int, void *); +static void tunifinit(void *xtp); +static int tuntapmodevent(module_t, int, void *); static int tunoutput(struct ifnet *, struct mbuf *, const struct sockaddr *, struct route *ro); static void tunstart(struct ifnet *); +static void tunstart_l2(struct ifnet *); static int tun_clone_match(struct if_clone *ifc, const char *name); +static int tap_clone_match(struct if_clone *ifc, const char *name); +static int vmnet_clone_match(struct if_clone *ifc, const char *name); static int tun_clone_create(struct if_clone *, char *, size_t, caddr_t); static int tun_clone_destroy(struct if_clone *, struct ifnet *); -static struct unrhdr *tun_unrhdr; -VNET_DEFINE_STATIC(struct if_clone *, tun_cloner); -#define V_tun_cloner VNET(tun_cloner) static d_open_t tunopen; static d_close_t tunclose; @@ -163,58 +226,241 @@ static struct filterops tun_write_filterops = { .f_event = tunkqwrite, }; -static struct cdevsw tun_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDMINOR, - .d_open = tunopen, - .d_close = tunclose, - .d_read = tunread, - .d_write = tunwrite, - .d_ioctl = tunioctl, - .d_poll = tunpoll, - .d_kqfilter = tunkqfilter, - .d_name = tunname, +#define TUN_DRIVER_IDENT_MASK (TUN_L2 | TUN_VMNET) + +static struct tuntap_driver { + int tun_flags; + struct unrhdr *unrhdr; + struct cdevsw cdevsw; + struct clonedevs *clones; + ifc_match_t *clone_match_fn; + ifc_create_t *clone_create_fn; + ifc_destroy_t *clone_destroy_fn; +} tuntap_drivers[] = { + { + .tun_flags = 0, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .d_close = tunclose, + .d_read = tunread, + .d_write = tunwrite, + .d_ioctl = tunioctl, + .d_poll = tunpoll, + .d_kqfilter = tunkqfilter, + .d_name = tunname, + }, + .clone_match_fn = tun_clone_match, + .clone_create_fn = tun_clone_create, + .clone_destroy_fn = tun_clone_destroy, + }, + { + .tun_flags = TUN_L2, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .d_close = tunclose, + .d_read = tunread, + .d_write = tunwrite, + .d_ioctl = tunioctl, + .d_poll = tunpoll, + .d_kqfilter = tunkqfilter, + .d_name = tapname, + }, + .clone_match_fn = tap_clone_match, + .clone_create_fn = tun_clone_create, + .clone_destroy_fn = tun_clone_destroy, + }, + { + .tun_flags = TUN_L2 | TUN_VMNET, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .d_close = tunclose, + .d_read = tunread, + .d_write = tunwrite, + .d_ioctl = tunioctl, + .d_poll = tunpoll, + .d_kqfilter = tunkqfilter, + .d_name = vmnetname, + }, + .clone_match_fn = vmnet_clone_match, + .clone_create_fn = tun_clone_create, + .clone_destroy_fn = tun_clone_destroy, + }, }; +struct tuntap_driver_cloner { + SLIST_ENTRY(tuntap_driver_cloner) link; + struct tuntap_driver *drv; + struct if_clone *cloner; +}; + +VNET_DEFINE_STATIC(SLIST_HEAD(, tuntap_driver_cloner), tuntap_driver_cloners) = + SLIST_HEAD_INITIALIZER(tuntap_driver_cloners); + +#define V_tuntap_driver_cloners VNET(tuntap_driver_cloners) + +/* + * Sets unit and/or flags given the device name. Must be called with correct + * vnet context. + */ static int +tuntap_name2info(const char *name, int *outunit, int *outflags) +{ + struct tuntap_driver *drv; + struct tuntap_driver_cloner *drvc; + char *dname; + int flags, unit; + bool found; + + if (name == NULL) + return (EINVAL); + + /* + * Needed for dev_stdclone, but dev_stdclone will not modify, it just + * wants to be able to pass back a char * through the second param. We + * will always set that as NULL here, so we'll fake it. + */ + dname = __DECONST(char *, name); + found = false; + + KASSERT(!SLIST_EMPTY(&V_tuntap_driver_cloners), + ("tuntap_driver_cloners failed to initialize")); + SLIST_FOREACH(drvc, &V_tuntap_driver_cloners, link) { + KASSERT(drvc->drv != NULL, + ("tuntap_driver_cloners entry not properly initialized")); + drv = drvc->drv; + + if (strcmp(name, drv->cdevsw.d_name) == 0) { + found = true; + unit = -1; + flags = drv->tun_flags; + break; + } + + if (dev_stdclone(dname, NULL, drv->cdevsw.d_name, &unit) == 1) { + found = true; + flags = drv->tun_flags; + break; + } + } + + if (!found) + return (ENXIO); + + if (outunit != NULL) + *outunit = unit; + if (outflags != NULL) + *outflags = flags; + return (0); +} + +/* + * Get driver information from a set of flags specified. Masks the identifying + * part of the flags and compares it against all of the available + * tuntap_drivers. Must be called with correct vnet context. + */ +static struct tuntap_driver * +tuntap_driver_from_flags(int tun_flags) +{ + struct tuntap_driver *drv; + struct tuntap_driver_cloner *drvc; + + KASSERT(!SLIST_EMPTY(&V_tuntap_driver_cloners), + ("tuntap_driver_cloners failed to initialize")); + SLIST_FOREACH(drvc, &V_tuntap_driver_cloners, link) { + KASSERT(drvc->drv != NULL, + ("tuntap_driver_cloners entry not properly initialized")); + drv = drvc->drv; + if ((tun_flags & TUN_DRIVER_IDENT_MASK) == drv->tun_flags) + return (drv); + } + + return (NULL); +} + + + +static int tun_clone_match(struct if_clone *ifc, const char *name) { - if (strncmp(tunname, name, 3) == 0 && - (name[3] == '\0' || isdigit(name[3]))) - return (1); + int tunflags; + if (tuntap_name2info(name, NULL, &tunflags) == 0) { + if ((tunflags & TUN_L2) == 0) + return (1); + } + return (0); } static int +tap_clone_match(struct if_clone *ifc, const char *name) +{ + int tunflags; + + if (tuntap_name2info(name, NULL, &tunflags) == 0) { + if ((tunflags & (TUN_L2 | TUN_VMNET)) == TUN_L2) + return (1); + } + + return (0); +} + +static int +vmnet_clone_match(struct if_clone *ifc, const char *name) +{ + int tunflags; + + if (tuntap_name2info(name, NULL, &tunflags) == 0) { + if ((tunflags & TUN_VMNET) != 0) + return (1); + } + + return (0); +} + +static int tun_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) { + struct tuntap_driver *drv; struct cdev *dev; - int err, unit, i; + int err, i, tunflags, unit; - err = ifc_name2unit(name, &unit); + tunflags = 0; + /* The name here tells us exactly what we're creating */ + err = tuntap_name2info(name, &unit, &tunflags); if (err != 0) return (err); + drv = tuntap_driver_from_flags(tunflags); + if (drv == NULL) + return (ENXIO); + if (unit != -1) { /* If this unit number is still available that/s okay. */ - if (alloc_unr_specific(tun_unrhdr, unit) == -1) + if (alloc_unr_specific(drv->unrhdr, unit) == -1) return (EEXIST); } else { - unit = alloc_unr(tun_unrhdr); + unit = alloc_unr(drv->unrhdr); } - snprintf(name, IFNAMSIZ, "%s%d", tunname, unit); + snprintf(name, IFNAMSIZ, "%s%d", drv->cdevsw.d_name, unit); /* find any existing device, or allocate new unit number */ - i = clone_create(&tunclones, &tun_cdevsw, &unit, &dev, 0); + i = clone_create(&drv->clones, &drv->cdevsw, &unit, &dev, 0); if (i) { /* No preexisting struct cdev *, create one */ - dev = make_dev(&tun_cdevsw, unit, - UID_UUCP, GID_DIALER, 0600, "%s%d", tunname, unit); + dev = make_dev(&drv->cdevsw, unit, UID_UUCP, GID_DIALER, 0600, + "%s%d", drv->cdevsw.d_name, unit); } - tuncreate(tunname, dev); + tuncreate(dev, drv); + return (0); } @@ -223,33 +469,47 @@ tunclone(void *arg, struct ucred *cred, char *name, in struct cdev **dev) { char devname[SPECNAMELEN + 1]; - int u, i, append_unit; + struct tuntap_driver *drv; + int append_unit, i, u, tunflags; + bool mayclone; if (*dev != NULL) return; + tunflags = 0; + CURVNET_SET(CRED_TO_VNET(cred)); + if (tuntap_name2info(name, &u, &tunflags) != 0) + goto out; /* Not recognized */ + + if (u != -1 && u > IF_MAXUNIT) + goto out; /* Unit number too high */ + + mayclone = priv_check_cred(cred, PRIV_NET_IFCREATE) == 0; + if ((tunflags & TUN_L2) != 0) { + /* tap/vmnet allow user open with a sysctl */ + mayclone = (mayclone || tap_allow_uopen) && tapdclone; + } else { + mayclone = mayclone && tundclone; + } + /* * If tun cloning is enabled, only the superuser can create an * interface. */ - if (!tundclone || priv_check_cred(cred, PRIV_NET_IFCREATE) != 0) - return; + if (!mayclone) + goto out; - if (strcmp(name, tunname) == 0) { - u = -1; - } else if (dev_stdclone(name, NULL, tunname, &u) != 1) - return; /* Don't recognise the name */ - if (u != -1 && u > IF_MAXUNIT) - return; /* Unit number too high */ - if (u == -1) append_unit = 1; else append_unit = 0; - CURVNET_SET(CRED_TO_VNET(cred)); + drv = tuntap_driver_from_flags(tunflags); + if (drv == NULL) + goto out; + /* find any existing device, or allocate new unit number */ - i = clone_create(&tunclones, &tun_cdevsw, &u, dev, 0); + i = clone_create(&drv->clones, &drv->cdevsw, &u, dev, 0); if (i) { if (append_unit) { namelen = snprintf(devname, sizeof(devname), "%s%d", @@ -257,25 +517,26 @@ tunclone(void *arg, struct ucred *cred, char *name, in name = devname; } /* No preexisting struct cdev *, create one */ - *dev = make_dev_credf(MAKEDEV_REF, &tun_cdevsw, u, cred, + *dev = make_dev_credf(MAKEDEV_REF, &drv->cdevsw, u, cred, UID_UUCP, GID_DIALER, 0600, "%s", name); } if_clone_create(name, namelen, NULL); +out: CURVNET_RESTORE(); } static void -tun_destroy(struct tun_softc *tp) +tun_destroy(struct tuntap_softc *tp) { struct cdev *dev; - mtx_lock(&tp->tun_mtx); + TUN_LOCK(tp); tp->tun_flags |= TUN_DYING; if ((tp->tun_flags & TUN_OPEN) != 0) cv_wait_unlock(&tp->tun_cv, &tp->tun_mtx); else - mtx_unlock(&tp->tun_mtx); + TUN_UNLOCK(tp); CURVNET_SET(TUN2IFP(tp)->if_vnet); sx_xlock(&tun_ioctl_sx); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905080232.x482WBXN088564>