📄 tun.c
字号:
NULL, tt->local); }#endif#if defined(TARGET_LINUX)#ifdef CONFIG_FEATURE_IPROUTE /* * Set the MTU for the device */ openvpn_snprintf (command_line, sizeof (command_line), IPROUTE_PATH " link set dev %s up mtu %d", actual, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "Linux ip link set failed"); if (tun) { /* * Set the address for the device */ openvpn_snprintf (command_line, sizeof (command_line), IPROUTE_PATH " addr add dev %s local %s peer %s", actual, ifconfig_local, ifconfig_remote_netmask ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "Linux ip addr add failed"); } else { openvpn_snprintf (command_line, sizeof (command_line), IPROUTE_PATH " addr add dev %s %s/%d broadcast %s", actual, ifconfig_local, count_netmask_bits(ifconfig_remote_netmask), ifconfig_broadcast ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "Linux ip addr add failed"); } tt->did_ifconfig = true;#else if (tun) openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s pointopoint %s mtu %d", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); else openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "Linux ifconfig failed"); tt->did_ifconfig = true;#endif /*CONFIG_FEATURE_IPROUTE*/#elif defined(TARGET_SOLARIS) /* Solaris 2.6 (and 7?) cannot set all parameters in one go... * example: * ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 up * ifconfig tun2 netmask 255.255.255.255 */ if (tun) { openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); msg (M_INFO, "%s", command_line); if (!system_check (command_line, es, 0, "Solaris ifconfig phase-1 failed")) solaris_error_close (tt, es, actual); openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s netmask 255.255.255.255", actual ); } else no_tap_ifconfig (); msg (M_INFO, "%s", command_line); if (!system_check (command_line, es, 0, "Solaris ifconfig phase-2 failed")) solaris_error_close (tt, es, actual); tt->did_ifconfig = true;#elif defined(TARGET_OPENBSD) /* * OpenBSD tun devices appear to be persistent by default. It seems in order * to make this work correctly, we need to delete the previous instance * (if it exists), and re-ifconfig. Let me know if you know a better way. */ openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s destroy", actual); msg (M_INFO, "%s", command_line); system_check (command_line, es, 0, NULL); openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s create", actual); msg (M_INFO, "%s", command_line); system_check (command_line, es, 0, NULL); msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure"); /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ if (tun) openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); else openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s link0", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "OpenBSD ifconfig failed"); tt->did_ifconfig = true;#elif defined(TARGET_NETBSD) if (tun) openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); else /* * NetBSD has distinct tun and tap devices * so we don't need the "link0" extra parameter to specify we want to do * tunneling at the ethernet level */ openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s netmask %s mtu %d broadcast %s", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu, ifconfig_broadcast ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "NetBSD ifconfig failed"); tt->did_ifconfig = true;#elif defined(TARGET_DARWIN) /* * Darwin (i.e. Mac OS X) seems to exhibit similar behaviour to OpenBSD... */ openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s delete", actual); msg (M_INFO, "%s", command_line); system_check (command_line, es, 0, NULL); msg (M_INFO, "NOTE: Tried to delete pre-existing tun/tap instance -- No Problem if failure"); /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ if (tun) openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); else openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s netmask %s mtu %d up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "Mac OS X ifconfig failed"); tt->did_ifconfig = true;#elif defined(TARGET_FREEBSD) /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ if (tun) openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); else openvpn_snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s netmask %s mtu %d up", actual, ifconfig_local, ifconfig_remote_netmask, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "FreeBSD ifconfig failed"); tt->did_ifconfig = true;#elif defined (WIN32) { const char *netmask; /* * Make sure that both ifconfig addresses are part of the * same .252 subnet. */ if (tun) { verify_255_255_255_252 (tt->local, tt->remote_netmask); tt->adapter_netmask = ~3; netmask = print_in_addr_t (tt->adapter_netmask, 0, &gc); } else { netmask = ifconfig_remote_netmask; tt->adapter_netmask = tt->remote_netmask; } /* example: netsh interface ip set address my-tap static 10.3.0.1 255.255.255.0 */ openvpn_snprintf (command_line, sizeof (command_line), "netsh interface ip set address \"%s\" static %s %s", actual, ifconfig_local, netmask); switch (tt->options.ip_win32_type) { case IPW32_SET_MANUAL: msg (M_INFO, "******** NOTE: Please manually set the IP/netmask of '%s' to %s/%s (if it is not already set)", actual, ifconfig_local, netmask); break; case IPW32_SET_NETSH: if (!strcmp (actual, "NULL")) msg (M_FATAL, "Error: When using --ip-win32 netsh, if you have more than one TAP-Win32 adapter, you must also specify --dev-node"); netcmd_semaphore_lock (); msg (M_INFO, "%s", command_line); system_check (command_line, es, S_FATAL, "ERROR: netsh command failed"); netcmd_semaphore_release (); break; } tt->did_ifconfig = true; }#else msg (M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system. You should ifconfig your TUN/TAP device manually or use an --up script.");#endif } gc_free (&gc);}voidclear_tuntap (struct tuntap *tuntap){ CLEAR (*tuntap);#ifdef WIN32 tuntap->hand = NULL;#else tuntap->fd = -1;#endif#ifdef TARGET_SOLARIS tuntap->ip_fd = -1;#endif tuntap->ipv6 = false;}static voidopen_null (struct tuntap *tt){ tt->actual_name = string_alloc ("null", NULL);}#ifndef WIN32static voidopen_tun_generic (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, bool ipv6_explicitly_supported, bool dynamic, struct tuntap *tt){ char tunname[256]; char dynamic_name[256]; bool dynamic_opened = false; ipv6_support (ipv6, ipv6_explicitly_supported, tt); if (tt->type == DEV_TYPE_NULL) { open_null (tt); } else { /* * --dev-node specified, so open an explicit device node */ if (dev_node) { openvpn_snprintf (tunname, sizeof (tunname), "%s", dev_node); } else { /* * dynamic open is indicated by --dev specified without * explicit unit number. Try opening /dev/[dev]n * where n = [0, 255]. */ if (dynamic && !has_digit(dev)) { int i; for (i = 0; i < 256; ++i) { openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s%d", dev, i); openvpn_snprintf (dynamic_name, sizeof (dynamic_name), "%s%d", dev, i); if ((tt->fd = open (tunname, O_RDWR)) > 0) { dynamic_opened = true; break; } msg (D_READ_WRITE | M_ERRNO, "Tried opening %s (failed)", tunname); } if (!dynamic_opened) msg (M_FATAL, "Cannot allocate TUN/TAP dev dynamically"); } /* * explicit unit number specified */ else { openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev); } } if (!dynamic_opened) { if ((tt->fd = open (tunname, O_RDWR)) < 0) msg (M_ERR, "Cannot open TUN/TAP dev %s", tunname); } set_nonblock (tt->fd); set_cloexec (tt->fd); /* don't pass fd to scripts */ msg (M_INFO, "TUN/TAP device %s opened", tunname); /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */ tt->actual_name = string_alloc (dynamic_opened ? dynamic_name : dev, NULL); }}static voidclose_tun_generic (struct tuntap *tt){ if (tt->fd >= 0) close (tt->fd); if (tt->actual_name) free (tt->actual_name); clear_tuntap (tt);}#endif#if defined(TARGET_LINUX)#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */#ifndef HAVE_LINUX_SOCKIOS_H#error header file linux/sockios.h required#endif#if defined(HAVE_TUN_PI) && defined(HAVE_IPHDR) && defined(HAVE_IOVEC) && defined(ETH_P_IPV6) && defined(ETH_P_IP) && defined(HAVE_READV) && defined(HAVE_WRITEV)#define LINUX_IPV6 1/* #warning IPv6 ON */#else#define LINUX_IPV6 0/* #warning IPv6 OFF */#endif#if !PEDANTICvoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ struct ifreq ifr; /* * Set tt->ipv6 to true if * (a) we have the capability of supporting --tun-ipv6, and * (b) --tun-ipv6 was specified. */ ipv6_support (ipv6, LINUX_IPV6, tt); /* * We handle --dev null specially, we do not open /dev/null for this. */ if (tt->type == DEV_TYPE_NULL) { open_null (tt); } else { /* * Process --dev-node */ const char *node = dev_node; if (!node) node = "/dev/net/tun"; /* * Open the interface */ if ((tt->fd = open (node, O_RDWR)) < 0) { msg (M_WARN | M_ERRNO, "Note: Cannot open TUN/TAP dev %s", node); goto linux_2_2_fallback; } /* * Process --tun-ipv6 */ CLEAR (ifr); if (!tt->ipv6) ifr.ifr_flags = IFF_NO_PI;#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) ifr.ifr_flags |= IFF_ONE_QUEUE;#endif /* * Figure out if tun or tap device */ if (tt->type == DEV_TYPE_TUN) { ifr.ifr_flags |= IFF_TUN; } else if (tt->type == DEV_TYPE_TAP) { ifr.ifr_flags |= IFF_TAP; } else { msg (M_FATAL, "I don't recognize device %s as a tun or tap device", dev); } /* * Set an explicit name, if --dev is not tun or tap */ if (strcmp(dev, "tun") && strcmp(dev, "tap")) strncpynt (ifr.ifr_name, dev, IFNAMSIZ); /* * Use special ioctl that configures tun/tap device with the parms * we set in ifr */ if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0) { msg (M_WARN | M_ERRNO, "Note: Cannot ioctl TUNSETIFF %s", dev); goto linux_2_2_fallback; } msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name); /* * Try making the TX send queue bigger */#if defined(IFF_ONE_QUEUE) && defined(SIOCSIFTXQLEN) { struct ifreq netifr; int ctl_fd; if ((ctl_fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) { CLEAR (netifr); strncpynt (netifr.ifr_name, ifr.ifr_name, IFNAMSIZ); netifr.ifr_qlen = tt->options.txqueuelen; if (ioctl (ctl_fd, SIOCSIFTXQLEN, (void *) &netifr) >= 0) msg (D_OSBUF, "TUN/TAP TX queue length set to %d", tt->options.txqueuelen); else msg (M_WARN | M_ERRNO, "Note: Cannot set tx queue length on %s", ifr.ifr_name); close (ctl_fd); } else { msg (M_WARN | M_ERRNO, "Note: Cannot open control socket on %s", ifr.ifr_name); } }#endif set_nonblock (tt->fd); set_cloexec (tt->fd); tt->actual_name = string_alloc (ifr.ifr_name, NULL); } return; linux_2_2_fallback: msg (M_INFO, "Note: Attempting fallback to kernel 2.2 TUN/TAP interface"); if (tt->fd >= 0) { close (tt->fd); tt->fd = -1; } open_tun_generic (dev, dev_type, dev_node, ipv6, false, true, tt);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -