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...

Kyle Evans kevans at FreeBSD.org
Wed May 8 02:32:17 UTC 2019


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 at yahoo.com>
+ * All rights reserved.
+ * Copyright (c) 2019 Kyle Evans <kevans at 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 at 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 ***


More information about the svn-src-all mailing list