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