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

📄 tun.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Confirm that GUID is a TAP-Win32 adapter. */static boolis_tap_win32 (const char *guid, const struct tap_reg *tap_reg){  const struct tap_reg *tr;  for (tr = tap_reg; tr != NULL; tr = tr->next)    {      if (guid && !strcmp (tr->guid, guid))	return true;    }  return false;}static const char *guid_to_name (const char *guid, const struct panel_reg *panel_reg){  const struct panel_reg *pr;  for (pr = panel_reg; pr != NULL; pr = pr->next)    {      if (guid && !strcmp (pr->guid, guid))	return pr->name;    }  return NULL;}static const char *name_to_guid (const char *name, const struct tap_reg *tap_reg, const struct panel_reg *panel_reg){  const struct panel_reg *pr;  for (pr = panel_reg; pr != NULL; pr = pr->next)    {      if (name && !strcmp (pr->name, name) && is_tap_win32 (pr->guid, tap_reg))	return pr->guid;    }  return NULL;}/* * Lookup a --dev-node adapter name in the registry * returning the GUID and optional actual_name. */const char *get_device_guid (const char *name,		 char *actual_name,		 int actual_name_size,		 struct gc_arena *gc){  const struct tap_reg *tr;  const struct panel_reg *pr;  const struct tap_reg *tap_reg = get_tap_reg (gc);  const struct panel_reg *panel_reg = get_panel_reg (gc);  struct buffer ret = alloc_buf_gc (256, gc);  struct buffer actual;  buf_set_write (&actual, actual_name, actual_name_size);  /* Make sure we have at least one TAP adapter */  if (!tap_reg)    {      msg (M_FATAL, "There are no TAP-Win32 adapters on this system.  You should be able to create a TAP-Win32 adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Win32 virtual ethernet adapter.");    }  /* If --dev-node not specified, look for a default TAP adapter */  if (!name)    {      const char *act;      if (tap_reg->next)	msg (M_FATAL, "You have more than one TAP-Win32 adapter on this system.  You must use the --dev-node option to tell me which one to use.  Use openvpn --show-adapters to see a list.");      act = guid_to_name (tap_reg->guid, panel_reg);      buf_printf (&ret, "%s", tap_reg->guid);      if (act)	buf_printf (&actual, "%s", act);      else	buf_printf (&actual, "NULL");      return BSTR (&ret);    }  /* Check if GUID was explicitly specified as --dev-node parameter */  if (is_tap_win32 (name, tap_reg))    {      const char *act = guid_to_name (name, panel_reg);      buf_printf (&ret, "%s", name);      if (act)	buf_printf (&actual, "%s", act);      else	buf_printf (&actual, "NULL");      return BSTR (&ret);    }  /* Lookup TAP adapter in network connections list */  {    const char *guid = name_to_guid (name, tap_reg, panel_reg);    if (guid)      {	buf_printf (&actual, "%s", name);	buf_printf (&ret, "%s", guid);	return BSTR (&ret);      }  }  msg (M_FATAL, "TAP-Win32 adapter '%s' not found.  Use openvpn --show-adapters to show a list of TAP-WIN32 adapters on this system.  Remember that if you are specifying a TAP-Win32 adapter by GUID for the --dev-node option, enclose the GUID in braces, for example: {4E22992D-0780-4B8F-AC18-5F1DDBE13E09}", name);  return NULL;}/* * Given an adapter index, return a pointer to the * IP_ADAPTER_INFO structure for that adapter. */static PIP_ADAPTER_INFOget_adapt_info (DWORD index){  struct gc_arena gc = gc_new ();  ULONG size = 0;  DWORD status;  if (index != (DWORD)~0)    {      if ((status = GetAdaptersInfo (NULL, &size)) != ERROR_BUFFER_OVERFLOW)	{	  msg (M_INFO, "GetAdaptersInfo #1 failed [%u] (status=%u) : %s",	       (unsigned int)index,	       (unsigned int)status,	       strerror_win32 (status, &gc));	}      else	{	  PIP_ADAPTER_INFO pi = (PIP_ADAPTER_INFO) gc_malloc (size, false, &gc);	  if ((status = GetAdaptersInfo (pi, &size)) != NO_ERROR)	    {	      msg (M_INFO, "GetAdaptersInfo #2 failed [%u] (status=%u) : %s",		   (unsigned int)index,		   (unsigned int)status,		   strerror_win32 (status, &gc));	      gc_free (&gc);	      return NULL;	    }	  /* find index in the linked list */	  {	    PIP_ADAPTER_INFO a;	    for (a = pi; a != NULL; a = a->Next)	      {		if (a->Index == index)		  {		    gc_free (&gc);		    return a;		  }	      }	  }	}    }  gc_free (&gc);  return NULL;}/* * Given an adapter index, return true if the adapter * is DHCP disabled. */static booldhcp_disabled (DWORD index){  PIP_ADAPTER_INFO a = get_adapt_info (index);  if (a)    {      if (!a->DhcpEnabled)	return true;    }  return false;}/* * Delete all temporary address/netmask pairs which were added * to adapter (given by index) by previous calls to AddIPAddress. */static voiddelete_temp_addresses (DWORD index){  PIP_ADAPTER_INFO a = get_adapt_info (index);  if (a)    {      PIP_ADDR_STRING ip = &a->IpAddressList;      while (ip)	{	  DWORD status;	  const DWORD context = ip->Context;	  if ((status = DeleteIPAddress ((ULONG) context)) == NO_ERROR)	    {	      msg (M_INFO, "Successfully deleted previously set dynamic IP/netmask: %s/%s",		   ip->IpAddress.String,		   ip->IpMask.String);	    }	  else	    {	      const char *empty = "0.0.0.0";	      if (strcmp (ip->IpAddress.String, empty)		  || strcmp (ip->IpMask.String, empty))		msg (M_INFO, "NOTE: could not delete previously set dynamic IP/netmask: %s/%s (status=%u)",		     ip->IpAddress.String,		     ip->IpMask.String,		     (unsigned int)status);	    }	  ip = ip->Next;	}    }}/* * Get interface index for use with IP Helper API functions. */static DWORDget_interface_index (const char *guid){  struct gc_arena gc = gc_new ();  ULONG index;  DWORD status;  wchar_t wbuf[256];  snwprintf (wbuf, SIZE (wbuf), L"\\DEVICE\\TCPIP_%S", guid);  wbuf [SIZE(wbuf) - 1] = 0;  if ((status = GetAdapterIndex (wbuf, &index)) != NO_ERROR)    {      msg (M_INFO, "NOTE: could not get adapter index for %S, status=%u : %s",	   wbuf,	   (unsigned int)status,	   strerror_win32 (status, &gc));      gc_free (&gc);      return (DWORD)~0;    }  else    {      gc_free (&gc);      return index;    }}/* * Convert DHCP options from the command line / config file * into a raw DHCP-format options string. */static voidwrite_dhcp_u8 (struct buffer *buf, const int type, const int data){  if (!buf_safe (buf, 3))    msg (M_FATAL, "write_dhcp_u8: buffer overflow building DHCP options");  buf_write_u8 (buf, type);  buf_write_u8 (buf, 1);  buf_write_u8 (buf, data);}static voidwrite_dhcp_u32_array (struct buffer *buf, const int type, const uint32_t *data, const unsigned int len){  if (len > 0)    {      int i;      const int size = len * sizeof (uint32_t);      if (!buf_safe (buf, 2 + size))	msg (M_FATAL, "write_dhcp_u32_array: buffer overflow building DHCP options");      if (size < 1 || size > 255)	msg (M_FATAL, "write_dhcp_u32_array: size (%d) must be > 0 and <= 255", size);      buf_write_u8 (buf, type);      buf_write_u8 (buf, size);      for (i = 0; i < len; ++i)	buf_write_u32 (buf, data[i]);    }}static voidwrite_dhcp_str (struct buffer *buf, const int type, const char *str){  const int len = strlen (str);  if (!buf_safe (buf, 2 + len))    msg (M_FATAL, "write_dhcp_str: buffer overflow building DHCP options");  if (len < 1 || len > 255)    msg (M_FATAL, "write_dhcp_str: string '%s' must be > 0 bytes and <= 255 bytes", str);  buf_write_u8 (buf, type);  buf_write_u8 (buf, len);  buf_write (buf, str, len);}static voidbuild_dhcp_options_string (struct buffer *buf, const struct tuntap_options *o){  if (o->domain)    write_dhcp_str (buf, 15, o->domain);  if (o->netbios_scope)    write_dhcp_str (buf, 47, o->netbios_scope);  if (o->netbios_node_type)    write_dhcp_u8 (buf, 46, o->netbios_node_type);  write_dhcp_u32_array (buf, 6, (uint32_t*)o->dns, o->dns_len);  write_dhcp_u32_array (buf, 44, (uint32_t*)o->wins, o->wins_len);  write_dhcp_u32_array (buf, 42, (uint32_t*)o->ntp, o->ntp_len);  write_dhcp_u32_array (buf, 45, (uint32_t*)o->nbdd, o->nbdd_len);}voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  struct gc_arena gc = gc_new ();  char device_path[256];  const char *device_guid = NULL;  DWORD len;  netcmd_semaphore_lock ();  ipv6_support (ipv6, false, tt);  if (tt->type == DEV_TYPE_NULL)    {      open_null (tt);      gc_free (&gc);      return;    }  else if (tt->type == DEV_TYPE_TAP || tt->type == DEV_TYPE_TUN)    {      ;    }  else    {      msg (M_FATAL|M_NOPREFIX, "Unknown virtual device type: '%s'", dev);    }  /*   * Lookup the device name in the registry, using the --dev-node high level name.   */  {    char guid_buffer[256];    /* translate high-level device name into a device instance       GUID using the registry */    device_guid = get_device_guid (dev_node, guid_buffer, sizeof (guid_buffer), &gc);    tt->actual_name = string_alloc (guid_buffer, NULL);  }  /*   * Open Windows TAP-Win32 adapter   */  openvpn_snprintf (device_path, sizeof(device_path), "%s%s%s",		    USERMODEDEVICEDIR,		    device_guid,		    TAPSUFFIX);  tt->hand = CreateFile (			 device_path,			 GENERIC_READ | GENERIC_WRITE,			 0, /* was: FILE_SHARE_READ */			 0,			 OPEN_EXISTING,			 FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,			 0			 );  if (tt->hand == INVALID_HANDLE_VALUE)    msg (M_ERR, "CreateFile failed on TAP device: %s", device_path);  msg (M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path);  /* get driver version info */  {    ULONG info[3];    CLEAR (info);    if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_VERSION,			 &info, sizeof (info),			 &info, sizeof (info), &len, NULL))      {	msg (D_TUNTAP_INFO, "TAP-Win32 Driver Version %d.%d %s",	     (int) info[0],	     (int) info[1],	     (info[2] ? "(DEBUG)" : ""));      }    if ( !(info[0] > TAP_WIN32_MIN_MAJOR	   || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)) )      msg (M_FATAL, "ERROR:  This version of " PACKAGE_NAME " requires a TAP-Win32 driver that is at least version %d.%d -- If you recently upgraded your " PACKAGE_NAME " distribution, a reboot is probably required at this point to get Windows to see the new driver.",	   TAP_WIN32_MIN_MAJOR,	   TAP_WIN32_MIN_MINOR);  }  /* get driver MTU */  {    ULONG mtu;    if (DeviceIoControl (tt->hand, TAP_IOCTL_GET_MTU,			 &mtu, sizeof (mtu),			 &mtu, sizeof (mtu), &len, NULL))      {	tt->post_open_mtu = (int) mtu;	msg (D_MTU_INFO, "TAP-Win32 MTU=%d", (int) mtu);      }  }  /* set point-to-point mode if TUN device */  if (tt->type == DEV_TYPE_TUN)    {      in_addr_t ep[2];      ep[0] = htonl (tt->local);      ep[1] = htonl (tt->remote_netmask);      if (!tt->did_ifconfig_setup)	{	  msg (M_FATAL, "ERROR: --dev tun also requires --ifconfig");	}      if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_POINT_TO_POINT,			    ep, sizeof (ep),			    ep, sizeof (ep), &len, NULL))	msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set Point-to-Point mode, which is required for --dev tun");    }  /* should we tell the TAP-Win32 driver to masquerade as a DHCP server as a means     of setting the adapter address? */  if (tt->did_ifconfig_setup && tt->options.ip_win32_type == IPW32_SET_DHCP_MASQ)    {      uint32_t ep[4];      /* We will answer DHCP requests with a reply to set IP/subnet to these values */      ep[0] = htonl (tt->local);      ep[1] = htonl (tt->adapter_netmask);      /* At what IP address should the DHCP server masquerade at? */      if (tt->type == DEV_TYPE_TUN)	{	  ep[2] = htonl (tt->remote_netmask);	  if (tt->options.dhcp_masq_custom_offset)	    msg (M_WARN, "WARNING: because you are using '--dev tun' mode, the '--ip-win32 dynamic [offset]' option is ignoring the offset parameter");	}      else	{	  in_addr_t dsa; /* DHCP server addr */	  ASSERT (tt->type == DEV_TYPE_TAP);	  if (tt->options.dhcp_masq_offset < 0)	    dsa = (tt->local | (~tt->adapter_netmask)) + tt->options.dhcp_masq_offset;	  else	    dsa = (tt->local & tt->adapter_netmask) + tt->options.dhcp_masq_offset;	  if (dsa == tt->local)	    msg (M_FATAL, "ERROR: There is a clash between the --ifconfig local address and the internal DHCP server address -- both are set to %s -- please use the --ip-win32 dynamic option to choose a different free address from the --ifconfig subnet for the internal DHCP server", print_in_addr_t (dsa, false, &gc));	  if ((tt->local & tt->adapter_netmask) != (dsa & tt->adapter_netmask))	    msg (M_FATAL, "ERROR: --tap-win32 dynamic [offset] : offset is outside of --ifconfig subnet");	  ep[2] = htonl (dsa);	}      /* lease time in seconds */      ep[3] = (uint32_t) tt->options.dhcp_lease_time;      ASSERT (ep[3] > 0);      if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_MASQ,			    ep, sizeof (ep),			    ep, sizeof (ep), &len, NULL))	msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a DeviceIoControl call to set TAP_IOCTL_CONFIG_DHCP_MASQ mode");      msg (M_INFO, "Notified TAP-Win32 driver to set a DHCP IP/netmask of %s/%s on interface %s [DHCP-serv: %s, lease-time: %d]",	   print_in_addr_t (tt->local, false, &gc),	   print_in_addr_t (tt->adapter_netmask, false, &gc),	   device_guid,	   print_in_addr_t (ntohl(ep[2]), false, &gc),	   ep[3]	   );      /* user-supplied DHCP options capability */      if (tt->options.dhcp_options)	{	  struct buffer buf = alloc_buf (256);	  build_dhcp_options_string (&buf, &tt->options);	  msg (D_DHCP_OPT, "DHCP option string: %s", format_hex (BPTR (&buf), BLEN (&buf), 0, &gc));	  if (!DeviceIoControl (tt->hand, TAP_IOCTL_CONFIG_DHCP_SET_OPT,				BPTR (&buf), BLEN (&buf),				BPTR (&buf), BLEN (&buf), &len, NULL))	    msg (M_FATAL, "ERROR: The TAP-Win32 driver rejected a TAP_IOCTL_CONFIG_DHCP_SET_OPT DeviceIoControl call");	  free_buf (&buf);	}    }#if 1  /* set driver media status to 'connected' */  {    ULONG status = TRUE;    if (!DeviceIoControl (tt->hand, TAP_IOCTL_SET_MEDIA_STATUS,			  &status, sizeof (status),			  &status, sizeof (status), &len, NULL))      msg (M_WARN, "WARNING: The TAP-Win32 driver rejected a TAP_IOCTL_SET_MEDIA_STATUS DeviceIoControl call.");  }#endif  /* possible wait for adapter to come up */  {    int s = tt->options.tap_sleep;    if (s)      {	msg (M_INFO, "Sleeping for %d s

⌨️ 快捷键说明

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