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-head
mailing list