?? tun.c
字號:
/* * OpenVPN -- An application to securely tunnel IP networks * over a single UDP port, with support for TLS-based * session authentication and key exchange, * packet encryption, packet authentication, and * packet compression. * * Copyright (C) 2002 James Yonan <jim@yonan.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* * This file is based on the TUN/TAP driver interface routines * from VTun by Maxim Krasnyansky <max_mk@yahoo.com>. */#include "config.h"#include "syshead.h"#include "tun.h"#include "fdmisc.h"#include "error.h"#include "buffer.h"#include "common.h"#include "misc.h"#include "memdbg.h"static boolis_dev_type (const char *dev, const char *dev_type, const char *match_type){ ASSERT (dev); ASSERT (match_type); if (dev_type) return !strcmp (dev_type, match_type); else return !strncmp (dev, match_type, strlen (match_type));}const char *dev_type_string(const char *dev, const char *dev_type){ if (is_dev_type (dev, dev_type, "tun")) return "tun"; else if (is_dev_type (dev, dev_type, "tap")) return "tap"; else if (is_dev_type (dev, dev_type, "null")) return "null"; else return "[unknown-dev-type]";}const char *dev_component_in_dev_node (const char *dev_node){ const char *ret; const int dirsep = '/'; if (dev_node) { ret = rindex (dev_node, dirsep); if (ret && *ret) ++ret; else ret = dev_node; if (*ret) return ret; } return NULL;}/* * Called by the open_tun function of OSes to check if we * explicitly support IPv6. * * In this context, explicit means that the OS expects us to * do something special to the tun socket in order to support * IPv6, i.e. it is not transparent. * * ipv6_explicitly_supported should be set to false if we don't * have any explicit IPv6 code in the tun device handler. * * If ipv6_explicitly_supported is true, then we have explicit * OS-specific tun dev code for handling IPv6. If so, tt->ipv6 * is set according to the --tun-ipv6 command line option. */static voidipv6_support (bool ipv6, bool ipv6_explicitly_supported, struct tuntap* tt){ tt->ipv6 = false; if (ipv6_explicitly_supported) tt->ipv6 = ipv6; else if (ipv6) msg (M_WARN, "NOTE: explicit support for IPv6 tun devices is not provided for this OS");}/* do ifconfig */voiddo_ifconfig (const char *dev, const char *dev_type, const char *ifconfig_local, const char *ifconfig_remote, int tun_mtu){ if (ifconfig_local && ifconfig_remote) { char command_line[256]; if (!is_dev_type (dev, dev_type, "tun")) msg (M_FATAL, "%s is not a tun device. The --ifconfig option works only for tun devices. You should use an --up script to ifconfig a tap device.", dev);#if defined(TARGET_LINUX) snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s pointopoint %s mtu %d", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "Linux ifconfig failed", true);#elif defined(TARGET_SOLARIS) /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "Solaris ifconfig failed", 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. */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s delete", dev); msg (M_INFO, "%s", command_line); system_check (command_line, NULL, false); msg (M_INFO, "NOTE: Tried to delete pre-existing tun instance -- No Problem if failure"); /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "OpenBSD ifconfig failed", true);#elif defined(TARGET_NETBSD) snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "NetBSD ifconfig failed", true);#elif defined(TARGET_DARWIN) /* * Darwin seems to exibit similar behaviour to OpenBSD... */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s delete", dev); msg (M_INFO, "%s", command_line); system_check (command_line, NULL, false); msg (M_INFO, "NOTE: Tried to delete pre-existing tun instance -- No Problem if failure"); /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "Darwin ifconfig failed", true);#elif defined(TARGET_FREEBSD) /* example: ifconfig tun2 10.2.0.2 10.2.0.1 mtu 1450 netmask 255.255.255.255 up */ snprintf (command_line, sizeof (command_line), IFCONFIG_PATH " %s %s %s mtu %d netmask 255.255.255.255 up", dev, ifconfig_local, ifconfig_remote, tun_mtu ); msg (M_INFO, "%s", command_line); system_check (command_line, "FreeBSD ifconfig failed", 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 }}voidclear_tuntap (struct tuntap *tuntap){ tuntap->fd = -1;#ifdef TARGET_SOLARIS tuntap->ip_fd = -1;#endif tuntap->ipv6 = false; CLEAR (tuntap->actual);}static voidopen_null (struct tuntap *tt){ clear_tuntap (tt); strncpynt (tt->actual, "null", sizeof (tt->actual));}static voidopen_tun_generic (const char *dev, const char *dev_node, bool ipv6, bool ipv6_explicitly_supported, struct tuntap *tt){ char tunname[64]; clear_tuntap (tt); ipv6_support (ipv6, ipv6_explicitly_supported, tt); if (!strcmp(dev, "null")) { open_null (tt); } else { if (dev_node) snprintf (tunname, sizeof (tunname), "%s", dev_node); else snprintf (tunname, sizeof (tunname), "/dev/%s", dev); if ((tt->fd = open (tunname, O_RDWR)) < 0) msg (M_ERR, "Cannot open tun/tap dev %s", tunname); set_nonblock (tt->fd); msg (M_INFO, "tun/tap device %s opened", tunname); strncpynt (tt->actual, dev, sizeof (tt->actual)); }}static voidclose_tun_generic (struct tuntap *tt){ if (tt->fd >= 0) close (tt->fd); clear_tuntap (tt);}#if defined(TARGET_LINUX)#ifdef HAVE_LINUX_IF_TUN_H /* New driver support */#if defined(HAVE_NETINET_IF_ETHER_H) && defined(HAVE_NETINET_IP_H) && defined(ETH_P_IPV6)#define LINUX_IPV6 1#else#define LINUX_IPV6 0#endifvoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ struct ifreq ifr; clear_tuntap (tt); ipv6_support (ipv6, LINUX_IPV6, tt); if (!strcmp(dev, "null")) { open_null (tt); } else { if (!dev_node) dev_node = "/dev/net/tun"; if ((tt->fd = open (dev_node, O_RDWR)) < 0) msg (M_ERR, "Cannot open tun/tap dev %s", dev_node); CLEAR (ifr); if (!tt->ipv6) ifr.ifr_flags = IFF_NO_PI; if (is_dev_type (dev, dev_type, "tun")) { ifr.ifr_flags |= IFF_TUN; } else if (is_dev_type (dev, 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); } if (strlen (dev) > 3) /* unit number specified? */ strncpynt (ifr.ifr_name, dev, IFNAMSIZ); if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0) msg (M_ERR, "Cannot ioctl TUNSETIFF %s", dev); set_nonblock (tt->fd); msg (M_INFO, "tun/tap device %s opened", ifr.ifr_name); strncpynt (tt->actual, ifr.ifr_name, sizeof (tt->actual)); }}#ifdef TUNSETPERSISTvoid
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -