Hi, testing today's "master" for problems due to the SVN merger (what bit ecrist on FreeBSD), I noticed a number of problems on NetBSD with the way tun/tap devices are handled, and (not) cleaned up at session end.
The attached patch cleans up the tun.c code for NetBSD, and has been tested with IPv4 + IPv6, TUN mode, TUN/top-subnet mode and TAP mode, and passes all tests *except* TAP+IPv6 (and that one seems to be a NetBSD kernel side issue, still investigating). David, please ACK and merge :-) gert -- USENET is *not* the non-clickable part of WWW! //www.muc.de/~gert/ Gert Doering - Munich, Germany g...@greenie.muc.de fax: +49-89-35655025 g...@net.informatik.tu-muenchen.de
From e5c787261e973ee0638b940f6b4f0e7767890e00 Mon Sep 17 00:00:00 2001 From: Gert Doering <g...@medat.de> List-Post: openvpn-devel@lists.sourceforge.net Date: Fri, 16 Sep 2011 19:51:09 +0200 Subject: [PATCH] platform cleanup for NetBSD: make TAP devices work (need to go via multiplex device /dev/tap) cleanup TUN devices at program end ("ifconfig tunX destroy") correctly setup TUN devices for "topology subnet" don't try to put TAP devices into TUNSIFHEAD mode (get rid of error message) tested on NetBSD 5.1_STABLE / Sparc64 Signed-off-by: Gert Doering <g...@medat.de> --- syshead.h | 4 +++ tun.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/syshead.h b/syshead.h index e208d4c..f10ae04 100644 --- a/syshead.h +++ b/syshead.h @@ -207,6 +207,10 @@ #include <net/if.h> #endif +#ifdef TARGET_NETBSD +#include <net/if_tap.h> +#endif + #ifdef TARGET_LINUX #if defined(HAVE_NETINET_IF_ETHER_H) diff --git a/tun.c b/tun.c index aa17c36..a71909c 100644 --- a/tun.c +++ b/tun.c @@ -946,16 +946,6 @@ do_ifconfig (struct tuntap *tt, # define NETBSD_MULTI_AF #endif - /* as on OpenBSD and Darwin, destroy and re-create tun<x> interface - */ - argv_printf (&argv, "%s %s destroy", IFCONFIG_PATH, actual ); - argv_msg (M_INFO, &argv); - openvpn_execve_check (&argv, es, 0, "NetBSD ifconfig destroy failed"); - - argv_printf (&argv, "%s %s create", IFCONFIG_PATH, actual ); - argv_msg (M_INFO, &argv); - openvpn_execve_check (&argv, es, S_FATAL, "NetBSD ifconfig create failed"); - if (tun) argv_printf (&argv, "%s %s %s %s mtu %d netmask 255.255.255.255 up", @@ -966,6 +956,19 @@ do_ifconfig (struct tuntap *tt, tun_mtu ); else + if ( tt->topology == TOP_SUBNET ) + { + argv_printf (&argv, + "%s %s %s %s mtu %d netmask %s up", + IFCONFIG_PATH, + actual, + ifconfig_local, + ifconfig_local, + tun_mtu, + ifconfig_remote_netmask + ); + } + else /* * NetBSD has distinct tun and tap devices * so we don't need the "link0" extra parameter to specify we want to do @@ -1265,6 +1268,30 @@ open_tun_generic (const char *dev, const char *dev_type, const char *dev_node, * explicit unit number. Try opening /dev/[dev]n * where n = [0, 255]. */ +#ifdef TARGET_NETBSD + /* on NetBSD, tap (but not tun) devices are opened by + * opening /dev/tap and then querying the system about the + * actual device name (tap0, tap1, ...) assigned + */ + if ( dynamic && strcmp( dev, "tap" ) == 0 ) + { + struct ifreq ifr; + if ((tt->fd = open ( "/dev/tap", O_RDWR)) < 0) + { + msg (M_FATAL, "Cannot allocate NetBSD TAP dev dynamically"); + } + if ( ioctl( tt->fd, TAPGIFNAME, (void*)&ifr ) < 0 ) + { + msg (M_FATAL, "Cannot query NetBSD TAP device name"); + } + CLEAR(dynamic_name); + strncpy( dynamic_name, ifr.ifr_name, sizeof(dynamic_name)-1 ); + dynamic_opened = true; + openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dynamic_name ); + } + else +#endif + if (dynamic && !has_digit((unsigned char *)dev)) { int i; @@ -2085,24 +2112,49 @@ open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tu ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */ #ifdef NETBSD_MULTI_AF - i = 1; - if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */ + if ( tt->type == DEV_TYPE_TUN ) { - msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno)); + i = 1; + if (ioctl (tt->fd, TUNSIFHEAD, &i) < 0) /* multi-af mode on */ + { + msg (M_WARN | M_ERRNO, "ioctl(TUNSIFHEAD): %s", strerror(errno)); + } } #endif } } +/* the current way OpenVPN handles tun devices on NetBSD leads to + * lingering tunX interfaces after close -> for a full cleanup, they + * need to be explicitely destroyed + */ void close_tun (struct tuntap *tt) { - /* TODO: we really should cleanup non-persistant tunX with - * "ifconfig tunX destroy" here... + /* only tun devices need destroying, tap devices auto-self-destruct */ - if (tt) + if (tt && tt->type != DEV_TYPE_TUN ) { close_tun_generic (tt); + free(tt); + } + else if (tt) + { + struct gc_arena gc = gc_new (); + struct argv argv; + + /* setup command, close tun dev (clears tt->actual_name!), run command + */ + + argv_init (&argv); + argv_printf (&argv, "%s %s destroy", + IFCONFIG_PATH, tt->actual_name); + + close_tun_generic (tt); + + argv_msg (M_INFO, &argv); + openvpn_execve_check (&argv, NULL, 0, "NetBSD 'destroy tun interface' failed (non-critical)"); + free (tt); } } -- 1.6.4
pgpVdJIgrZB4m.pgp
Description: PGP signature