diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-02 23:53:15 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-02 23:53:15 +0200 |
commit | 46dbf5404013e83867356ea8a590a45a569acbf4 (patch) | |
tree | 0759e6ea30009538fdb458170d0bd632b63de8ee | |
parent | 247e14693adb3d7a337ec57a4d2db374fb9099cd (diff) |
wintun: don't retry when not creating
The only time we're trying to counteract the race condition is when
we're creating a driver. When we're simply looking up all drivers, it
doesn't make sense to retry.
-rw-r--r-- | tun/wintun/registryhacks_windows.go | 6 | ||||
-rw-r--r-- | tun/wintun/wintun_windows.go | 29 |
2 files changed, 26 insertions, 9 deletions
diff --git a/tun/wintun/registryhacks_windows.go b/tun/wintun/registryhacks_windows.go index bbcc020..94cc2f3 100644 --- a/tun/wintun/registryhacks_windows.go +++ b/tun/wintun/registryhacks_windows.go @@ -11,7 +11,7 @@ import ( ) const ( - numRetries = 100 + numRetries = 100 retryTimeout = 150 * time.Millisecond ) @@ -21,7 +21,7 @@ func registryOpenKeyRetry(k registry.Key, path string, access uint32) (key regis if err == nil { break } - if i != numRetries - 1 { + if i != numRetries-1 { time.Sleep(retryTimeout) } } @@ -34,7 +34,7 @@ func keyGetStringValueRetry(k registry.Key, name string) (val string, valtype ui if err == nil { break } - if i != numRetries - 1 { + if i != numRetries-1 { time.Sleep(retryTimeout) } } diff --git a/tun/wintun/wintun_windows.go b/tun/wintun/wintun_windows.go index eae283b..e1b46a8 100644 --- a/tun/wintun/wintun_windows.go +++ b/tun/wintun/wintun_windows.go @@ -38,7 +38,7 @@ const machineName = "" // // MakeWintun creates interface handle and populates it from device registry key // -func MakeWintun(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfoData) (*Wintun, error) { +func makeWintun(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfoData, wait bool) (*Wintun, error) { // Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key. key, err := deviceInfoSet.OpenDevRegKey(deviceInfoData, setupapi.DICS_FLAG_GLOBAL, 0, setupapi.DIREG_DRV, registry.READ) if err != nil { @@ -50,7 +50,11 @@ func MakeWintun(deviceInfoSet setupapi.DevInfo, deviceInfoData *setupapi.DevInfo var valueType uint32 // Read the NetCfgInstanceId value. - valueStr, valueType, err = keyGetStringValueRetry(key, "NetCfgInstanceId") + if wait { + valueStr, valueType, err = keyGetStringValueRetry(key, "NetCfgInstanceId") + } else { + valueStr, valueType, err = key.GetStringValue("NetCfgInstanceId") + } if err != nil { return nil, errors.New("RegQueryStringValue(\"NetCfgInstanceId\") failed: " + err.Error()) } @@ -121,13 +125,14 @@ func GetInterface(ifname string, hwndParent uintptr) (*Wintun, error) { } // Get interface ID. - wintun, err := MakeWintun(devInfoList, deviceData) + wintun, err := makeWintun(devInfoList, deviceData, false) if err != nil { continue } + //TODO: is there a better way than comparing ifnames? // Get interface name. - ifname2, err := wintun.GetInterfaceName() + ifname2, err := wintun.getInterfaceNameNoRetry() if err != nil { continue } @@ -301,7 +306,7 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err // installation continues in the background. It might take a while, before all registry // keys and values are populated. for numAttempts := 0; numAttempts < 30; numAttempts++ { - wintun, err = MakeWintun(devInfoList, deviceData) + wintun, err = makeWintun(devInfoList, deviceData, true) if err != nil { if errWin, ok := err.(syscall.Errno); ok && errWin == windows.ERROR_FILE_NOT_FOUND { // Wait and retry. TODO: Wait for a cancellable event instead. @@ -371,7 +376,8 @@ func (wintun *Wintun) DeleteInterface(hwndParent uintptr) (bool, bool, error) { } // Get interface ID. - wintun2, err := MakeWintun(devInfoList, deviceData) + //TODO: Store some ID in the Wintun object such that this call isn't required. + wintun2, err := makeWintun(devInfoList, deviceData, false) if err != nil { continue } @@ -446,6 +452,17 @@ func (wintun *Wintun) GetInterfaceName() (string, error) { return getRegStringValue(key, "Name") } +func (wintun *Wintun) getInterfaceNameNoRetry() (string, error) { + key, err := registry.OpenKey(registry.LOCAL_MACHINE, wintun.GetNetRegKeyName(), registry.QUERY_VALUE) + if err != nil { + return "", errors.New("Network-specific registry key open failed: " + err.Error()) + } + defer key.Close() + + // Get the interface name. + return getRegStringValue(key, "Name") +} + // // SetInterfaceName sets network interface name. // |