⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tun.c

📁 OpenVPN -- A Secure tunneling daemon
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  OpenVPN -- An application to securely tunnel IP networks *             over a single UDP port, with support for SSL/TLS-based *             session authentication and key exchange, *             packet encryption, packet authentication, and *             packet compression. * *  Copyright (C) 2002-2003 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>. */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#include "tun.h"#include "fdmisc.h"#include "error.h"#include "buffer.h"#include "common.h"#include "misc.h"#include "memdbg.h"boolis_dev_type (const char *dev, const char *dev_type, const char *match_type){  ASSERT (match_type);  if (!dev)    return false;  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 = strrchr (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)      openvpn_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 */      openvpn_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);      if (!system_check (command_line, "Solaris ifconfig failed", false))	{	  openvpn_snprintf (command_line, sizeof (command_line),			    IFCONFIG_PATH " %s unplumb",			    dev			    );	  msg (M_INFO, "%s", command_line);	  system_check (command_line, "Solaris ifconfig unplumb failed", false);	  msg (M_FATAL, "ifconfig failed");	}#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 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 */      openvpn_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)      openvpn_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 exhibit similar behaviour to OpenBSD...       */      openvpn_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 */      openvpn_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 */      openvpn_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.  Attempted ifconfig command was: '%s'", command_line);#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, bool dynamic,		  struct tuntap *tt){  char tunname[64];  char dynamic_name[64];  bool dynamic_opened = false;  clear_tuntap (tt);  ipv6_support (ipv6, ipv6_explicitly_supported, tt);  if (!strcmp(dev, "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 is passed to up and down scripts and used as the ifconfig dev name */      strncpynt (tt->actual, (dynamic_opened ? dynamic_name : 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 */#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 */#endifvoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  struct ifreq ifr;  clear_tuntap (tt);  /*   * 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 (!strcmp(dev, "null"))    {      open_null (tt);    }  else    {      /*       * Process --dev-node       */      const char *node = dev_node;      if (!node)	node = "/dev/net/tun";      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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -