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

📄 tun.c

📁 tun虚拟网卡设备源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			    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 + -