From patchwork Thu Nov 7 06:45:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Lev Stipakov X-Patchwork-Id: 879 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.30.191.6]) by backend30.mail.ord1d.rsapps.net with LMTP id ODaiKw1ZxF32RAAAIUCqbw for ; Thu, 07 Nov 2019 12:49:01 -0500 Received: from proxy14.mail.ord1d.rsapps.net ([172.30.191.6]) by director9.mail.ord1d.rsapps.net with LMTP id sItSKw1ZxF1SCAAAalYnBA ; Thu, 07 Nov 2019 12:49:01 -0500 Received: from smtp31.gate.ord1d ([172.30.191.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy14.mail.ord1d.rsapps.net with LMTP id wHHLKg1ZxF33RQAAtEH5vw ; Thu, 07 Nov 2019 12:49:01 -0500 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp31.gate.ord1d.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dkim=fail (signature verification failed) header.d=gmail.com; dmarc=fail (p=none; dis=none) header.from=gmail.com X-Suspicious-Flag: YES X-Classification-ID: e1718d74-0186-11ea-bb24-525400b3ac8c-1-1 Received: from [216.105.38.7] ([216.105.38.7:48524] helo=lists.sourceforge.net) by smtp31.gate.ord1d.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id ED/F3-11949-D0954CD5; Thu, 07 Nov 2019 12:49:01 -0500 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1iSlt7-0003SE-5p; Thu, 07 Nov 2019 17:48:05 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1iSlt3-0003RT-Qd for openvpn-devel@lists.sourceforge.net; Thu, 07 Nov 2019 17:48:01 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=/WQ2/P012ewbox9ZocbU0lwiV3R5lZC/dCnAqrjKbtc=; b=Y8k7oKjUJE8CVjW27PSrLw9xtX xEsnt0EFYQMraNuVTQ3tBxJGkg4AtrUlWq1aaUymMzSwCjZ010tIjOHp6SI8KsGvpsZVZqzqPSOjr UYSkvT12k0J1cNkDK7sUS3VFnHpSDJOznacqh29c6K2jOsNSLiBHat9GTZ0gCh4QddXg=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=/WQ2/P012ewbox9ZocbU0lwiV3R5lZC/dCnAqrjKbtc=; b=DevLqA64ItK+UihpojjUEzmb8y Od7tUOPOQWi36iKo6ITZaomsn3xfg8cSl0K+ItWa34vBob0wu230+QrdAKYJNq7iCyfLiXibt/A8k 1eTphfdR8BBp1vpJovJI1VjId9AzumFGB1tlrGK+dJ15pmYpIkwnu52XoUVPQtDYSlDA=; Received: from mail-wm1-f42.google.com ([209.85.128.42]) by sfi-mx-3.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128) (Exim 4.92.2) id 1iSlsz-003xb5-FV for openvpn-devel@lists.sourceforge.net; Thu, 07 Nov 2019 17:48:01 +0000 Received: by mail-wm1-f42.google.com with SMTP id f3so3413840wmc.5 for ; Thu, 07 Nov 2019 09:47:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/WQ2/P012ewbox9ZocbU0lwiV3R5lZC/dCnAqrjKbtc=; b=hZNnlaAMuCJb1VindKvfvQQy6k/BWU40cWA7R+4sqG1xZ26S8hDvLfmP8vwouMmE3I cLq56PKK3GG2Wgo7C0y0UB5KOkVx1JRMz6RAPQerFTwvKLb45C9WZBdDVHD1v4EHA2iC KPkH6MefSSkdDLKdd6kryRJb/dmBIw9OLbPr+FIHBJxGlJ142CGGSaxi427tcUadKZ2e Fi/BYoV4eYLGn2qGjJ6pCoPj3B2KzDXMShMeKQaC0Rx++vdNOSNekU9jYEJql66BvYTk qNOTPFKCYONJqdB8Z+/dX5HpICstEYFdZXgCOY2Hkbpwd53HuBeRVL/Z9GaeSPNOmqs1 9edw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/WQ2/P012ewbox9ZocbU0lwiV3R5lZC/dCnAqrjKbtc=; b=fTM7XFk2tYtB7OVOlr1Gi6imXv4NifWcgmhvZWjXpU4qwdCLOG4njHtwsNBA7DXyK6 2ErU3mWGzoxdMT8tfflFElrxIYtn/aqX7r1HIoo+scJhhdEe8YAY6osGntp/GUo0ElMA 9OxNmftJTkDaJYqpnn9HpO2B77LJMU4oAH2+ZG6Omzc5OcBvnKlDwLtVheYsLchJ5CWK aQnjthyuOJyeUPFXI0fpV7wOrA0SoMjFK13O3Db8dCG2WFTfnuy7o7CW5P4sDPwfwsOM C/ZDibMzoeld16LlTNc91SIG6imKKHVQ+eZjbU7FSheuiQjsECwgj1akzerUwOk133D+ VTjg== X-Gm-Message-State: APjAAAXXp36mqn5TYZrRIDmce5ig2bm0P3uvcC/qy8z3ygoCD/hsAYEx r5GsqY9MjuXotfa1VpXot/ANJ5Jvl+T6Ew== X-Google-Smtp-Source: APXvYqwJnrxs3AXXKyVRgbKc8wieSFtnRhXyfTJzdREckafmnSwRzI9xuOxZGA0HuHzYyStMZk9zow== X-Received: by 2002:a05:600c:214b:: with SMTP id v11mr4266120wml.149.1573148868679; Thu, 07 Nov 2019 09:47:48 -0800 (PST) Received: from stipakov.fi (stipakov.fi. [128.199.52.117]) by smtp.gmail.com with ESMTPSA id l13sm2527752wmh.12.2019.11.07.09.47.47 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 07 Nov 2019 09:47:47 -0800 (PST) From: Lev Stipakov To: openvpn-devel@lists.sourceforge.net Date: Thu, 7 Nov 2019 19:45:25 +0200 Message-Id: <1573148729-27339-4-git-send-email-lstipakov@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1573148729-27339-1-git-send-email-lstipakov@gmail.com> References: <1573148729-27339-1-git-send-email-lstipakov@gmail.com> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: openvpn.net] -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [209.85.128.42 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (lstipakov[at]gmail.com) -0.0 RCVD_IN_MSPIKE_H2 RBL: Average reputation (+2) [209.85.128.42 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-Headers-End: 1iSlsz-003xb5-FV Subject: [Openvpn-devel] [PATCH v2 3/7] wintun: implement opening wintun device X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lev Stipakov MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Lev Stipakov To open wintun device, we cannot use "\\.\Global\Wintun" 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_windows.go for implementation examples. Signed-off-by: Lev Stipakov Acked-by: Simon Rozman Signed-off-by: Lev Stipakov <lev@openvpn.net>

This also has been ACKed and merged,  but two questions that may need some attention:

--- src/openvpn/Makefile.am | 2 +- src/openvpn/openvpn.vcxproj | 6 +- src/openvpn/tun.c | 244 +++++++++++++++++++++++++++++++++++++------- src/openvpn/tun.h | 14 +++ 4 files changed, 223 insertions(+), 43 deletions(-) diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index fbb86ad..a091ffc 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -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 diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index e77f026..9ffef9f 100644 --- a/src/openvpn/openvpn.vcxproj +++ b/src/openvpn/openvpn.vcxproj @@ -91,7 +91,7 @@ - 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) + 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) $(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories) Console @@ -117,7 +117,7 @@ - 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) + 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) $(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories) Console @@ -301,4 +301,4 @@ - \ No newline at end of file + diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index ce23eb6..37bf065 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -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); - - 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->wintun) + { + const struct device_instance_id_interface* dev_if; + + 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, diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index df935f6..19cab7e 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -27,6 +27,8 @@ #ifdef _WIN32 #include #include +#include +#include #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);