aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/manager
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-07-12 15:53:10 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2021-08-02 19:10:58 +0200
commit5409c45a10dc7a045197bc4105c6a7bd5d29283f (patch)
treee64f9e7e09a4f3d965659413487781f452800256 /manager
parentversion: bump (diff)
downloadwireguard-windows-5409c45a10dc7a045197bc4105c6a7bd5d29283f.tar.xz
wireguard-windows-5409c45a10dc7a045197bc4105c6a7bd5d29283f.zip
driver: introduce new module for talking with kernel driver
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'manager')
-rw-r--r--manager/interfacecleanup.go51
-rw-r--r--manager/ipc_driver.go59
-rw-r--r--manager/ipc_server.go83
-rw-r--r--manager/service.go2
4 files changed, 155 insertions, 40 deletions
diff --git a/manager/interfacecleanup.go b/manager/interfacecleanup.go
index c270f4ab..32976b79 100644
--- a/manager/interfacecleanup.go
+++ b/manager/interfacecleanup.go
@@ -11,33 +11,66 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
- "golang.zx2c4.com/wireguard/tun/wintun"
-
"golang.zx2c4.com/wireguard/tun"
+ "golang.zx2c4.com/wireguard/tun/wintun"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/services"
)
-func cleanupStaleWintunInterfaces() {
+func cleanupStaleNetworkInterfaces() {
m, err := mgr.Connect()
if err != nil {
return
}
defer m.Disconnect()
- tun.WintunPool.DeleteMatchingAdapters(func(wintun *wintun.Adapter) bool {
- interfaceName, err := wintun.Name()
+ if conf.AdminBool("ExperimentalKernelDriver") {
+ driver.DefaultPool.DeleteMatchingAdapters(func(wintun *driver.Adapter) bool {
+ interfaceName, err := wintun.Name()
+ if err != nil {
+ log.Printf("Removing network adapter because determining interface name failed: %v", err)
+ return true
+ }
+ serviceName, err := services.ServiceNameOfTunnel(interfaceName)
+ if err != nil {
+ log.Printf("Removing network adapter ‘%s’ because determining tunnel service name failed: %v", interfaceName, err)
+ return true
+ }
+ service, err := m.OpenService(serviceName)
+ if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
+ log.Printf("Removing network adapter ‘%s’ because no service for it exists", interfaceName)
+ return true
+ } else if err != nil {
+ return false
+ }
+ defer service.Close()
+ status, err := service.Query()
+ if err != nil {
+ return false
+ }
+ if status.State == svc.Stopped {
+ log.Printf("Removing network adapter ‘%s’ because its service is stopped", interfaceName)
+ return true
+ }
+ return false
+ })
+ }
+
+ tun.WintunPool.DeleteMatchingAdapters(func(adapter *wintun.Adapter) bool {
+ interfaceName, err := adapter.Name()
if err != nil {
- log.Printf("Removing Wintun interface because determining interface name failed: %v", err)
+ log.Printf("Removing network adapter because determining interface name failed: %v", err)
return true
}
serviceName, err := services.ServiceNameOfTunnel(interfaceName)
if err != nil {
- log.Printf("Removing Wintun interface ‘%s’ because determining tunnel service name failed: %v", interfaceName, err)
+ log.Printf("Removing network adapter ‘%s’ because determining tunnel service name failed: %v", interfaceName, err)
return true
}
service, err := m.OpenService(serviceName)
if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
- log.Printf("Removing Wintun interface ‘%s’ because no service for it exists", interfaceName)
+ log.Printf("Removing network adapter ‘%s’ because no service for it exists", interfaceName)
return true
} else if err != nil {
return false
@@ -48,7 +81,7 @@ func cleanupStaleWintunInterfaces() {
return false
}
if status.State == svc.Stopped {
- log.Printf("Removing Wintun interface ‘%s’ because its service is stopped", interfaceName)
+ log.Printf("Removing network adapter ‘%s’ because its service is stopped", interfaceName)
return true
}
return false
diff --git a/manager/ipc_driver.go b/manager/ipc_driver.go
new file mode 100644
index 00000000..dae213de
--- /dev/null
+++ b/manager/ipc_driver.go
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "sync"
+
+ "golang.zx2c4.com/wireguard/windows/driver"
+)
+
+type lockedDriverAdapter struct {
+ *driver.Adapter
+ sync.Mutex
+}
+
+var driverAdapters = make(map[string]*lockedDriverAdapter)
+var driverAdaptersLock sync.RWMutex
+
+func findDriverAdapter(tunnelName string) (*lockedDriverAdapter, error) {
+ driverAdaptersLock.RLock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ driverAdaptersLock.RUnlock()
+ return driverAdapter, nil
+ }
+ driverAdaptersLock.RUnlock()
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok = driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ return driverAdapter, nil
+ }
+ driverAdapter = &lockedDriverAdapter{}
+ var err error
+ driverAdapter.Adapter, err = driver.DefaultPool.OpenAdapter(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ driverAdapters[tunnelName] = driverAdapter
+ driverAdapter.Lock()
+ return driverAdapter, nil
+}
+
+func releaseDriverAdapter(tunnelName string) {
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if !ok {
+ return
+ }
+ driverAdapter.Lock()
+ delete(driverAdapters, tunnelName)
+ driverAdapter.Unlock()
+}
diff --git a/manager/ipc_server.go b/manager/ipc_server.go
index 9a36e60f..b9b1eb8c 100644
--- a/manager/ipc_server.go
+++ b/manager/ipc_server.go
@@ -47,41 +47,64 @@ func (s *ManagerService) StoredConfig(tunnelName string) (*conf.Config, error) {
}
func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error) {
- storedConfig, err := conf.LoadFromName(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe, err := connectTunnelServicePipe(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe.SetDeadline(time.Now().Add(time.Second * 2))
- _, err = pipe.Write([]byte("get=1\n\n"))
- if err == windows.ERROR_NO_DATA {
- log.Println("IPC pipe closed unexpectedly, so reopening")
- pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
- pipe, err = connectTunnelServicePipe(tunnelName)
+ if conf.AdminBool("ExperimentalKernelDriver") {
+ storedConfig, err := conf.LoadFromName(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ driverAdapter, err := findDriverAdapter(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ runtimeConfig, err := driverAdapter.Configuration()
+ if err != nil {
+ driverAdapter.Unlock()
+ releaseDriverAdapter(tunnelName)
+ return nil, err
+ }
+ conf := conf.FromDriverConfiguration(runtimeConfig, storedConfig)
+ driverAdapter.Unlock()
+ if s.elevatedToken == 0 {
+ conf.Redact()
+ }
+ return conf, nil
+ } else {
+ storedConfig, err := conf.LoadFromName(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ pipe, err := connectTunnelServicePipe(tunnelName)
if err != nil {
return nil, err
}
pipe.SetDeadline(time.Now().Add(time.Second * 2))
_, err = pipe.Write([]byte("get=1\n\n"))
- }
- if err != nil {
+ if err == windows.ERROR_NO_DATA {
+ log.Println("IPC pipe closed unexpectedly, so reopening")
+ pipe.Unlock()
+ disconnectTunnelServicePipe(tunnelName)
+ pipe, err = connectTunnelServicePipe(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ pipe.SetDeadline(time.Now().Add(time.Second * 2))
+ _, err = pipe.Write([]byte("get=1\n\n"))
+ }
+ if err != nil {
+ pipe.Unlock()
+ disconnectTunnelServicePipe(tunnelName)
+ return nil, err
+ }
+ conf, err := conf.FromUAPI(pipe, storedConfig)
pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
- return nil, err
- }
- conf, err := conf.FromUAPI(pipe, storedConfig)
- pipe.Unlock()
- if err != nil {
- return nil, err
- }
- if s.elevatedToken == 0 {
- conf.Redact()
+ if err != nil {
+ return nil, err
+ }
+ if s.elevatedToken == 0 {
+ conf.Redact()
+ }
+ return conf, nil
}
- return conf, nil
}
func (s *ManagerService) Start(tunnelName string) error {
@@ -116,7 +139,7 @@ func (s *ManagerService) Start(tunnelName string) error {
}
}()
}
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
+ time.AfterFunc(time.Second*10, cleanupStaleNetworkInterfaces)
// After that process is started -- it's somewhat asynchronous -- we install the new one.
c, err := conf.LoadFromName(tunnelName)
@@ -131,7 +154,7 @@ func (s *ManagerService) Start(tunnelName string) error {
}
func (s *ManagerService) Stop(tunnelName string) error {
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
+ time.AfterFunc(time.Second*10, cleanupStaleNetworkInterfaces)
err := UninstallTunnel(tunnelName)
if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
diff --git a/manager/service.go b/manager/service.go
index da6ff497..9555d386 100644
--- a/manager/service.go
+++ b/manager/service.go
@@ -254,7 +254,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}()
}
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
+ time.AfterFunc(time.Second*10, cleanupStaleNetworkInterfaces)
go checkForUpdates()
var sessionsPointer *windows.WTS_SESSION_INFO