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

📄 tun.c

📁 一个开源的VPN原码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  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

⌨️ 快捷键说明

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