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_evmen...@yahoo.com>
+ * All rights reserved.
+ * Copyright (c) 2019 Kyle Evans <kev...@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 <j...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to