diff options
author | Lev Stipakov | 2023-05-19 11:25:48 +0300 |
---|---|---|
committer | Gert Doering | 2023-05-21 17:26:18 +0200 |
commit | 868286fa756f7faf768bdd7e18a44e6a92e47066 (patch) | |
tree | a59b7f465c6a173241659da93e64dd5006babc0e | |
parent | 9e112be5dde043cdc1f073f33ada0a1810b730a6 (diff) | |
download | openvpn-868286fa756f7faf768bdd7e18a44e6a92e47066.zip openvpn-868286fa756f7faf768bdd7e18a44e6a92e47066.tar.gz |
tapctl: generate driver-specific adapter names
At the moment if --name is not specified, adapter names
are generated by Windows and they look a bit confusing
like "Local Area Connection 2".
This is also behavior of "Add a new <driver-name> virtual network
adapter" shortcuts.
This makes tapctl generate driver-specific names for adapters
if --name is missing, inclusing resolving duplicates. For instance
following commands:
tapctl.exe create --hwid ovpn-dco
will create an adapter named
OpenVPN Data Channel Offload
If the name is taken, the next one will be
OpenVPN Data Channel Offload #1
and so on up to 100.
Fixes https://github.com/OpenVPN/openvpn/issues/337
Change-Id: Ic5afb470d14ac7b231d91f0f5de0a0046043a7e0
Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Selva Nair <selva.nair@gmail.com>
Message-Id: <20230519082548.1714-1-lstipakov@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg26712.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 4323b8277814495f5a9a24d3225679c6e7a971a4)
-rw-r--r-- | src/tapctl/main.c | 132 |
1 files changed, 105 insertions, 27 deletions
diff --git a/src/tapctl/main.c b/src/tapctl/main.c index 1194036..d76d553 100644 --- a/src/tapctl/main.c +++ b/src/tapctl/main.c @@ -126,6 +126,85 @@ usage(void) title_string); } +/** + * Checks if adapter with given name doesn't already exist + */ +static BOOL +is_adapter_name_available(LPCTSTR name, struct tap_adapter_node *adapter_list, BOOL log) +{ + for (struct tap_adapter_node *a = adapter_list; a; a = a->pNext) + { + if (_tcsicmp(name, a->szName) == 0) + { + if (log) + { + LPOLESTR adapter_id = NULL; + StringFromIID((REFIID)&a->guid, &adapter_id); + _ftprintf(stderr, TEXT("Adapter \"%") TEXT(PRIsLPTSTR) TEXT("\" already exists (GUID %") + TEXT(PRIsLPOLESTR) TEXT(").\n"), a->szName, adapter_id); + CoTaskMemFree(adapter_id); + } + + return FALSE; + } + } + + return TRUE; +} + +/** + * Returns unique adapter name based on hwid or NULL if name cannot be generated. + * Caller is responsible for freeing it. + */ +static LPTSTR +get_unique_adapter_name(LPCTSTR hwid, struct tap_adapter_node *adapter_list) +{ + if (hwid == NULL) + { + return NULL; + } + + LPCTSTR base_name; + if (_tcsicmp(hwid, TEXT("ovpn-dco")) == 0) + { + base_name = TEXT("OpenVPN Data Channel Offload"); + } + else if (_tcsicmp(hwid, TEXT("wintun")) == 0) + { + base_name = TEXT("OpenVPN Wintun"); + } + else if (_tcsicmp(hwid, TEXT("root\\") TEXT(TAP_WIN_COMPONENT_ID)) == 0) + { + base_name = TEXT("OpenVPN TAP-Windows6"); + } + else + { + return NULL; + } + + if (is_adapter_name_available(base_name, adapter_list, FALSE)) + { + return _tcsdup(base_name); + } + + size_t name_len = _tcslen(base_name) + 10; + LPTSTR name = malloc(name_len * sizeof(TCHAR)); + if (name == NULL) + { + return NULL; + } + for (int i = 1; i < 100; ++i) + { + _stprintf_s(name, name_len, TEXT("%ls #%d"), base_name, i); + + if (is_adapter_name_available(name, adapter_list, FALSE)) + { + return name; + } + } + + return NULL; +} /** * Program entry point @@ -210,50 +289,49 @@ _tmain(int argc, LPCTSTR argv[]) iResult = 1; goto quit; } - if (szName) + /* Get existing network adapters. */ + struct tap_adapter_node *pAdapterList = NULL; + dwResult = tap_list_adapters(NULL, NULL, &pAdapterList); + if (dwResult != ERROR_SUCCESS) { - /* Get existing network adapters. */ - struct tap_adapter_node *pAdapterList = NULL; - dwResult = tap_list_adapters(NULL, NULL, &pAdapterList); - if (dwResult != ERROR_SUCCESS) - { - _ftprintf(stderr, TEXT("Enumerating adapters failed (error 0x%x).\n"), dwResult); - iResult = 1; goto create_delete_adapter; - } + _ftprintf(stderr, TEXT("Enumerating adapters failed (error 0x%x).\n"), dwResult); + iResult = 1; + goto create_delete_adapter; + } - /* Check for duplicates. */ - for (struct tap_adapter_node *pAdapter = pAdapterList; pAdapter; pAdapter = pAdapter->pNext) + LPTSTR adapter_name = szName ? _tcsdup(szName) : get_unique_adapter_name(szHwId, pAdapterList); + if (adapter_name) + { + /* Check for duplicates when name was specified, + * otherwise get_adapter_default_name() takes care of it */ + if (szName && !is_adapter_name_available(adapter_name, pAdapterList, TRUE)) { - if (_tcsicmp(szName, pAdapter->szName) == 0) - { - StringFromIID((REFIID)&pAdapter->guid, &szAdapterId); - _ftprintf(stderr, TEXT("Adapter \"%") TEXT(PRIsLPTSTR) TEXT("\" already exists (GUID %") - TEXT(PRIsLPOLESTR) TEXT(").\n"), pAdapter->szName, szAdapterId); - CoTaskMemFree(szAdapterId); - iResult = 1; goto create_cleanup_pAdapterList; - } + iResult = 1; + goto create_cleanup_pAdapterList; } /* Rename the adapter. */ - dwResult = tap_set_adapter_name(&guidAdapter, szName, FALSE); + dwResult = tap_set_adapter_name(&guidAdapter, adapter_name, FALSE); if (dwResult != ERROR_SUCCESS) { StringFromIID((REFIID)&guidAdapter, &szAdapterId); _ftprintf(stderr, TEXT("Renaming TUN/TAP adapter %") TEXT(PRIsLPOLESTR) TEXT(" to \"%") TEXT(PRIsLPTSTR) TEXT("\" failed (error 0x%x).\n"), - szAdapterId, szName, dwResult); + szAdapterId, adapter_name, dwResult); CoTaskMemFree(szAdapterId); iResult = 1; goto quit; } + } - iResult = 0; + iResult = 0; create_cleanup_pAdapterList: - tap_free_adapter_list(pAdapterList); - if (iResult) - { - goto create_delete_adapter; - } + free(adapter_name); + + tap_free_adapter_list(pAdapterList); + if (iResult) + { + goto create_delete_adapter; } /* Output adapter GUID. */ |