mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 12:02:28 +02:00
wintun: implement opening wintun device
To open wintun device, we cannot use "\\.\Global\Wintun<luid>" path as before. To get device path which we supply to CreateFile, we have to use SetupAPI to: - enumerate network adapters with "wintun" as component id - for each adapter save its guid - open device information set - for each item in set - open corresponding registry key to get net_cfg_instance_id - get symbolic link name of device interface by instance id - path will be symbolic link name of device instance matched with adapter's guid See https://github.com/OpenVPN/openvpn3/blob/master/openvpn/tun/win/tunutil.hpp and https://github.com/WireGuard/wireguard-go/blob/master/tun/wintun/wintun_win dows.go for implementation examples. Signed-off-by: Lev Stipakov <lev@openvpn.net> Acked-by: Simon Rozman <simon@rozman.si> Message-Id: <1573148729-27339-4-git-send-email-lstipakov@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg19029.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
c0658271be
commit
e64b4a9e68
@ -139,5 +139,5 @@ openvpn_LDADD = \
|
||||
$(OPTIONAL_DL_LIBS)
|
||||
if WIN32
|
||||
openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h
|
||||
openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt
|
||||
openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt -lsetupapi
|
||||
endif
|
||||
|
@ -91,7 +91,7 @@
|
||||
</ClCompile>
|
||||
<ResourceCompile />
|
||||
<Link>
|
||||
<AdditionalDependencies>legacy_stdio_definitions.lib;Ncrypt.lib;libssl.lib;libcrypto.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;Fwpuclnt.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>legacy_stdio_definitions.lib;Ncrypt.lib;libssl.lib;libcrypto.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;Fwpuclnt.lib;Rpcrt4.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
@ -117,7 +117,7 @@
|
||||
</ClCompile>
|
||||
<ResourceCompile />
|
||||
<Link>
|
||||
<AdditionalDependencies>legacy_stdio_definitions.lib;Ncrypt.lib;libssl.lib;libcrypto.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;Fwpuclnt.lib;Rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>legacy_stdio_definitions.lib;Ncrypt.lib;libssl.lib;libcrypto.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;Fwpuclnt.lib;Rpcrt4.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
@ -303,4 +303,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -58,6 +58,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
const static GUID GUID_DEVCLASS_NET = { 0x4d36e972L, 0xe325, 0x11ce, { 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 } };
|
||||
const static GUID GUID_DEVINTERFACE_NET = { 0xcac88484, 0x7515, 0x4c03, { 0x82, 0xe6, 0x71, 0xa8, 0x7a, 0xba, 0xc3, 0x61 } };
|
||||
|
||||
/* #define SIMULATE_DHCP_FAILED */ /* simulate bad DHCP negotiation */
|
||||
|
||||
#define NI_TEST_FIRST (1<<0)
|
||||
@ -3444,7 +3447,123 @@ tun_finalize(
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct tap_reg *
|
||||
static const struct device_instance_id_interface *
|
||||
get_device_instance_id_interface(struct gc_arena* gc)
|
||||
{
|
||||
HDEVINFO dev_info_set;
|
||||
DWORD err;
|
||||
struct device_instance_id_interface *first = NULL;
|
||||
struct device_instance_id_interface *last = NULL;
|
||||
|
||||
dev_info_set = SetupDiGetClassDevsEx(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
if (dev_info_set == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
err = GetLastError();
|
||||
msg(M_FATAL, "Error [%u] opening device information set key: %s", (unsigned int)err, strerror_win32(err, gc));
|
||||
}
|
||||
|
||||
for (DWORD i = 0;; ++i)
|
||||
{
|
||||
SP_DEVINFO_DATA device_info_data;
|
||||
BOOL res;
|
||||
HKEY dev_key;
|
||||
char net_cfg_instance_id_string[] = "NetCfgInstanceId";
|
||||
char net_cfg_instance_id[256];
|
||||
char device_instance_id[256];
|
||||
DWORD len;
|
||||
DWORD data_type;
|
||||
LONG status;
|
||||
ULONG dev_interface_list_size;
|
||||
CONFIGRET cr;
|
||||
struct buffer dev_interface_list;
|
||||
|
||||
ZeroMemory(&device_info_data, sizeof(SP_DEVINFO_DATA));
|
||||
device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
res = SetupDiEnumDeviceInfo(dev_info_set, i, &device_info_data);
|
||||
if (!res)
|
||||
{
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
dev_key = SetupDiOpenDevRegKey(dev_info_set, &device_info_data, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
|
||||
if (dev_key == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
len = sizeof(net_cfg_instance_id);
|
||||
data_type = REG_SZ;
|
||||
status = RegQueryValueEx(dev_key,
|
||||
net_cfg_instance_id_string,
|
||||
NULL,
|
||||
&data_type,
|
||||
net_cfg_instance_id,
|
||||
&len);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
|
||||
len = sizeof(device_instance_id);
|
||||
res = SetupDiGetDeviceInstanceId(dev_info_set, &device_info_data, device_instance_id, len, &len);
|
||||
if (!res)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
|
||||
cr = CM_Get_Device_Interface_List_Size(&dev_interface_list_size,
|
||||
(LPGUID)& GUID_DEVINTERFACE_NET,
|
||||
device_instance_id,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
|
||||
if (cr != CR_SUCCESS)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
|
||||
dev_interface_list = alloc_buf_gc(dev_interface_list_size, gc);
|
||||
cr = CM_Get_Device_Interface_List((LPGUID)& GUID_DEVINTERFACE_NET, device_instance_id,
|
||||
BPTR(&dev_interface_list),
|
||||
dev_interface_list_size,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
|
||||
if (cr != CR_SUCCESS)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
|
||||
struct device_instance_id_interface* dev_if;
|
||||
ALLOC_OBJ_CLEAR_GC(dev_if, struct device_instance_id_interface, gc);
|
||||
dev_if->net_cfg_instance_id = string_alloc(net_cfg_instance_id, gc);
|
||||
dev_if->device_interface_list = string_alloc(BSTR(&dev_interface_list), gc);
|
||||
|
||||
/* link into return list */
|
||||
if (!first)
|
||||
{
|
||||
first = dev_if;
|
||||
}
|
||||
if (last)
|
||||
{
|
||||
last->next = dev_if;
|
||||
}
|
||||
last = dev_if;
|
||||
|
||||
next:
|
||||
RegCloseKey(dev_key);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(dev_info_set);
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
static const struct tap_reg *
|
||||
get_tap_reg(struct gc_arena *gc)
|
||||
{
|
||||
HKEY adapter_key;
|
||||
@ -3541,11 +3660,13 @@ get_tap_reg(struct gc_arena *gc)
|
||||
if (status == ERROR_SUCCESS && data_type == REG_SZ)
|
||||
{
|
||||
if (!strcmp(component_id, TAP_WIN_COMPONENT_ID) ||
|
||||
!strcmp(component_id, "root\\" TAP_WIN_COMPONENT_ID))
|
||||
!strcmp(component_id, "root\\" TAP_WIN_COMPONENT_ID) ||
|
||||
!strcmp(component_id, WINTUN_COMPONENT_ID))
|
||||
{
|
||||
struct tap_reg *reg;
|
||||
ALLOC_OBJ_CLEAR_GC(reg, struct tap_reg, gc);
|
||||
reg->guid = string_alloc(net_cfg_instance_id, gc);
|
||||
reg->wintun = !strcmp(component_id, WINTUN_COMPONENT_ID);
|
||||
|
||||
/* link into return list */
|
||||
if (!first)
|
||||
@ -3569,7 +3690,7 @@ get_tap_reg(struct gc_arena *gc)
|
||||
return first;
|
||||
}
|
||||
|
||||
const struct panel_reg *
|
||||
static const struct panel_reg *
|
||||
get_panel_reg(struct gc_arena *gc)
|
||||
{
|
||||
LONG status;
|
||||
@ -3776,7 +3897,7 @@ show_tap_win_adapters(int msglev, int warnlev)
|
||||
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]:");
|
||||
msg(msglev, "Available TAP-WIN32 / Wintun adapters [name, GUID, driver]:");
|
||||
|
||||
/* loop through each TAP-Windows adapter registry entry */
|
||||
for (tr = tap_reg; tr != NULL; tr = tr->next)
|
||||
@ -3788,7 +3909,7 @@ show_tap_win_adapters(int msglev, int warnlev)
|
||||
{
|
||||
if (!strcmp(tr->guid, pr->guid))
|
||||
{
|
||||
msg(msglev, "'%s' %s", pr->name, tr->guid);
|
||||
msg(msglev, "'%s' %s %s", pr->name, tr->guid, tr->wintun ? "wintun" : "tap-windows6");
|
||||
++links;
|
||||
}
|
||||
}
|
||||
@ -3907,6 +4028,7 @@ get_unspecified_device_guid(const int device_number,
|
||||
int actual_name_size,
|
||||
const struct tap_reg *tap_reg_src,
|
||||
const struct panel_reg *panel_reg_src,
|
||||
bool *wintun,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
const struct tap_reg *tap_reg = tap_reg_src;
|
||||
@ -3956,6 +4078,10 @@ get_unspecified_device_guid(const int device_number,
|
||||
/* Save GUID for return value */
|
||||
ret = alloc_buf_gc(256, gc);
|
||||
buf_printf(&ret, "%s", tap_reg->guid);
|
||||
if (wintun != NULL)
|
||||
{
|
||||
*wintun = tap_reg->wintun;
|
||||
}
|
||||
return BSTR(&ret);
|
||||
}
|
||||
|
||||
@ -4733,6 +4859,7 @@ tap_allow_nonadmin_access(const char *dev_node)
|
||||
sizeof(actual_buffer),
|
||||
tap_reg,
|
||||
panel_reg,
|
||||
NULL,
|
||||
&gc);
|
||||
|
||||
if (!device_guid)
|
||||
@ -5267,9 +5394,9 @@ netsh_get_id(const char *dev_node, struct gc_arena *gc)
|
||||
}
|
||||
else
|
||||
{
|
||||
guid = get_unspecified_device_guid(0, BPTR(&actual), BCAP(&actual), tap_reg, panel_reg, gc);
|
||||
guid = get_unspecified_device_guid(0, BPTR(&actual), BCAP(&actual), tap_reg, panel_reg, NULL, gc);
|
||||
|
||||
if (get_unspecified_device_guid(1, NULL, 0, tap_reg, panel_reg, gc)) /* ambiguous if more than one TAP-Windows adapter */
|
||||
if (get_unspecified_device_guid(1, NULL, 0, tap_reg, panel_reg, NULL, gc)) /* ambiguous if more than one TAP-Windows adapter */
|
||||
{
|
||||
guid = NULL;
|
||||
}
|
||||
@ -5541,7 +5668,8 @@ void
|
||||
open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt)
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
char device_path[256];
|
||||
char tuntap_device_path[256];
|
||||
char *path = NULL;
|
||||
const char *device_guid = NULL;
|
||||
DWORD len;
|
||||
bool dhcp_masq = false;
|
||||
@ -5571,6 +5699,8 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
{
|
||||
const struct tap_reg *tap_reg = get_tap_reg(&gc);
|
||||
const struct panel_reg *panel_reg = get_panel_reg(&gc);
|
||||
const struct device_instance_id_interface *device_instance_id_interface = get_device_instance_id_interface(&gc);
|
||||
|
||||
char actual_buffer[256];
|
||||
|
||||
at_least_one_tap_win(tap_reg);
|
||||
@ -5586,24 +5716,22 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
}
|
||||
|
||||
/* Open Windows TAP-Windows adapter */
|
||||
openvpn_snprintf(device_path, sizeof(device_path), "%s%s%s",
|
||||
openvpn_snprintf(tuntap_device_path, sizeof(tuntap_device_path), "%s%s%s",
|
||||
USERMODEDEVICEDIR,
|
||||
device_guid,
|
||||
TAP_WIN_SUFFIX);
|
||||
|
||||
tt->hand = CreateFile(
|
||||
device_path,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, /* was: FILE_SHARE_READ */
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
|
||||
0
|
||||
);
|
||||
tt->hand = CreateFile(tuntap_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_ERR, "CreateFile failed on TAP device: %s", tuntap_device_path);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -5613,43 +5741,78 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
/* Try opening all TAP devices until we find one available */
|
||||
while (true)
|
||||
{
|
||||
bool is_picked_device_wintun = false;
|
||||
device_guid = get_unspecified_device_guid(device_number,
|
||||
actual_buffer,
|
||||
sizeof(actual_buffer),
|
||||
tap_reg,
|
||||
panel_reg,
|
||||
&is_picked_device_wintun,
|
||||
&gc);
|
||||
|
||||
if (!device_guid)
|
||||
{
|
||||
msg(M_FATAL, "All TAP-Windows adapters on this system are currently in use.");
|
||||
msg(M_FATAL, "All %s adapters on this system are currently in use.", tt->wintun ? "wintun" : "TAP - Windows");
|
||||
}
|
||||
|
||||
/* Open Windows TAP-Windows adapter */
|
||||
openvpn_snprintf(device_path, sizeof(device_path), "%s%s%s",
|
||||
USERMODEDEVICEDIR,
|
||||
device_guid,
|
||||
TAP_WIN_SUFFIX);
|
||||
if (tt->wintun)
|
||||
{
|
||||
const struct device_instance_id_interface* dev_if;
|
||||
|
||||
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 (!is_picked_device_wintun)
|
||||
{
|
||||
/* wintun driver specified but picked adapter is not wintun, proceed to next one */
|
||||
goto next;
|
||||
}
|
||||
|
||||
path = NULL;
|
||||
for (dev_if = device_instance_id_interface; dev_if != NULL; dev_if = dev_if->next)
|
||||
{
|
||||
if (strcmp(dev_if->net_cfg_instance_id, device_guid) == 0)
|
||||
{
|
||||
path = (char *)dev_if->device_interface_list;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (path == NULL)
|
||||
{
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_picked_device_wintun)
|
||||
{
|
||||
/* tap-windows6 driver specified but picked adapter is wintun, proceed to next one */
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* Open Windows TAP-Windows adapter */
|
||||
openvpn_snprintf(tuntap_device_path, sizeof(tuntap_device_path), "%s%s%s",
|
||||
USERMODEDEVICEDIR,
|
||||
device_guid,
|
||||
TAP_WIN_SUFFIX);
|
||||
path = tuntap_device_path;
|
||||
}
|
||||
|
||||
tt->hand = CreateFile(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(D_TUNTAP_INFO, "CreateFile failed on TAP device: %s", device_path);
|
||||
msg(D_TUNTAP_INFO, "CreateFile failed on %s device: %s", tt->wintun ? "wintun" : "TAP", tuntap_device_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
next:
|
||||
device_number++;
|
||||
}
|
||||
}
|
||||
@ -5659,10 +5822,11 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
tt->actual_name = string_alloc(actual_buffer, NULL);
|
||||
}
|
||||
|
||||
msg(M_INFO, "TAP-WIN32 device [%s] opened: %s", tt->actual_name, device_path);
|
||||
msg(M_INFO, "%s device [%s] opened: %s", tt->wintun ? "Wintun" : "TAP-WIN32", tt->actual_name, path);
|
||||
tt->adapter_index = get_adapter_index(device_guid);
|
||||
|
||||
/* get driver version info */
|
||||
if (!tt->wintun)
|
||||
{
|
||||
ULONG info[3];
|
||||
CLEAR(info);
|
||||
@ -5702,6 +5866,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
}
|
||||
|
||||
/* get driver MTU */
|
||||
if (!tt->wintun)
|
||||
{
|
||||
ULONG mtu;
|
||||
if (DeviceIoControl(tt->hand, TAP_WIN_IOCTL_GET_MTU,
|
||||
@ -5761,7 +5926,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
|
||||
/* set point-to-point mode if TUN device */
|
||||
|
||||
if (tt->type == DEV_TYPE_TUN)
|
||||
if ((tt->type == DEV_TYPE_TUN) && !tt->wintun)
|
||||
{
|
||||
if (!tt->did_ifconfig_setup && !tt->did_ifconfig_ipv6_setup)
|
||||
{
|
||||
@ -5816,7 +5981,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
|
||||
/* should we tell the TAP-Windows driver to masquerade as a DHCP server as a means
|
||||
* of setting the adapter address? */
|
||||
if (dhcp_masq)
|
||||
if (dhcp_masq && !tt->wintun)
|
||||
{
|
||||
uint32_t ep[4];
|
||||
|
||||
@ -5894,6 +6059,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
|
||||
}
|
||||
|
||||
/* set driver media status to 'connected' */
|
||||
if (!tt->wintun)
|
||||
{
|
||||
ULONG status = TRUE;
|
||||
if (!DeviceIoControl(tt->hand, TAP_WIN_IOCTL_SET_MEDIA_STATUS,
|
||||
|
@ -27,6 +27,8 @@
|
||||
#ifdef _WIN32
|
||||
#include <winioctl.h>
|
||||
#include <tap-windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <cfgmgr32.h>
|
||||
#endif
|
||||
|
||||
#include "buffer.h"
|
||||
@ -38,6 +40,10 @@
|
||||
#include "misc.h"
|
||||
#include "networking.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WINTUN_COMPONENT_ID "wintun"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(TARGET_ANDROID)
|
||||
|
||||
#define TUN_ADAPTER_INDEX_INVALID ((DWORD)-1)
|
||||
@ -340,6 +346,7 @@ route_order(void)
|
||||
struct tap_reg
|
||||
{
|
||||
const char *guid;
|
||||
bool wintun;
|
||||
struct tap_reg *next;
|
||||
};
|
||||
|
||||
@ -350,6 +357,13 @@ struct panel_reg
|
||||
struct panel_reg *next;
|
||||
};
|
||||
|
||||
struct device_instance_id_interface
|
||||
{
|
||||
const char *net_cfg_instance_id;
|
||||
const char *device_interface_list;
|
||||
struct device_instance_id_interface *next;
|
||||
};
|
||||
|
||||
int ascii2ipset(const char *name);
|
||||
|
||||
const char *ipset2ascii(int index);
|
||||
|
Loading…
Reference in New Issue
Block a user