wintun: simplify DeleteInterface method signature

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-06-03 14:16:34 +02:00
parent 108c37a056
commit c2ed133df8
2 changed files with 81 additions and 60 deletions

View file

@ -67,7 +67,7 @@ func CreateTUN(ifname string) (TUNDevice, error) {
wt, err = wintun.GetInterface(ifname, 0) wt, err = wintun.GetInterface(ifname, 0)
if err == nil { if err == nil {
// If so, we delete it, in case it has weird residual configuration. // If so, we delete it, in case it has weird residual configuration.
_, _, err = wt.DeleteInterface(0) _, err = wt.DeleteInterface(0)
if err != nil { if err != nil {
return nil, fmt.Errorf("Unable to delete already existing Wintun interface: %v", err) return nil, fmt.Errorf("Unable to delete already existing Wintun interface: %v", err)
} }
@ -206,7 +206,7 @@ func (tun *NativeTun) Close() error {
close(tun.events) close(tun.events)
} }
_, _, err2 := tun.wt.DeleteInterface(0) _, err2 := tun.wt.DeleteInterface(0)
if err1 == nil { if err1 == nil {
err1 = err2 err1 = err2
} }

View file

@ -417,43 +417,20 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err
// optional and can be 0. If a specific top-level window is not required, set // optional and can be 0. If a specific top-level window is not required, set
// hwndParent to 0. // hwndParent to 0.
// //
// Function returns true if the interface was found and deleted and a flag if // Function silently succeeds if the interface was not found.
// reboot is required.
// //
func (wintun *Wintun) DeleteInterface(hwndParent uintptr) (bool, bool, error) { // Function returns true if a reboot is required.
// Create a list of network devices. //
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, enumerator, hwndParent, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), machineName) func (wintun *Wintun) DeleteInterface(hwndParent uintptr) (bool, error) {
devInfoList, deviceData, err := wintun.deviceData(hwndParent)
if err == windows.ERROR_OBJECT_NOT_FOUND {
return false, nil
}
if err != nil { if err != nil {
return false, false, fmt.Errorf("SetupDiGetClassDevsEx(%s) failed: %v", guid.ToString(&deviceClassNetGUID), err.Error()) return false, err
} }
defer devInfoList.Close() defer devInfoList.Close()
// Iterate.
for index := 0; ; index++ {
// Get the device from the list. Should anything be wrong with this device, continue with next.
deviceData, err := devInfoList.EnumDeviceInfo(index)
if err != nil {
if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
break
}
continue
}
// Get interface ID.
//TODO: Store some ID in the Wintun object such that this call isn't required.
wintun2, err := makeWintun(devInfoList, deviceData)
if err != nil {
continue
}
if wintun.cfgInstanceID == wintun2.cfgInstanceID {
if hwndParent == 0 {
err = setQuietInstall(devInfoList, deviceData)
if err != nil {
return false, false, fmt.Errorf("Setting quiet installation failed: %v", err)
}
}
// Remove the device. // Remove the device.
removeDeviceParams := setupapi.RemoveDeviceParams{ removeDeviceParams := setupapi.RemoveDeviceParams{
ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE), ClassInstallHeader: *setupapi.MakeClassInstallHeader(setupapi.DIF_REMOVE),
@ -463,25 +440,18 @@ func (wintun *Wintun) DeleteInterface(hwndParent uintptr) (bool, bool, error) {
// Set class installer parameters for DIF_REMOVE. // Set class installer parameters for DIF_REMOVE.
err = devInfoList.SetClassInstallParams(deviceData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams))) err = devInfoList.SetClassInstallParams(deviceData, &removeDeviceParams.ClassInstallHeader, uint32(unsafe.Sizeof(removeDeviceParams)))
if err != nil { if err != nil {
return false, false, fmt.Errorf("SetupDiSetClassInstallParams failed: %v", err) return false, fmt.Errorf("SetupDiSetClassInstallParams failed: %v", err)
} }
// Call appropriate class installer. // Call appropriate class installer.
err = devInfoList.CallClassInstaller(setupapi.DIF_REMOVE, deviceData) err = devInfoList.CallClassInstaller(setupapi.DIF_REMOVE, deviceData)
if err != nil { if err != nil {
return false, false, fmt.Errorf("SetupDiCallClassInstaller failed: %v", err) return false, fmt.Errorf("SetupDiCallClassInstaller failed: %v", err)
} }
// Check if a system reboot is required. (Ignore errors) // Check if a system reboot is required. (Ignore errors)
if ret, _ := checkReboot(devInfoList, deviceData); ret { ret, _ := checkReboot(devInfoList, deviceData)
return true, true, nil return ret, nil
}
return true, false, nil
}
}
return false, false, nil
} }
// //
@ -575,6 +545,57 @@ func (wintun *Wintun) tcpipInterfaceRegKeyName() (path string, err error) {
return fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), nil return fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), nil
} }
//
// deviceData returns TUN device info list handle and interface device info
// data.
//
// The device info list handle must be closed after use.
//
// In case the device is not found, windows.ERROR_OBJECT_NOT_FOUND is
// returned.
//
func (wintun *Wintun) deviceData(hwndParent uintptr) (setupapi.DevInfo, *setupapi.DevInfoData, error) {
// Create a list of network devices.
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, enumerator, hwndParent, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), machineName)
if err != nil {
return 0, nil, fmt.Errorf("SetupDiGetClassDevsEx(%s) failed: %v", guid.ToString(&deviceClassNetGUID), err.Error())
}
// Iterate.
for index := 0; ; index++ {
// Get the device from the list. Should anything be wrong with this device, continue with next.
deviceData, err := devInfoList.EnumDeviceInfo(index)
if err != nil {
if errWin, ok := err.(windows.Errno); ok && errWin == windows.ERROR_NO_MORE_ITEMS {
break
}
continue
}
// Get interface ID.
//TODO: Store some ID in the Wintun object such that this call isn't required.
wintun2, err := makeWintun(devInfoList, deviceData)
if err != nil {
continue
}
if wintun.cfgInstanceID == wintun2.cfgInstanceID {
if hwndParent == 0 {
err = setQuietInstall(devInfoList, deviceData)
if err != nil {
devInfoList.Close()
return 0, nil, fmt.Errorf("Setting quiet installation failed: %v", err)
}
}
return devInfoList, deviceData, nil
}
}
devInfoList.Close()
return 0, nil, windows.ERROR_OBJECT_NOT_FOUND
}
// //
// DataFileName returns Wintun device data pipe name. // DataFileName returns Wintun device data pipe name.
// //