From e924280baa36f6fd80f4a65f2fb6223a4965b281 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Sun, 9 Jun 2019 19:20:17 +0200 Subject: [PATCH] wintun: allow controlling GUID --- tun/tun_windows.go | 10 +++++++++- tun/wintun/wintun_windows.go | 21 ++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/tun/tun_windows.go b/tun/tun_windows.go index 0b41be9..1881e5b 100644 --- a/tun/tun_windows.go +++ b/tun/tun_windows.go @@ -60,6 +60,14 @@ func packetAlign(size uint32) uint32 { // adapter with the same name exist, it is reused. // func CreateTUN(ifname string) (TUNDevice, error) { + return CreateTUNWithRequestedGUID(ifname, nil) +} + +// +// CreateTUNWithRequestedGUID creates a Wintun adapter with the given name and +// a requested GUID. Should a Wintun adapter with the same name exist, it is reused. +// +func CreateTUNWithRequestedGUID(ifname string, requestedGUID *windows.GUID) (TUNDevice, error) { var err error var wt *wintun.Wintun @@ -74,7 +82,7 @@ func CreateTUN(ifname string) (TUNDevice, error) { } else if err == windows.ERROR_ALREADY_EXISTS { return nil, fmt.Errorf("Foreign network interface with the same name exists") } - wt, _, err = wintun.CreateInterface("WireGuard Tunnel Adapter", 0) + wt, _, err = wintun.CreateInterface("WireGuard Tunnel Adapter", requestedGUID, 0) if err != nil { return nil, fmt.Errorf("Unable to create Wintun interface: %v", err) } diff --git a/tun/wintun/wintun_windows.go b/tun/wintun/wintun_windows.go index ec7f8ea..9e71581 100644 --- a/tun/wintun/wintun_windows.go +++ b/tun/wintun/wintun_windows.go @@ -176,6 +176,13 @@ func GetInterface(ifname string, hwndParent uintptr) (*Wintun, error) { // description is a string that supplies the text description of the device. // description is optional and can be "". // +// requestedGUID is the GUID of the created network interface, which then +// influences NLA generation deterministically. If it is set to nil, the GUID +// is chosen by the system at random, and hence a new NLA entry is created for +// each new interface. It is called "requested" GUID because the API it uses +// is completely undocumented, and so there could be minor interesting +// complications with its usage. +// // hwndParent is a handle to the top-level window to use for any user // interface that is related to non-device-specific actions (such as a select- // device dialog box that uses the global class driver list). This handle is @@ -184,7 +191,7 @@ func GetInterface(ifname string, hwndParent uintptr) (*Wintun, error) { // // Function returns the network interface ID and a flag if reboot is required. // -func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, error) { +func CreateInterface(description string, requestedGUID *windows.GUID, hwndParent uintptr) (*Wintun, bool, error) { // Create an empty device info set for network adapter device class. devInfoList, err := setupapi.SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, hwndParent, machineName) if err != nil { @@ -280,6 +287,18 @@ func CreateInterface(description string, hwndParent uintptr) (*Wintun, bool, err // Register device co-installers if any. (Ignore errors) devInfoList.CallClassInstaller(setupapi.DIF_REGISTER_COINSTALLERS, deviceData) + if requestedGUID != nil { + key, err := devInfoList.OpenDevRegKey(deviceData, setupapi.DICS_FLAG_GLOBAL, 0, setupapi.DIREG_DRV, registry.SET_VALUE) + if err != nil { + return nil, false, fmt.Errorf("OpenDevRegKey failed: %v", err) + } + err = key.SetStringValue("NetSetupAnticipatedInstanceId", requestedGUID.String()) + key.Close() + if err != nil { + return nil, false, fmt.Errorf("SetStringValue(NetSetupAnticipatedInstanceId) failed: %v", err) + } + } + // Install interfaces if any. (Ignore errors) devInfoList.CallClassInstaller(setupapi.DIF_INSTALLINTERFACES, deviceData)