📄 tun.c
字号:
}#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 + -