+#ifdef ENABLE_TUNEMU
+
+ case DEVICE_TYPE_TUNEMU: {
+ char dynamic_name[256] = "";
+ device_fd = tunemu_open(dynamic_name);
+ }
+ break;
+#endif
+#ifdef HAVE_NET_IF_UTUN_H
+
+ case DEVICE_TYPE_UTUN:
+ return setup_utun();
+#endif
+
+ default:
+ device_fd = open(device, O_RDWR | O_NONBLOCK);
+ }
+
+ if(device_fd < 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", device, strerror(errno));
+ return false;
+ }
+
+#ifdef FD_CLOEXEC
+ fcntl(device_fd, F_SETFD, FD_CLOEXEC);
+#endif
+
+ // Guess what the corresponding interface is called
+
+ char *realname = NULL;
+
+#if defined(HAVE_FDEVNAME)
+ realname = fdevname(device_fd);
+#elif defined(HAVE_DEVNAME)
+ struct stat buf;
+
+ if(!fstat(device_fd, &buf)) {
+ realname = devname(buf.st_rdev, S_IFCHR);
+ }
+
+#endif
+
+ if(!realname) {
+ realname = device;
+ }
+
+ 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(DEBUG_ALWAYS, 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;
+
+ case DEVICE_TYPE_TUN: