From ac685f112deb7eafc047c718da094a8b160182ad Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 9 Apr 2016 18:39:40 +0200 Subject: [PATCH] Use devname() if available to support devfs cloning on BSD. Some BSD flavors allow opening /dev/tun and/or /dev/tap, which automatically create a new tun or tap interface with an unused number. To find out which number the interface got, you have to call devname() on the device file that was opened. The semantics are different from the way Linux's /dev/tun works though. In particular, after closing the device, the interface will continue to exist. Restarting tincd would cause the old interface to stay around, and a new one to be created. One could add a tinc-down script with the following line: ifconfig $INTERFACE destroy But that is still no guarantee that restarting tinc will give you the same interface. So the default tun and tap device will stay /dev/tun0 and /dev/tap0 for all BSD flavors to avoid surprises for existing users. --- configure.ac | 2 +- src/bsd/device.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 3b781ba..61917f8 100644 --- a/configure.ac +++ b/configure.ac @@ -187,7 +187,7 @@ AC_CHECK_TYPES([socklen_t, struct ether_header, struct arphdr, struct ether_arp, dnl Checks for library functions. AC_TYPE_SIGNAL -AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev], +AC_CHECK_FUNCS([asprintf daemon fchmod flock ftime fork get_current_dir_name gettimeofday mlockall pselect putenv random select strdup strerror strsignal strtol system unsetenv usleep vsyslog writev devname fdevname], [], [], [#include "src/have.h"] ) diff --git a/src/bsd/device.c b/src/bsd/device.c index b58db8a..70e0b0b 100644 --- a/src/bsd/device.c +++ b/src/bsd/device.c @@ -60,7 +60,7 @@ static device_type_t device_type = DEVICE_TYPE_TUN; #endif static bool setup_device(void) { - char *type; + // Find out which device file to open if(!get_config_string(lookup_config(config_tree, "Device"), &device)) { if(routing_mode == RMODE_ROUTER) @@ -69,10 +69,9 @@ static bool setup_device(void) { device = xstrdup(DEFAULT_TAP_DEVICE); } - if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) - iface = xstrdup(strrchr(device, '/') ? strrchr(device, '/') + 1 : device); - else if(strcmp(iface, strrchr(device, '/') ? strrchr(device, '/') + 1 : device)) - logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); + // Find out if it's supposed to be a tun or a tap device + + char *type; if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "tun")) @@ -96,6 +95,8 @@ static bool setup_device(void) { device_type = DEVICE_TYPE_TAP; } + // Open the device + switch(device_type) { #ifdef ENABLE_TUNEMU case DEVICE_TYPE_TUNEMU: { @@ -117,6 +118,27 @@ static bool setup_device(void) { fcntl(device_fd, F_SETFD, FD_CLOEXEC); #endif + // Guess what the corresponding interface is called + + char *realname; + +#if defined(HAVE_FDEVNAME) + realname = fdevname(device_fd) ? : device; +#elif defined(HAVE_DEVNAME) + struct stat buf; + if(!fstat(device_fd, &buf)) + realname = devname(buf.st_rdev, S_IFCHR) ? : device; +#else + realname = device; +#endif + + if(!get_config_string(lookup_config(config_tree, "Interface"), &iface)) + iface = xstrdup(strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname); + else if(strcmp(iface, strrchr(realname, '/') ? strrchr(realname, '/') + 1 : realname)) + logger(LOG_WARNING, "Warning: Interface does not match Device. $INTERFACE might be set incorrectly."); + + // Configure the device as best as we can + switch(device_type) { default: device_type = DEVICE_TYPE_TUN; -- 2.25.1