wintun: take mutex so that deletion uses the right name
This commit is contained in:
parent
353f0956bc
commit
14df9c3e75
7
go.mod
7
go.mod
@ -3,7 +3,8 @@ module golang.zx2c4.com/wireguard
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
|
||||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f
|
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad
|
||||||
|
golang.org/x/text v0.3.2
|
||||||
)
|
)
|
||||||
|
15
go.sum
15
go.sum
@ -1,11 +1,14 @@
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56 h1:ZpKuNIejY8P0ExLOVyKhb0WsgG8UdvHXe6TWjY7eL6k=
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
|
||||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f h1:dHNZYIYdq2QuU6w73vZ/DzesPbVlZVYZTtTZmrnsbQ8=
|
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad h1:cCejgArrk10gX6kFqjWeLwXD7aVMqWoRpyUCaaJSggc=
|
||||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -75,17 +75,11 @@ func CreateTUNWithRequestedGUID(ifname string, requestedGUID *windows.GUID) (Dev
|
|||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wt, _, err = WintunPool.CreateInterface(requestedGUID)
|
wt, _, err = WintunPool.CreateInterface(ifname, requestedGUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Unable to create Wintun interface: %v", err)
|
return nil, fmt.Errorf("Unable to create Wintun interface: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = wt.SetName(ifname)
|
|
||||||
if err != nil {
|
|
||||||
wt.DeleteInterface()
|
|
||||||
return nil, fmt.Errorf("Unable to set name of Wintun interface: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tun := &NativeTun{
|
tun := &NativeTun{
|
||||||
wt: wt,
|
wt: wt,
|
||||||
handle: windows.InvalidHandle,
|
handle: windows.InvalidHandle,
|
||||||
|
@ -6,14 +6,17 @@
|
|||||||
package wintun
|
package wintun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/blake2s"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
|
"golang.org/x/text/unicode/norm"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun/wintun/iphlpapi"
|
"golang.zx2c4.com/wireguard/tun/wintun/iphlpapi"
|
||||||
"golang.zx2c4.com/wireguard/tun/wintun/nci"
|
"golang.zx2c4.com/wireguard/tun/wintun/nci"
|
||||||
@ -99,6 +102,15 @@ func removeNumberedSuffix(ifname string) string {
|
|||||||
// the interface is found but not a Wintun-class or a member of the pool,
|
// the interface is found but not a Wintun-class or a member of the pool,
|
||||||
// this function returns windows.ERROR_ALREADY_EXISTS.
|
// this function returns windows.ERROR_ALREADY_EXISTS.
|
||||||
func (pool Pool) GetInterface(ifname string) (*Interface, error) {
|
func (pool Pool) GetInterface(ifname string) (*Interface, error) {
|
||||||
|
mutex, err := pool.takeNameMutex()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
windows.ReleaseMutex(mutex)
|
||||||
|
windows.CloseHandle(mutex)
|
||||||
|
}()
|
||||||
|
|
||||||
// Create a list of network devices.
|
// Create a list of network devices.
|
||||||
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
|
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,14 +190,15 @@ func (pool Pool) GetInterface(ifname string) (*Interface, error) {
|
|||||||
return nil, windows.ERROR_OBJECT_NOT_FOUND
|
return nil, windows.ERROR_OBJECT_NOT_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateInterface creates a Wintun interface. requestedGUID is the GUID of the
|
// CreateInterface creates a Wintun interface. ifname is the requested name of
|
||||||
// created network interface, which then influences NLA generation
|
// the interface, while requestedGUID is the GUID of the created network
|
||||||
// deterministically. If it is set to nil, the GUID is chosen by the system at
|
// interface, which then influences NLA generation deterministically. If it is
|
||||||
// random, and hence a new NLA entry is created for each new interface. It is
|
// set to nil, the GUID is chosen by the system at random, and hence a new NLA
|
||||||
// called "requested" GUID because the API it uses is completely undocumented,
|
// entry is created for each new interface. It is called "requested" GUID
|
||||||
// and so there could be minor interesting complications with its usage. This
|
// because the API it uses is completely undocumented, and so there could be minor
|
||||||
// function returns the network interface ID and a flag if reboot is required.
|
// interesting complications with its usage. This function returns the network
|
||||||
func (pool Pool) CreateInterface(requestedGUID *windows.GUID) (wintun *Interface, rebootRequired bool, err error) {
|
// interface ID and a flag if reboot is required.
|
||||||
|
func (pool Pool) CreateInterface(ifname string, requestedGUID *windows.GUID) (wintun *Interface, rebootRequired bool, err error) {
|
||||||
// Create an empty device info set for network adapter device class.
|
// Create an empty device info set for network adapter device class.
|
||||||
devInfoList, err := setupapi.SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, "")
|
devInfoList, err := setupapi.SetupDiCreateDeviceInfoListEx(&deviceClassNetGUID, 0, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -271,6 +284,15 @@ func (pool Pool) CreateInterface(requestedGUID *windows.GUID) (wintun *Interface
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex, err := pool.takeNameMutex()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
windows.ReleaseMutex(mutex)
|
||||||
|
windows.CloseHandle(mutex)
|
||||||
|
}()
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The interface failed to install, or the interface ID was unobtainable. Clean-up.
|
// The interface failed to install, or the interface ID was unobtainable. Clean-up.
|
||||||
@ -403,6 +425,12 @@ func (pool Pool) CreateInterface(requestedGUID *windows.GUID) (wintun *Interface
|
|||||||
// Disable dead gateway detection on our interface.
|
// Disable dead gateway detection on our interface.
|
||||||
tcpipInterfaceRegKey.SetDWordValue("EnableDeadGWDetect", 0)
|
tcpipInterfaceRegKey.SetDWordValue("EnableDeadGWDetect", 0)
|
||||||
|
|
||||||
|
err = wintun.SetName(ifname)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Unable to set name of Wintun interface: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,6 +472,16 @@ func (wintun *Interface) DeleteInterface() (rebootRequired bool, err error) {
|
|||||||
// given criteria, and returns which ones it deleted, whether a reboot
|
// given criteria, and returns which ones it deleted, whether a reboot
|
||||||
// is required after, and which errors occurred during the process.
|
// is required after, and which errors occurred during the process.
|
||||||
func (pool Pool) DeleteMatchingInterfaces(matches func(wintun *Interface) bool) (deviceInstancesDeleted []uint32, rebootRequired bool, errors []error) {
|
func (pool Pool) DeleteMatchingInterfaces(matches func(wintun *Interface) bool) (deviceInstancesDeleted []uint32, rebootRequired bool, errors []error) {
|
||||||
|
mutex, err := pool.takeNameMutex()
|
||||||
|
if err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
windows.ReleaseMutex(mutex)
|
||||||
|
windows.CloseHandle(mutex)
|
||||||
|
}()
|
||||||
|
|
||||||
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
|
devInfoList, err := setupapi.SetupDiGetClassDevsEx(&deviceClassNetGUID, "", 0, setupapi.DIGCF_PRESENT, setupapi.DevInfo(0), "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, []error{fmt.Errorf("SetupDiGetClassDevsEx(%v) failed: %v", deviceClassNetGUID, err.Error())}
|
return nil, false, []error{fmt.Errorf("SetupDiGetClassDevsEx(%v) failed: %v", deviceClassNetGUID, err.Error())}
|
||||||
@ -498,7 +536,7 @@ func (pool Pool) DeleteMatchingInterfaces(matches func(wintun *Interface) bool)
|
|||||||
|
|
||||||
wintun, err := makeWintun(devInfoList, deviceData, pool)
|
wintun, err := makeWintun(devInfoList, deviceData, pool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, fmt.Errorf("makeWintun failed: %v", err))
|
errors = append(errors, fmt.Errorf("Unable to make Wintun interface object: %v", err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !matches(wintun) {
|
if !matches(wintun) {
|
||||||
@ -720,3 +758,26 @@ func (wintun *Interface) GUID() windows.GUID {
|
|||||||
func (wintun *Interface) LUID() uint64 {
|
func (wintun *Interface) LUID() uint64 {
|
||||||
return ((uint64(wintun.luidIndex) & ((1 << 24) - 1)) << 24) | ((uint64(wintun.ifType) & ((1 << 16) - 1)) << 48)
|
return ((uint64(wintun.luidIndex) & ((1 << 24) - 1)) << 24) | ((uint64(wintun.ifType) & ((1 << 16) - 1)) << 48)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pool Pool) takeNameMutex() (windows.Handle, error) {
|
||||||
|
const mutexLabel = "WireGuard Adapter Name Mutex Stable Suffix v1 jason@zx2c4.com"
|
||||||
|
b2, _ := blake2s.New256(nil)
|
||||||
|
b2.Write([]byte(mutexLabel))
|
||||||
|
b2.Write(norm.NFC.Bytes([]byte(string(pool))))
|
||||||
|
mutexName := `Global\Wintun-Name-Mutex-` + hex.EncodeToString(b2.Sum(nil))
|
||||||
|
mutex, err := windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(mutexName))
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error creating name mutex: %v", err)
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
event, err := windows.WaitForSingleObject(mutex, windows.INFINITE)
|
||||||
|
if err != nil {
|
||||||
|
windows.CloseHandle(mutex)
|
||||||
|
return 0, fmt.Errorf("Error waiting on name mutex: %v", err)
|
||||||
|
}
|
||||||
|
if event != windows.WAIT_OBJECT_0 {
|
||||||
|
windows.CloseHandle(mutex)
|
||||||
|
return 0, errors.New("Error with event trigger of name mutex")
|
||||||
|
}
|
||||||
|
return mutex, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user