Date: Fri, 25 Oct 2019 01:10:08 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r354060 - in stable/12: . 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 ... Message-ID: <201910250110.x9P1A8bl014107@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Fri Oct 25 01:10:08 2019 New Revision: 354060 URL: https://svnweb.freebsd.org/changeset/base/354060 Log: MFC tun/tap merge: r347241, r347394, r347404, r347483, r351220, r351229, r352148, r353056-r353057, r353781-r353782, r353785-r353786, r353877 Note: A little more than just the tun/tap merge has been MFC'd to ease auditing correctness/differences, as some later commits were cherry-picked back to tun+tap. r347241: 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. r347394: tuntap: Properly detach tap ifp r347404: tuntap: Don't down tap interfaces if LINK0 is set r347483: tuntap: Improve style No functional change. tun_flags of the tuntap_driver was renamed to ident_flags to reflect the fact that it's a subset of the tun_flags that identifies a tuntap device. This maps more easily (visually) to the TUN_DRIVER_IDENT_MASK that masks off the bits of tun_flags that are applicable to tuntap driver ident. This is a purely cosmetic change. r351220: if_tuntap: minor improvements Rewrite a loop to avoid duplicating the exit condition. Simplify mask processing in tunpoll(). Fix minor typos. r351229: tuntap: belatedly add MODULE_VERSION for if_tun and if_tap When tun/tap were merged, appropriate MODULE_VERSION should have been added for things like modfind(2) to continue to do the right thing with the old names. r352148: Remove empty tap/tun modules directories after r347241 r353056: if_tuntap: add a busy/unbusy mechanism, replace destroy OPEN check A future commit will create device aliases when a tuntap device is renamed so that it's still easily found in /dev after the rename. Said mechanism will want to keep the tun alive long enough to either realize that it's about to go away or complete the alias creation, even if the alias is about to get destroyed. While we're introducing it, using it to prevent open devices from going away makes plenty of sense and keeps the logic on waking up tun_destroy clean, so we don't have multiple places trying to cv_broadcast unless it's still in use elsewhere. r353057: if_tuntap: create /dev aliases when a tuntap device gets renamed Currently, if you do: $ ifconfig tun0 create $ ifconfig tun0 name wg0 $ ls -l /dev | egrep 'wg|tun' You will see tun0, but no wg0. In fact, it's slightly more annoying to make the association between the new name and the old name in order to open the device (if it hadn't been opened during the rename). Register an eventhandler for ifnet_arrival_events and catch interface renames. We can determine if the ifnet is a tun easily enough from the if_dname, which matches the cevsw.d_name from the associated tuntap_driver. Some locking dance is required because renames don't require the device to be opened, so it could go away in the middle of handling the ioctl, but as soon as we've verified this isn't the case we can attempt to busy the tun and either bail out if the tun device is dying, or we can proceed with the rename. We only create these aliases on a best-effort basis. Renaming a tun device to "usbctl", which doesn't exist as an ifnet but does as a /dev, is clearly not that disastrous, but we can't and won't create a /dev for that. r353781: tuntap(4): Drop TUN_IASET This flag appears to have been effectively unused since introduction to if_tun(4) -- drop it now. r353782: tuntap(4): break out after setting TUN_DSTADDR This is now the only flag we set in this loop, terminate early. r353785: tuntap(4): Use make_dev_s to avoid si_drv1 race This allows us to avoid some dance in tunopen for dealing with the possibility of dev->si_drv1 being NULL as it's set prior to the devfs node being created in all cases. There's still the possibility that the tun device hasn't been fully initialized, since that's done after the devfs node was created. Alleviate this by returning ENXIO if we're not to that point of tuncreate yet. This work is what sparked r353128, full initialization of cloned devices w/ specified make_dev_args. r353786: tuntap(4): use cdevpriv w/ dtor for last close instead of d_close cdevpriv dtors will be called when the reference count on the associated struct file drops to 0, while d_close can be unreliable for cleaning up state at "last close" for a number of reasons. As far as tunclose/tundtor is concerned the difference is minimal, so make the switch. r353877: tuntap(4): properly declare if_tun and if_tap modules Simply adding MODULE_VERSION does not do the trick, because the modules haven't been declared. This should actually fix modfind/kldstat, which r351229 aimed and failed to do. This should make vm-bhyve do the right thing again when using the ports version, rather than the latest version not in ports. Relnotes: yes Added: stable/12/sys/modules/if_tuntap/ - copied from r347241, head/sys/modules/if_tuntap/ stable/12/sys/net/if_tuntap.c - copied, changed from r354059, stable/12/sys/net/if_tun.c Deleted: stable/12/sys/modules/if_tap/ stable/12/sys/modules/if_tun/ stable/12/sys/net/if_tap.c stable/12/sys/net/if_tapvar.h stable/12/sys/net/if_tun.c Modified: stable/12/UPDATING stable/12/sbin/ifconfig/ifconfig.c stable/12/share/man/man4/tap.4 stable/12/share/man/man4/tun.4 stable/12/sys/amd64/conf/GENERIC stable/12/sys/amd64/conf/MINIMAL stable/12/sys/arm/conf/DOCKSTAR stable/12/sys/arm/conf/DREAMPLUG-1001 stable/12/sys/arm/conf/EFIKA_MX stable/12/sys/arm/conf/IMX53 stable/12/sys/arm/conf/IMX6 stable/12/sys/arm/conf/TEGRA124 stable/12/sys/arm64/conf/GENERIC stable/12/sys/conf/NOTES stable/12/sys/conf/files stable/12/sys/i386/conf/GENERIC stable/12/sys/mips/conf/ERL stable/12/sys/mips/conf/OCTEON1 stable/12/sys/modules/Makefile stable/12/sys/modules/if_tuntap/Makefile stable/12/sys/net/if_tap.h stable/12/sys/powerpc/conf/GENERIC stable/12/sys/powerpc/conf/GENERIC64 stable/12/sys/powerpc/conf/MPC85XX stable/12/sys/powerpc/conf/MPC85XXSPE stable/12/sys/powerpc/conf/QORIQ64 stable/12/sys/riscv/conf/GENERIC stable/12/sys/sparc64/conf/GENERIC Directory Properties: stable/12/ (props changed) Modified: stable/12/UPDATING ============================================================================== --- stable/12/UPDATING Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/UPDATING Fri Oct 25 01:10:08 2019 (r354060) @@ -16,6 +16,14 @@ from older versions of FreeBSD, try WITHOUT_CLANG and the tip of head, and then rebuild without this option. The bootstrap process from older version of current across the gcc/clang cutover is a bit fragile. +20191024: + 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. + 20190913: ntpd no longer by default locks its pages in memory, allowing them to be paged out by the kernel. Use rlimit memlock to restore Modified: stable/12/sbin/ifconfig/ifconfig.c ============================================================================== --- stable/12/sbin/ifconfig/ifconfig.c Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sbin/ifconfig/ifconfig.c Fri Oct 25 01:10:08 2019 (r354060) @@ -136,8 +136,16 @@ static struct module_map_entry { const char *kldname; } module_map[] = { { + .ifname = "tun", + .kldname = "if_tuntap", + }, + { + .ifname = "tap", + .kldname = "if_tuntap", + }, + { .ifname = "vmnet", - .kldname = "if_tap", + .kldname = "if_tuntap", }, { .ifname = "ipsec", Modified: stable/12/share/man/man4/tap.4 ============================================================================== --- stable/12/share/man/man4/tap.4 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/share/man/man4/tap.4 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/share/man/man4/tun.4 ============================================================================== --- stable/12/share/man/man4/tun.4 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/share/man/man4/tun.4 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/amd64/conf/GENERIC ============================================================================== --- stable/12/sys/amd64/conf/GENERIC Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/amd64/conf/GENERIC Fri Oct 25 01:10:08 2019 (r354060) @@ -308,7 +308,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: stable/12/sys/amd64/conf/MINIMAL ============================================================================== --- stable/12/sys/amd64/conf/MINIMAL Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/amd64/conf/MINIMAL Fri Oct 25 01:10:08 2019 (r354060) @@ -125,7 +125,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: stable/12/sys/arm/conf/DOCKSTAR ============================================================================== --- stable/12/sys/arm/conf/DOCKSTAR Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/DOCKSTAR Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm/conf/DREAMPLUG-1001 ============================================================================== --- stable/12/sys/arm/conf/DREAMPLUG-1001 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/DREAMPLUG-1001 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm/conf/EFIKA_MX ============================================================================== --- stable/12/sys/arm/conf/EFIKA_MX Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/EFIKA_MX Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm/conf/IMX53 ============================================================================== --- stable/12/sys/arm/conf/IMX53 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/IMX53 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm/conf/IMX6 ============================================================================== --- stable/12/sys/arm/conf/IMX6 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/IMX6 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm/conf/TEGRA124 ============================================================================== --- stable/12/sys/arm/conf/TEGRA124 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm/conf/TEGRA124 Fri Oct 25 01:10:08 2019 (r354060) @@ -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: stable/12/sys/arm64/conf/GENERIC ============================================================================== --- stable/12/sys/arm64/conf/GENERIC Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/arm64/conf/GENERIC Fri Oct 25 01:10:08 2019 (r354060) @@ -271,7 +271,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: stable/12/sys/conf/NOTES ============================================================================== --- stable/12/sys/conf/NOTES Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/conf/NOTES Fri Oct 25 01:10:08 2019 (r354060) @@ -895,11 +895,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: stable/12/sys/conf/files ============================================================================== --- stable/12/sys/conf/files Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/conf/files Fri Oct 25 01:10:08 2019 (r354060) @@ -4152,8 +4152,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: stable/12/sys/i386/conf/GENERIC ============================================================================== --- stable/12/sys/i386/conf/GENERIC Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/i386/conf/GENERIC Fri Oct 25 01:10:08 2019 (r354060) @@ -309,7 +309,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: stable/12/sys/mips/conf/ERL ============================================================================== --- stable/12/sys/mips/conf/ERL Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/mips/conf/ERL Fri Oct 25 01:10:08 2019 (r354060) @@ -151,7 +151,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: stable/12/sys/mips/conf/OCTEON1 ============================================================================== --- stable/12/sys/mips/conf/OCTEON1 Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/mips/conf/OCTEON1 Fri Oct 25 01:10:08 2019 (r354060) @@ -256,7 +256,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: stable/12/sys/modules/Makefile ============================================================================== --- stable/12/sys/modules/Makefile Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/modules/Makefile Fri Oct 25 01:10:08 2019 (r354060) @@ -170,8 +170,7 @@ SUBDIR= \ if_lagg \ ${_if_ndis} \ ${_if_stf} \ - if_tap \ - if_tun \ + if_tuntap \ if_vlan \ if_vxlan \ iflib \ Modified: stable/12/sys/modules/if_tuntap/Makefile ============================================================================== --- head/sys/modules/if_tuntap/Makefile Wed May 8 02:32:11 2019 (r347241) +++ stable/12/sys/modules/if_tuntap/Makefile Fri Oct 25 01:10:08 2019 (r354060) @@ -31,5 +31,4 @@ alias_debug: .PHONY .endif .endif - .include <bsd.kmod.mk> Modified: stable/12/sys/net/if_tap.h ============================================================================== --- stable/12/sys/net/if_tap.h Fri Oct 25 00:47:37 2019 (r354059) +++ stable/12/sys/net/if_tap.h Fri Oct 25 01:10:08 2019 (r354060) @@ -40,24 +40,22 @@ #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) -#define TAPGIFNAME _IOR('t', 93, struct ifreq) +/* + * 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 TUNGIFNAME /* VMware ioctl's */ #define VMIO_SIOCSIFFLAGS _IOWINT('V', 0) Copied and modified: stable/12/sys/net/if_tuntap.c (from r354059, stable/12/sys/net/if_tun.c) ============================================================================== --- stable/12/sys/net/if_tun.c Fri Oct 25 00:47:37 2019 (r354059, copy source) +++ stable/12/sys/net/if_tuntap.c Fri Oct 25 01:10:08 2019 (r354060) @@ -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. * @@ -46,9 +76,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> @@ -57,89 +90,131 @@ #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 cdev *tun_dev; - u_short tun_flags; /* misc flags */ +struct tuntap_softc { + TAILQ_ENTRY(tuntap_softc) tun_list; + struct cdev *tun_alias; + struct cdev *tun_dev; + u_short tun_flags; /* misc flags */ #define TUN_OPEN 0x0001 #define TUN_INITED 0x0002 -#define TUN_RCOLL 0x0004 -#define TUN_IASET 0x0008 +#define TUN_UNUSED1 0x0008 #define TUN_DSTADDR 0x0010 #define TUN_LMODE 0x0020 #define TUN_RWAIT 0x0040 #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) +#define TUN_DRIVER_IDENT_MASK (TUN_L2 | TUN_VMNET) +#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 selinfo tun_rsel; /* read select */ - struct mtx tun_mtx; /* protect mutable softc fields */ - struct cv tun_cv; /* protect against ref'd dev destroy */ + pid_t tun_pid; /* owning pid */ + struct ifnet *tun_ifp; /* the interface */ + struct sigio *tun_sigio; /* async I/O info */ + struct tuntap_driver *tun_drv; /* appropriate driver */ + struct selinfo tun_rsel; /* read select */ + struct mtx tun_mtx; /* softc field mutex */ + struct cv tun_cv; /* for ref'd dev destroy */ + struct ether_addr tun_ether; /* remote address */ + int tun_busy; /* busy count */ }; -#define TUN2IFP(sc) ((sc)->tun_ifp) +#define TUN2IFP(sc) ((sc)->tun_ifp) -#define TUNDEBUG if (tundebug) if_printf +#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_LOCK_ASSERT(tp) mtx_assert(&(tp)->tun_mtx, MA_OWNED); + +#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 eventhandler_tag arrival_tag; +static eventhandler_tag clone_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."); + "IP tunnel software network interface"); SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RWTUN, &tundclone, 0, - "Enable legacy devfs interface creation."); + "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 tun_create_device(struct tuntap_driver *drv, int unit, + struct ucred *cr, struct cdev **dev, const char *name); +static int tun_busy_locked(struct tuntap_softc *tp); +static void tun_unbusy_locked(struct tuntap_softc *tp); +static int tun_busy(struct tuntap_softc *tp); +static void tun_unbusy(struct tuntap_softc *tp); + +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); +static void tundtor(void *data); +static void tunrename(void *arg, struct ifnet *ifp); 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; static d_read_t tunread; static d_write_t tunwrite; static d_ioctl_t tunioctl; @@ -164,59 +239,295 @@ 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, +static struct tuntap_driver { + struct cdevsw cdevsw; + int ident_flags; + struct unrhdr *unrhdr; + struct clonedevs *clones; + ifc_match_t *clone_match_fn; + ifc_create_t *clone_create_fn; + ifc_destroy_t *clone_destroy_fn; +} tuntap_drivers[] = { + { + .ident_flags = 0, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .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, + }, + { + .ident_flags = TUN_L2, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .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, + }, + { + .ident_flags = TUN_L2 | TUN_VMNET, + .cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDMINOR, + .d_open = tunopen, + .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) + +/* + * Mechanism for marking a tunnel device as busy so that we can safely do some + * orthogonal operations (such as operations on devices) without racing against + * tun_destroy. tun_destroy will wait on the condvar if we're at all busy or + * open, to be woken up when the condition is alleviated. + */ static int +tun_busy_locked(struct tuntap_softc *tp) +{ + + TUN_LOCK_ASSERT(tp); + if ((tp->tun_flags & TUN_DYING) != 0) { + /* + * Perhaps unintuitive, but the device is busy going away. + * Other interpretations of EBUSY from tun_busy make little + * sense, since making a busy device even more busy doesn't + * sound like a problem. + */ + return (EBUSY); + } + + ++tp->tun_busy; + return (0); +} + +static void +tun_unbusy_locked(struct tuntap_softc *tp) +{ + + TUN_LOCK_ASSERT(tp); + KASSERT(tp->tun_busy != 0, ("tun_unbusy: called for non-busy tunnel")); + + --tp->tun_busy; + /* Wake up anything that may be waiting on our busy tunnel. */ + if (tp->tun_busy == 0) + cv_broadcast(&tp->tun_cv); +} + +static int +tun_busy(struct tuntap_softc *tp) +{ + int ret; + + TUN_LOCK(tp); + ret = tun_busy_locked(tp); + TUN_UNLOCK(tp); + return (ret); +} + + +static void +tun_unbusy(struct tuntap_softc *tp) +{ + + TUN_LOCK(tp); + tun_unbusy_locked(tp); + TUN_UNLOCK(tp); +} + +/* + * 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->ident_flags; + break; + } + + if (dev_stdclone(dname, NULL, drv->cdevsw.d_name, &unit) == 1) { + found = true; + flags = drv->ident_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->ident_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 this unit number is still available that's okay. */ + 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); - if (i) { - /* No preexisting struct cdev *, create one */ - dev = make_dev(&tun_cdevsw, unit, - UID_UUCP, GID_DIALER, 0600, "%s%d", tunname, unit); - } - tuncreate(tunname, dev); + dev = NULL; + i = clone_create(&drv->clones, &drv->cdevsw, &unit, &dev, 0); + /* No preexisting struct cdev *, create one */ + if (i != 0) + i = tun_create_device(drv, unit, NULL, &dev, name); + if (i == 0) + tuncreate(dev); - return (0); + return (i); } static void @@ -224,76 +535,91 @@ 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) == 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) != 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", name, u); name = devname; } - /* No preexisting struct cdev *, create one */ - *dev = make_dev_credf(MAKEDEV_REF, &tun_cdevsw, u, cred, - UID_UUCP, GID_DIALER, 0600, "%s", name); - } - if_clone_create(name, namelen, NULL); + i = tun_create_device(drv, u, cred, dev, name); + } + if (i == 0) + 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) + if (tp->tun_busy != 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); - dev = tp->tun_dev; - bpfdetach(TUN2IFP(tp)); - if_detach(TUN2IFP(tp)); - + /* destroy_dev will take care of any alias. */ + destroy_dev(tp->tun_dev); + seldrain(&tp->tun_rsel); + knlist_clear(&tp->tun_rsel.si_note, 0); + knlist_destroy(&tp->tun_rsel.si_note); *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201910250110.x9P1A8bl014107>