From 86871951e720e14d0fcdd1241ae206327f4764db Mon Sep 17 00:00:00 2001 From: Dmitry Shihovtsev Date: Thu, 14 Mar 2019 14:24:04 +0600 Subject: [PATCH] Add support for Windows to allow selecting between multiple `tap0901` adapters on the same system Co-authored-by: Neil Alexander --- CONTRIBUTORS | 1 + params_windows.go | 5 +++++ syscalls_windows.go | 27 ++++++++++++++++++++++++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 600ca63..9f8b6f4 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -10,3 +10,4 @@ ajee cai yinheli Paul Querna Cuong Manh Le +Neil Alexander diff --git a/params_windows.go b/params_windows.go index 7b89965..6ff0c7b 100644 --- a/params_windows.go +++ b/params_windows.go @@ -9,6 +9,10 @@ type PlatformSpecificParams struct { // use the default ComponentId. The default ComponentId is set to tap0901, // the one used by OpenVPN. ComponentID string + // Of course, you may have multiple tap0901 adapters on the system, in which + // case we need a friendlier way to identify them. In that case we can use + // the friendly name of the network adapter as set in Control Panel. + InterfaceName string // Network is required when creating a TUN interface. The library will call // net.ParseCIDR() to parse this string into LocalIP, RemoteNetaddr, // RemoteNetmask. The underlying driver will need those to generate ARP @@ -25,6 +29,7 @@ type PlatformSpecificParams struct { func defaultPlatformSpecificParams() PlatformSpecificParams { return PlatformSpecificParams{ ComponentID: "tap0901", + InterfaceName: "", Network: "192.168.1.10/24", } } diff --git a/syscalls_windows.go b/syscalls_windows.go index 473a399..5e56cce 100644 --- a/syscalls_windows.go +++ b/syscalls_windows.go @@ -139,7 +139,7 @@ func tap_control_code(request, method uint32) uint32 { } // getdeviceid finds out a TAP device from registry, it *may* requires privileged right to prevent some weird issue. -func getdeviceid(componentID string) (deviceid string, err error) { +func getdeviceid(componentID string, interfaceName string) (deviceid string, err error) { // TAP driver key location regkey := `SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}` k, err := registry.OpenKey(registry.LOCAL_MACHINE, regkey, registry.READ) @@ -169,12 +169,33 @@ func getdeviceid(componentID string) (deviceid string, err error) { key.Close() continue } + if len(interfaceName) > 0 { + key2 := `SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\`+val+`\Connection` + k2, err := registry.OpenKey(registry.LOCAL_MACHINE, key2, registry.READ) + if err != nil { + fmt.Println("Unable to open", key2) + continue + } + defer k2.Close() + val, _, err := k2.GetStringValue("Name") + if err != nil { + fmt.Println("Unable to get Name value from", key2) + continue + } + if val != interfaceName { + continue + } + } key.Close() return val, nil } key.Close() } - return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId(%s), TAP driver may be not installed", componentID) + if len(interfaceName) > 0 { + return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId '%s' and InterfaceName '%s', TAP driver may be not installed or you may have specified an interface name that doesn't exist", componentID) + } else { + return "", fmt.Errorf("Failed to find the tap device in registry with specified ComponentId '%s', TAP driver may be not installed", componentID) + } } // setStatus is used to bring up or bring down the interface @@ -216,7 +237,7 @@ func setTUN(fd syscall.Handle, network string) error { // openDev find and open an interface. func openDev(config Config) (ifce *Interface, err error) { // find the device in registry. - deviceid, err := getdeviceid(config.PlatformSpecificParams.ComponentID) + deviceid, err := getdeviceid(config.PlatformSpecificParams.ComponentID, config.PlatformSpecificParams.InterfaceName) if err != nil { return nil, err }