From patchwork Sun Nov 16 12:11:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 4603 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:6d04:b0:7b1:439f:bdf with SMTP id e4csp2639553may; Sun, 16 Nov 2025 04:12:13 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCWyNlnFIJaSd+yProAL655Ku0SNDVgvA7mG2+ClDhnXWcTEtG36zqey0dqprO4a5/qcwtPf8f6OpJ4=@openvpn.net X-Google-Smtp-Source: AGHT+IHMCzfGFa4OZSj3e3r7H1Nb44ZXFVre+vn7KJECkSZ6F3bF0eSeRsTRkTquAC18cKoO7KYF X-Received: by 2002:a05:6808:1511:b0:450:826e:5df1 with SMTP id 5614622812f47-45095dc8b5bmr4393514b6e.19.1763295133315; Sun, 16 Nov 2025 04:12:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1763295133; cv=none; d=google.com; s=arc-20240605; b=Y//bmuxifxa+L1DS81LVt74WuGlLhf+qp78pLZYLKiqvMZcy8KAwz6NxOGp1jOWCjG YNMc6XXyK3XB1BFtcNWGcnJpmAWblpujgitb7fBceko8MMdeWPqwOr0DXJp6S+KJD3LF 7pjC11veRG0f685sdGEAjUvbfhNuFNmxaBPGiqyhf1sEzYfIExQH9giS++Djw6n4QhZP 4wUbHOhSBGv5Go7wUsJUTToQv9t9fMFvWcH3QN1vkr6gS0MTAHbtDSbBy1xYgu0Hy5h9 QycWMkWyKSr3nOmoSmGWMnm8r755b1tKycr6ecPrarwJJsXlHSL4c/tR34Z9V9i+nkoN czIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=qSBIwStst5bn9OhajQPLZcKxMTgb1g6aowEpcCGUSnY=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=Mcb/8/+YD7Wc/+c88r4uF1Sri9u6z/z09LsJcSd7o9F9cb5nGo3PqchJ0NYWZOxNr3 GeVtHikG+0xgXteuWdgdJo49X+dGVZyZfRqZ84McRu6Uu+NDHxjD7Mr3abQTaMZ20sNX N0aB1YCpgalNVmfSPuKuBMZNZlDe/67wvRGzhs1FEl5ziRh+/LG1Y8ROvOrxYVtXXrPA MryISww2Y+8y4AkwyBNL26on6LAGB0XfMxAPSc72EHh1nl2y1bAJsQsToBOMSWLqlCXj dmyuZZimz64uxj8nQidOCzyUrTGu900qtt5HLAyaFohK0IyiByTL2cGAn7ve4nw1o+wp 5fsQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=hibLmbWH; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=DcGmC4kU; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=H3M2mbfe; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 5614622812f47-450c89f88c1si32126b6e.278.2025.11.16.04.12.12 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 16 Nov 2025 04:12:13 -0800 (PST) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=hibLmbWH; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=DcGmC4kU; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=H3M2mbfe; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=qSBIwStst5bn9OhajQPLZcKxMTgb1g6aowEpcCGUSnY=; b=hibLmbWHrP90Vduw+fYaZqeivV plx7OflQQsSV2w9HTjUishVOijNXEaUcnrVgjbE0Q7UxewMTI1//yz0MSK9SYw+ebygEUgqMbbrs1 imQ7Gn+9zKTLLdZk1IHNsyaAq8Lrp3jIwRXcaawS1an+UaP3B7tw/bcasoXjgKkabyt4=; 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.95) (envelope-from ) id 1vKbc1-0003ZD-4T; Sun, 16 Nov 2025 12:12:09 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1vKbbo-0003Yi-O6 for openvpn-devel@lists.sourceforge.net; Sun, 16 Nov 2025 12:11:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: 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=EB0G+ryEcZUjeIxyE6GmxgMQRi2KehPUnANYtGrXfvA=; b=DcGmC4kU5o7bGZw2WiS0b1MwsM GyTuzvtbCWtuiZnobLhl2u4o6Xpmz7Ea4cM8OYYehMQrT10kCdBtx3+7TAzNX8Ip3ST/AFxGN6S0y XNaibhP4WVIHjzPlx9CORXV4sLCKcwnGumzOik7JXbvv1SItrQo/sZXkdq0gQo4LiBo8=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: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=EB0G+ryEcZUjeIxyE6GmxgMQRi2KehPUnANYtGrXfvA=; b=H3M2mbfep5dFQAUPVC8AkcRlr5 FarAG5oLhtrCj61VUdyeQHaUr+UzvUlhs4ue/1WVtW5BwbFPJA1zYBSYoxMQglTp4nbiZcbn3plry psyzIZONtnulbmXVDhWN0gPw5yXnKXrAP6R4Lp9WYH63245BF8qUZ+gajB8v+YHZ6WCw=; Received: from [193.149.48.134] (helo=blue.greenie.muc.de) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1vKbbn-0003UL-5C for openvpn-devel@lists.sourceforge.net; Sun, 16 Nov 2025 12:11:56 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 5AGCBm6Y004085 for ; Sun, 16 Nov 2025 13:11:48 +0100 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.1/8.18.1/Submit) id 5AGCBm51004084 for openvpn-devel@lists.sourceforge.net; Sun, 16 Nov 2025 13:11:48 +0100 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Sun, 16 Nov 2025 13:11:40 +0100 Message-ID: <20251116121146.4067-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.49.1 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-1.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Lev Stipakov Make default adapter name selection logic more robust - sometimes renaming fails because the deleted adapter name might present in the registry even though adapter is not shown anymore in enumeration. Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1vKbbn-0003UL-5C Subject: [Openvpn-devel] [PATCH v2] tapctl: refactor 'create' command 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: =?utf-8?q?1848948957922764210?= X-GMAIL-MSGID: =?utf-8?q?1848948957922764210?= From: Lev Stipakov Make default adapter name selection logic more robust - sometimes renaming fails because the deleted adapter name might present in the registry even though adapter is not shown anymore in enumeration. Ensure that adapter name doesn't contain disallowed symbols. Use --hwid ovpn-dco by default and update documentation. Change-Id: I270f679505c90ef78a5afbad1e05219f166be089 Signed-off-by: Lev Stipakov Acked-by: Gert Doering Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1374 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1374 This mail reflects revision 2 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering diff --git a/src/tapctl/main.c b/src/tapctl/main.c index 15c25ae..c92c122 100644 --- a/src/tapctl/main.c +++ b/src/tapctl/main.c @@ -71,12 +71,12 @@ L"\n" L"--name Set VPN network adapter name. Should the adapter with given \n" L" name already exist, an error is returned. If this option is not \n" - L" specified, a default adapter name is chosen by Windows. \n" + L" specified, an OpenVPN-specific default name is chosen. \n" L" Note: This name can also be specified as OpenVPN's --dev-node \n" L" option. \n" - L"--hwid Adapter hardware ID. Default value is root\\tap0901, which \n" - L" describes tap-windows6 driver. To work with ovpn-dco driver, \n" - L" driver, specify 'ovpn-dco'. \n" + L"--hwid Adapter hardware ID. Default value is ovpn-dco, which uses \n" + L" the OpenVPN Data Channel Offload driver. To work with \n" + L" tap-windows6 driver, specify root\\tap0901 or tap0901. \n" L"\n" L"Output:\n" L"\n" @@ -125,26 +125,163 @@ } /** - * Checks if adapter with given name doesn't already exist + * Locate an adapter node by its friendly name within the enumerated list. + * + * @param name Friendly name to search for. Comparison is case-insensitive. + * @param adapter_list Head of the adapter list returned by tap_list_adapters(). + * + * @return Pointer to the matching node, or NULL when not found. */ -static BOOL -is_adapter_name_available(LPCWSTR name, struct tap_adapter_node *adapter_list, BOOL log) +static struct tap_adapter_node * +find_adapter_by_name(LPCWSTR name, struct tap_adapter_node *adapter_list) { for (struct tap_adapter_node *a = adapter_list; a; a = a->pNext) { - if (wcsicmp(name, a->szName) == 0) + if (_wcsicmp(name, a->szName) == 0) { - if (log) - { - LPOLESTR adapter_id = NULL; - StringFromIID((REFIID)&a->guid, &adapter_id); - fwprintf(stderr, - L"Adapter \"%ls\" already exists (GUID %" - L"ls).\n", - a->szName, adapter_id); - CoTaskMemFree(adapter_id); - } + return a; + } + } + return NULL; +} + +/** + * Check whether the registry still reserves a given network-connection name. + * + * Windows keeps friendly names under + * \\HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network\\{NETCLASS}\\{GUID}\\Connection\\Name, + * even after an adapter is removed. netsh refuses to rename to any reserved name. + * + * @param name Friendly name to test. + * + * @return TRUE if the name exists in the registry, FALSE otherwise. + */ +static BOOL +registry_name_exists(LPCWSTR name) +{ + static const WCHAR class_key[] = + L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4d36e972-e325-11ce-bfc1-08002be10318}"; + + HKEY hClassKey = NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, class_key, 0, KEY_READ, &hClassKey) != ERROR_SUCCESS) + { + return FALSE; + } + + BOOL found = FALSE; + + for (DWORD index = 0;; ++index) + { + WCHAR adapter_id[64]; + DWORD adapter_id_len = _countof(adapter_id); + LONG result = RegEnumKeyEx(hClassKey, index, adapter_id, &adapter_id_len, NULL, NULL, NULL, + NULL); + if (result == ERROR_NO_MORE_ITEMS) + { + break; + } + else if (result != ERROR_SUCCESS) + { + continue; + } + + WCHAR connection_key[512]; + swprintf_s(connection_key, _countof(connection_key), L"%ls\\%ls\\Connection", class_key, + adapter_id); + + DWORD value_size = 0; + LONG query = RegGetValueW(HKEY_LOCAL_MACHINE, connection_key, L"Name", + RRF_RT_REG_SZ | RRF_NOEXPAND, NULL, NULL, &value_size); + if (query != ERROR_SUCCESS || value_size < sizeof(WCHAR)) + { + continue; + } + + LPWSTR value = (LPWSTR)malloc(value_size); + if (!value) + { + continue; + } + + query = RegGetValueW(HKEY_LOCAL_MACHINE, connection_key, L"Name", + RRF_RT_REG_SZ | RRF_NOEXPAND, NULL, value, &value_size); + if (query == ERROR_SUCCESS && _wcsicmp(name, value) == 0) + { + found = TRUE; + free(value); + break; + } + + free(value); + + if (found) + { + break; + } + } + + RegCloseKey(hClassKey); + return found; +} + +/** + * Determine whether a friendly name is currently in use by an adapter or reserved + * in the registry. + * + * @param name Friendly name to test. + * @param adapter_list Head of the adapter list returned by tap_list_adapters(). + * + * @return TRUE when the name is taken/reserved, FALSE when available. + */ +static BOOL +tap_name_in_use(LPCWSTR name, struct tap_adapter_node *adapter_list) +{ + if (name == NULL) + { + return FALSE; + } + + if (find_adapter_by_name(name, adapter_list)) + { + return TRUE; + } + + return registry_name_exists(name); +} + +/** + * Check whether a proposed adapter name satisfies Windows connection-name rules. + * + * Tabs, control characters (except space), and the following characters are disallowed: + * \ / : * ? " < > | + * Names must also be non-empty and no longer than 255 characters. + */ +BOOL +tap_is_valid_adapter_name(LPCWSTR name) +{ + if (name == NULL) + { + return FALSE; + } + + size_t length = wcslen(name); + if (length == 0 || length > 255) + { + return FALSE; + } + + static const WCHAR invalid_chars[] = L"\\/:*?\"<>|"; + + for (const WCHAR *p = name; *p; ++p) + { + WCHAR ch = *p; + if (ch < L' ') + { + return FALSE; + } + if (wcschr(invalid_chars, ch)) + { return FALSE; } } @@ -153,81 +290,152 @@ } /** - * Returns unique adapter name based on hwid or NULL if name cannot be generated. - * Caller is responsible for freeing it. + * Resolve the adapter name we should apply: + * - For user-specified names, ensure they are unique both in the adapter list and + * in the registry. On conflict, an explanatory message is printed and NULL is returned. + * - For automatic naming, derive the base string from HWID and append the first available + * suffix recognised by Windows. + * + * @param requested_name Name provided via CLI or configuration (may be NULL/empty). + * @param hwid Hardware identifier of the adapter being created. + * @param adapter_list Existing adapters enumerated via tap_list_adapters(). + * + * @return Newly allocated wide string containing the final name, or NULL on failure. */ static LPWSTR -get_unique_adapter_name(LPCWSTR hwid, struct tap_adapter_node *adapter_list) +tap_resolve_adapter_name(LPCWSTR requested_name, LPCWSTR hwid, + struct tap_adapter_node *adapter_list) { + if (requested_name && requested_name[0]) + { + if (!tap_is_valid_adapter_name(requested_name)) + { + fwprintf(stderr, + L"Adapter name \"%ls\" contains invalid characters. Avoid tabs or the " + L"characters \\ / : * ? \" < > | and keep the length within 255 characters.\n", + requested_name); + return NULL; + } + + struct tap_adapter_node *conflict = find_adapter_by_name(requested_name, adapter_list); + if (conflict) + { + LPOLESTR adapter_id = NULL; + StringFromIID((REFIID)&conflict->guid, &adapter_id); + fwprintf(stderr, + L"Adapter \"%ls\" already exists (GUID %" + L"ls).\n", + conflict->szName, adapter_id); + CoTaskMemFree(adapter_id); + return NULL; + } + + if (registry_name_exists(requested_name)) + { + fwprintf(stderr, L"Adapter name \"%ls\" is already in use.\n", requested_name); + return NULL; + } + + return wcsdup(requested_name); + } + if (hwid == NULL) { return NULL; } - LPCWSTR base_name; - if (wcsicmp(hwid, L"ovpn-dco") == 0) + LPCWSTR base_name = NULL; + if (_wcsicmp(hwid, L"ovpn-dco") == 0) { base_name = L"OpenVPN Data Channel Offload"; } - else if (wcsicmp(hwid, L"root\\" _L(TAP_WIN_COMPONENT_ID)) == 0) + else if (_wcsicmp(hwid, L"root\\" _L(TAP_WIN_COMPONENT_ID)) == 0 + || _wcsicmp(hwid, _L(TAP_WIN_COMPONENT_ID)) == 0) { base_name = L"OpenVPN TAP-Windows6"; } else { + fwprintf(stderr, + L"Cannot auto-generate adapter name for hardware ID \"%ls\".\n", hwid); return NULL; } - if (is_adapter_name_available(base_name, adapter_list, FALSE)) + if (!tap_name_in_use(base_name, adapter_list)) { return wcsdup(base_name); } size_t name_len = wcslen(base_name) + 10; - LPWSTR name = malloc(name_len * sizeof(WCHAR)); + LPWSTR name = (LPWSTR)malloc(name_len * sizeof(WCHAR)); if (name == NULL) { return NULL; } - for (int i = 1; i < 100; ++i) + + /* Windows never assigns the "#1" suffix, so skip it to avoid netsh failures. */ + for (int i = 2; i < 100; ++i) { swprintf_s(name, name_len, L"%ls #%d", base_name, i); - if (is_adapter_name_available(name, adapter_list, FALSE)) + if (!tap_name_in_use(name, adapter_list)) { return name; } } + free(name); + fwprintf(stderr, L"Unable to find available adapter name based on \"%ls\".\n", base_name); return NULL; } -static int command_create(int argc, LPCWSTR argv[], BOOL *bRebootRequired); -static int command_list(int argc, LPCWSTR argv[]); -static int command_delete(int argc, LPCWSTR argv[], BOOL *bRebootRequired); - static int command_create(int argc, LPCWSTR argv[], BOOL *bRebootRequired) { LPCWSTR szName = NULL; - LPCWSTR szHwId = L"root\\" _L(TAP_WIN_COMPONENT_ID); - struct tap_adapter_node *adapter_list = NULL; - LPWSTR rename_name = NULL; - LPWSTR final_name = NULL; - LPOLESTR adapter_id = NULL; + LPCWSTR defaultHwId = L"ovpn-dco"; + LPCWSTR szHwId = defaultHwId; + LPWSTR adapter_name = NULL; + struct tap_adapter_node *pAdapterList = NULL; GUID guidAdapter; - int result = 1; - BOOL delete_created_adapter = FALSE; + LPOLESTR szAdapterId = NULL; + DWORD dwResult; + int iResult = 1; + BOOL adapter_created = FALSE; for (int i = 2; i < argc; i++) { if (wcsicmp(argv[i], L"--name") == 0) { - szName = argv[++i]; + if (++i >= argc) + { + fwprintf(stderr, L"--name option requires a value. Ignored.\n"); + break; + } + szName = argv[i]; + if (szName[0] == L'\0') + { + fwprintf(stderr, L"--name option cannot be empty. Ignored.\n"); + szName = NULL; + } } else if (wcsicmp(argv[i], L"--hwid") == 0) { - szHwId = argv[++i]; + if (++i >= argc) + { + fwprintf(stderr, + L"--hwid option requires a value. Using default \"%ls\".\n", + defaultHwId); + break; + } + szHwId = argv[i]; + if (szHwId[0] == L'\0') + { + fwprintf(stderr, + L"--hwid option cannot be empty. Using default \"%ls\".\n", + defaultHwId); + szHwId = defaultHwId; + } } else { @@ -238,69 +446,59 @@ } } - DWORD dwResult = - tap_create_adapter(NULL, L"Virtual Ethernet", szHwId, bRebootRequired, &guidAdapter); + dwResult = tap_create_adapter(NULL, L"Virtual Ethernet", szHwId, bRebootRequired, + &guidAdapter); if (dwResult != ERROR_SUCCESS) { - fwprintf(stderr, L"Creating TUN/TAP adapter failed (error 0x%x).\n", dwResult); - return result; + fwprintf(stderr, L"Creating network adapter failed (error 0x%x).\n", dwResult); + goto cleanup; } + adapter_created = TRUE; - dwResult = tap_list_adapters(NULL, NULL, &adapter_list); + dwResult = tap_list_adapters(NULL, NULL, &pAdapterList); if (dwResult != ERROR_SUCCESS) { fwprintf(stderr, L"Enumerating adapters failed (error 0x%x).\n", dwResult); - delete_created_adapter = TRUE; goto cleanup; } - rename_name = szName ? wcsdup(szName) : get_unique_adapter_name(szHwId, adapter_list); - if (rename_name) + adapter_name = tap_resolve_adapter_name(szName, szHwId, pAdapterList); + if (adapter_name == NULL) { - if (szName && !is_adapter_name_available(rename_name, adapter_list, TRUE)) - { - delete_created_adapter = TRUE; - goto cleanup; - } - - dwResult = tap_set_adapter_name(&guidAdapter, rename_name, FALSE); - if (dwResult == ERROR_SUCCESS) - { - final_name = rename_name; - rename_name = NULL; - } - else - { - StringFromIID((REFIID)&guidAdapter, &adapter_id); - fwprintf(stderr, - L"Renaming TUN/TAP adapter %ls" - L" to \"%ls\" failed (error 0x%x).\n", - adapter_id, rename_name, dwResult); - CoTaskMemFree(adapter_id); - } + goto cleanup; } - result = 0; + dwResult = tap_set_adapter_name(&guidAdapter, adapter_name, FALSE); + if (dwResult != ERROR_SUCCESS) + { + StringFromIID((REFIID)&guidAdapter, &szAdapterId); + fwprintf(stderr, + L"Renaming network adapter %ls to \"%ls\" failed (error 0x%x).\n", szAdapterId, + adapter_name, dwResult); + CoTaskMemFree(szAdapterId); + goto cleanup; + } + + iResult = 0; + StringFromIID((REFIID)&guidAdapter, &szAdapterId); + const WCHAR *name_to_print = (adapter_name && adapter_name[0]) ? adapter_name : L"(unnamed)"; + const WCHAR *hwid_to_print = (szHwId && szHwId[0]) ? szHwId : L"(unknown hwid)"; + fwprintf(stdout, L"%ls\t%ls\t%ls\n", szAdapterId, name_to_print, hwid_to_print); + CoTaskMemFree(szAdapterId); cleanup: - tap_free_adapter_list(adapter_list); - free(rename_name); - - if (result == 0 && final_name) + if (pAdapterList) { - StringFromIID((REFIID)&guidAdapter, &adapter_id); - fwprintf(stdout, L"%ls\t%ls\t%ls\n", adapter_id, final_name, szHwId ? szHwId : L""); - CoTaskMemFree(adapter_id); + tap_free_adapter_list(pAdapterList); } + free(adapter_name); - free(final_name); - - if (result != 0 && delete_created_adapter) + if (adapter_created && iResult != 0) { tap_delete_adapter(NULL, &guidAdapter, bRebootRequired); } - return result; + return iResult; } static int