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

📄 tun.c

📁 tun虚拟网卡设备源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}#elif defined(WIN32)inttun_read_queue (struct tuntap *tt, int maxsize){  if (tt->reads.iostate == IOSTATE_INITIAL)    {      DWORD len;      BOOL status;      int err;      /* reset buf to its initial state */      tt->reads.buf = tt->reads.buf_init;      len = maxsize ? maxsize : BLEN (&tt->reads.buf);      ASSERT (len <= BLEN (&tt->reads.buf));      /* the overlapped read will signal this event on I/O completion */      ASSERT (ResetEvent (tt->reads.overlapped.hEvent));      status = ReadFile(		      tt->hand,		      BPTR (&tt->reads.buf),		      len,		      &tt->reads.size,		      &tt->reads.overlapped		      );      if (status) /* operation completed immediately? */	{	  /* since we got an immediate return, we must signal the event object ourselves */	  ASSERT (SetEvent (tt->reads.overlapped.hEvent));	  tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;	  tt->reads.status = 0;	  dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]",	       (int) len,	       (int) tt->reads.size);	       	}      else	{	  err = GetLastError (); 	  if (err == ERROR_IO_PENDING) /* operation queued? */	    {	      tt->reads.iostate = IOSTATE_QUEUED;	      tt->reads.status = err;	      dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read queued [%d]",		   (int) len);	    }	  else /* error occurred */	    {	      struct gc_arena gc = gc_new ();	      ASSERT (SetEvent (tt->reads.overlapped.hEvent));	      tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN;	      tt->reads.status = err;	      dmsg (D_WIN32_IO, "WIN32 I/O: TAP Read error [%d] : %s",		   (int) len,		   strerror_win32 (status, &gc));	      gc_free (&gc);	    }	}    }  return tt->reads.iostate;}inttun_write_queue (struct tuntap *tt, struct buffer *buf){  if (tt->writes.iostate == IOSTATE_INITIAL)    {      BOOL status;      int err;       /* make a private copy of buf */      tt->writes.buf = tt->writes.buf_init;      tt->writes.buf.len = 0;      ASSERT (buf_copy (&tt->writes.buf, buf));      /* the overlapped write will signal this event on I/O completion */      ASSERT (ResetEvent (tt->writes.overlapped.hEvent));      status = WriteFile(			tt->hand,			BPTR (&tt->writes.buf),			BLEN (&tt->writes.buf),			&tt->writes.size,			&tt->writes.overlapped			);      if (status) /* operation completed immediately? */	{	  tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;	  /* since we got an immediate return, we must signal the event object ourselves */	  ASSERT (SetEvent (tt->writes.overlapped.hEvent));	  tt->writes.status = 0;	  dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write immediate return [%d,%d]",	       BLEN (&tt->writes.buf),	       (int) tt->writes.size);	       	}      else	{	  err = GetLastError (); 	  if (err == ERROR_IO_PENDING) /* operation queued? */	    {	      tt->writes.iostate = IOSTATE_QUEUED;	      tt->writes.status = err;	      dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write queued [%d]",		   BLEN (&tt->writes.buf));	    }	  else /* error occurred */	    {	      struct gc_arena gc = gc_new ();	      ASSERT (SetEvent (tt->writes.overlapped.hEvent));	      tt->writes.iostate = IOSTATE_IMMEDIATE_RETURN;	      tt->writes.status = err;	      dmsg (D_WIN32_IO, "WIN32 I/O: TAP Write error [%d] : %s",		   BLEN (&tt->writes.buf),		   strerror_win32 (err, &gc));	      gc_free (&gc);	    }	}    }  return tt->writes.iostate;}inttun_finalize (	      HANDLE h,	      struct overlapped_io *io,	      struct buffer *buf){  int ret = -1;  BOOL status;  switch (io->iostate)    {    case IOSTATE_QUEUED:      status = GetOverlappedResult(				   h,				   &io->overlapped,				   &io->size,				   FALSE				   );      if (status)	{	  /* successful return for a queued operation */	  if (buf)	    *buf = io->buf;	  ret = io->size;	  io->iostate = IOSTATE_INITIAL;	  ASSERT (ResetEvent (io->overlapped.hEvent));	  dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion success [%d]", ret);	}      else	{	  /* error during a queued operation */	  ret = -1;	  if (GetLastError() != ERROR_IO_INCOMPLETE)	    {	      /* if no error (i.e. just not finished yet),		 then DON'T execute this code */	      io->iostate = IOSTATE_INITIAL;	      ASSERT (ResetEvent (io->overlapped.hEvent));	      msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion error");	    }	}      break;    case IOSTATE_IMMEDIATE_RETURN:      io->iostate = IOSTATE_INITIAL;      ASSERT (ResetEvent (io->overlapped.hEvent));      if (io->status)	{	  /* error return for a non-queued operation */	  SetLastError (io->status);	  ret = -1;	  msg (D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion non-queued error");	}      else	{	  /* successful return for a non-queued operation */	  if (buf)	    *buf = io->buf;	  ret = io->size;	  dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued success [%d]", ret);	}      break;    case IOSTATE_INITIAL: /* were we called without proper queueing? */      SetLastError (ERROR_INVALID_FUNCTION);      ret = -1;      dmsg (D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE");      break;    default:      ASSERT (0);    }  if (buf)    buf->len = ret;  return ret;}const struct tap_reg *get_tap_reg (struct gc_arena *gc){  HKEY adapter_key;  LONG status;  DWORD len;  struct tap_reg *first = NULL;  struct tap_reg *last = NULL;  int i = 0;  status = RegOpenKeyEx(			HKEY_LOCAL_MACHINE,			ADAPTER_KEY,			0,			KEY_READ,			&adapter_key);  if (status != ERROR_SUCCESS)    msg (M_FATAL, "Error opening registry key: %s", ADAPTER_KEY);  while (true)    {      char enum_name[256];      char unit_string[256];      HKEY unit_key;      char component_id_string[] = "ComponentId";      char component_id[256];      char net_cfg_instance_id_string[] = "NetCfgInstanceId";      char net_cfg_instance_id[256];      DWORD data_type;      len = sizeof (enum_name);      status = RegEnumKeyEx(			    adapter_key,			    i,			    enum_name,			    &len,			    NULL,			    NULL,			    NULL,			    NULL);      if (status == ERROR_NO_MORE_ITEMS)	break;      else if (status != ERROR_SUCCESS)	msg (M_FATAL, "Error enumerating registry subkeys of key: %s",	     ADAPTER_KEY);      openvpn_snprintf (unit_string, sizeof(unit_string), "%s\\%s",			ADAPTER_KEY, enum_name);      status = RegOpenKeyEx(			    HKEY_LOCAL_MACHINE,			    unit_string,			    0,			    KEY_READ,			    &unit_key);      if (status != ERROR_SUCCESS)	dmsg (D_REGISTRY, "Error opening registry key: %s", unit_string);      else	{	  len = sizeof (component_id);	  status = RegQueryValueEx(				   unit_key,				   component_id_string,				   NULL,				   &data_type,				   component_id,				   &len);	  if (status != ERROR_SUCCESS || data_type != REG_SZ)	    dmsg (D_REGISTRY, "Error opening registry key: %s\\%s",		 unit_string, component_id_string);	  else	    {	      	      len = sizeof (net_cfg_instance_id);	      status = RegQueryValueEx(				       unit_key,				       net_cfg_instance_id_string,				       NULL,				       &data_type,				       net_cfg_instance_id,				       &len);	      if (status == ERROR_SUCCESS && data_type == REG_SZ)		{		  if (!strcmp (component_id, TAP_COMPONENT_ID))		    {		      struct tap_reg *reg;		      ALLOC_OBJ_CLEAR_GC (reg, struct tap_reg, gc);		      reg->guid = string_alloc (net_cfg_instance_id, gc);		      		      /* link into return list */		      if (!first)			first = reg;		      if (last)			last->next = reg;		      last = reg;		    }		}	    }	  RegCloseKey (unit_key);	}      ++i;    }  RegCloseKey (adapter_key);  return first;}const struct panel_reg *get_panel_reg (struct gc_arena *gc){  LONG status;  HKEY network_connections_key;  DWORD len;  struct panel_reg *first = NULL;  struct panel_reg *last = NULL;  int i = 0;  status = RegOpenKeyEx(			HKEY_LOCAL_MACHINE,			NETWORK_CONNECTIONS_KEY,			0,			KEY_READ,			&network_connections_key);  if (status != ERROR_SUCCESS)    msg (M_FATAL, "Error opening registry key: %s", NETWORK_CONNECTIONS_KEY);  while (true)    {      char enum_name[256];      char connection_string[256];      HKEY connection_key;      char name_data[256];      DWORD name_type;      const char name_string[] = "Name";      len = sizeof (enum_name);      status = RegEnumKeyEx(			    network_connections_key,			    i,			    enum_name,			    &len,			    NULL,			    NULL,			    NULL,			    NULL);      if (status == ERROR_NO_MORE_ITEMS)	break;      else if (status != ERROR_SUCCESS)	msg (M_FATAL, "Error enumerating registry subkeys of key: %s",	     NETWORK_CONNECTIONS_KEY);      openvpn_snprintf (connection_string, sizeof(connection_string),			"%s\\%s\\Connection",			NETWORK_CONNECTIONS_KEY, enum_name);      status = RegOpenKeyEx(			    HKEY_LOCAL_MACHINE,			    connection_string,			    0,			    KEY_READ,			    &connection_key);      if (status != ERROR_SUCCESS)	dmsg (D_REGISTRY, "Error opening registry key: %s", connection_string);      else	{	  len = sizeof (name_data);	  status = RegQueryValueEx(				   connection_key,				   name_string,				   NULL,				   &name_type,				   name_data,				   &len);	  if (status != ERROR_SUCCESS || name_type != REG_SZ)	    dmsg (D_REGISTRY, "Error opening registry key: %s\\%s\\%s",		 NETWORK_CONNECTIONS_KEY, connection_string, name_string);	  else	    {	      struct panel_reg *reg;	      ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc);	      reg->name = string_alloc (name_data, gc);	      reg->guid = string_alloc (enum_name, gc);		      	      /* link into return list */	      if (!first)		first = reg;	      if (last)		last->next = reg;	      last = reg;	    }	  RegCloseKey (connection_key);	}      ++i;    }  RegCloseKey (network_connections_key);  return first;}/* * Check that two addresses are part of the same 255.255.255.252 subnet. */voidverify_255_255_255_252 (in_addr_t local, in_addr_t remote){  struct gc_arena gc = gc_new ();  const unsigned int mask = 3;  const char *err = NULL;  if (local == remote)    {      err = "must be different";      goto error;    }  if ((local & (~mask)) != (remote & (~mask)))    {      err = "must exist within the same 255.255.255.252 subnet.  This is a limitation of --dev tun when used with the TAP-WIN32 driver";      goto error;    }  if ((local & mask) == 0      || (local & mask) == 3      || (remote & mask) == 0      || (remote & mask) == 3)    {      err = "cannot use the first or last address within a given 255.255.255.252 subnet.  This is a limitation of --dev tun when used with the TAP-WIN32 driver";      goto error;    }  gc_free (&gc);  return; error:  msg (M_FATAL, "There is a problem in your selection of --ifconfig endpoints [local=%s, remote=%s].  The local and remote VPN endpoints %s.  Try '" PACKAGE " --show-valid-subnets' option for more info.",       print_in_addr_t (local, 0, &gc),       print_in_addr_t (remote, 0, &gc),       err);  gc_free (&gc);}void show_valid_win32_tun_subnets (void){  int i;  int col = 0;  printf ("On Windows, point-to-point IP support (i.e. --dev tun)\n");  printf ("is emulated by the TAP-Win32 driver.  The major limitation\n");  printf ("imposed by this approach is that the --ifconfig local and\n");  printf ("remote endpoints must be part of the same 255.255.255.252\n");  printf ("subnet.  The following list shows examples of endpoint\n");  printf ("pairs which satisfy this requirement.  Only the final\n");  printf ("component of the IP address pairs is at issue.\n\n");  printf ("As an example, the following option would be correct:\n");  printf ("    --ifconfig 10.7.0.5 10.7.0.6 (on host A)\n");  printf ("    --ifconfig 10.7.0.6 10.7.0.5 (on host B)\n");  printf ("because [5,6] is part of the below list.\n\n");  for (i = 0; i < 256; i += 4)    {      printf("[%3d,%3d] ", i+1, i+2);      if (++col > 4)	{	  col = 0;	  printf ("\n");	}    }  if (col)    printf ("\n");}voidshow_tap_win32_adapters (int msglev, int warnlev){  struct gc_arena gc = gc_new ();  bool warn_panel_null = false;  bool warn_panel_dup = false;  bool warn_tap_dup = false;  int links;  const struct tap_reg *tr;  const struct tap_reg *tr1;  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);  msg (msglev, "Available TAP-WIN32 adapters [name, GUID]:");  /* loop through each TAP-Win32 adapter registry entry */  for (tr = tap_reg; tr != NULL; tr = tr->next)    {      links = 0;      /* loop through each network connections entry in the control panel */      for (pr = panel_reg; pr != NULL; pr = pr->next)	{	  if (!strcmp (tr->guid, pr->guid))	    {	      msg (msglev, "'%s' %s", pr->name, tr->guid);	      ++links;	    }	}      if (links > 1)	{	  warn_panel_dup = true;	}      else if (links == 0)	{	  /* a TAP adapter exists without a link from the network	     connections control panel */	  warn_panel_null = true;	  msg (msglev, "[NULL] %s", tr->guid);	}    }  /* check for TAP-Win32 adapter duplicated GUIDs */  for (tr = tap_reg; tr != NULL; tr = tr->next)    {

⌨️ 快捷键说明

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