summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-05-02 23:53:15 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-05-02 23:53:15 +0200
commit46dbf5404013e83867356ea8a590a45a569acbf4 (patch)
tree0759e6ea30009538fdb458170d0bd632b63de8ee
parent247e14693adb3d7a337ec57a4d2db374fb9099cd (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.go6
-rw-r--r--tun/wintun/wintun_windows.go29
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.
//