aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/manager
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-10-19 16:09:19 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2021-10-20 01:15:24 -0600
commit58a4703b0b5f01f333f6f82b4cfcb0c774ecffeb (patch)
tree816fc1190b73a378ea157fba782efc6dbcdcd8ec /manager
parentdriver: update naming of update only (diff)
downloadwireguard-windows-58a4703b0b5f01f333f6f82b4cfcb0c774ecffeb.tar.xz
wireguard-windows-58a4703b0b5f01f333f6f82b4cfcb0c774ecffeb.zip
manager: warn about dnscache and old virtio driver
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'manager')
-rw-r--r--manager/pitfalls.go136
-rw-r--r--manager/service.go2
2 files changed, 138 insertions, 0 deletions
diff --git a/manager/pitfalls.go b/manager/pitfalls.go
new file mode 100644
index 00000000..b178b615
--- /dev/null
+++ b/manager/pitfalls.go
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "log"
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc/mgr"
+)
+
+func checkForPitfalls() {
+ go func() {
+ pitfallDnsCacheDisabled()
+ pitfallVirtioNetworkDriver()
+ }()
+}
+
+func pitfallDnsCacheDisabled() {
+ scm, err := mgr.Connect()
+ if err != nil {
+ return
+ }
+ defer scm.Disconnect()
+ svc := mgr.Service{Name: "dnscache"}
+ svc.Handle, err = windows.OpenService(scm.Handle, windows.StringToUTF16Ptr(svc.Name), windows.SERVICE_QUERY_CONFIG)
+ if err != nil {
+ return
+ }
+ defer svc.Close()
+ cfg, err := svc.Config()
+ if err != nil {
+ return
+ }
+ if cfg.StartType != mgr.StartDisabled {
+ return
+ }
+
+ log.Printf("Warning: the %q (dnscache) service is disabled; please re-enable it", cfg.DisplayName)
+}
+
+/* TODO: put this into x/sys/windows */
+
+var versionDll = windows.NewLazySystemDLL("version.dll")
+var getFileVersionInfo = versionDll.NewProc("GetFileVersionInfoW")
+var getFileVersionInfoSize = versionDll.NewProc("GetFileVersionInfoSizeW")
+var verQueryValue = versionDll.NewProc("VerQueryValueW")
+
+type VS_FIXEDFILEINFO struct {
+ Signature uint32
+ StrucVersion uint32
+ FileVersionMS uint32
+ FileVersionLS uint32
+ ProductVersionMS uint32
+ ProductVersionLS uint32
+ FileFlagsMask uint32
+ FileFlags uint32
+ FileOS uint32
+ FileType uint32
+ FileSubtype uint32
+ FileDateMS uint32
+ FileDateLS uint32
+}
+
+var ntQuerySystemInformation = windows.NewLazySystemDLL("ntdll.dll").NewProc("NtQuerySystemInformation")
+
+const systemModuleInformation = 11
+
+type RTL_PROCESS_MODULE_INFORMATION struct {
+ Section windows.Handle
+ MappedBase uintptr
+ ImageBase uintptr
+ ImageSize uint32
+ Flags uint32
+ LoadOrderIndex uint16
+ InitOrderIndex uint16
+ LoadCount uint16
+ OffsetToFileName uint16
+ FullPathName [256]byte
+}
+
+type RTL_PROCESS_MODULES struct {
+ NumberOfModules uint32
+ FirstModule RTL_PROCESS_MODULE_INFORMATION
+}
+
+func pitfallVirtioNetworkDriver() {
+ var modules []RTL_PROCESS_MODULE_INFORMATION
+ for bufferSize := uint32(128 * 1024); ; {
+ moduleBuffer := make([]byte, bufferSize)
+ ret, _, _ := ntQuerySystemInformation.Call(systemModuleInformation, uintptr(unsafe.Pointer(&moduleBuffer[0])), uintptr(bufferSize), uintptr(unsafe.Pointer(&bufferSize)))
+ switch windows.NTStatus(ret) {
+ case windows.STATUS_INFO_LENGTH_MISMATCH:
+ continue
+ case windows.STATUS_SUCCESS:
+ break
+ default:
+ return
+ }
+ mods := (*RTL_PROCESS_MODULES)(unsafe.Pointer(&moduleBuffer[0]))
+ modules = unsafe.Slice(&mods.FirstModule, mods.NumberOfModules)
+ break
+ }
+ for i := range modules {
+ if !strings.EqualFold(windows.ByteSliceToString(modules[i].FullPathName[modules[i].OffsetToFileName:]), "netkvm.sys") {
+ continue
+ }
+ driverPath := `\\?\GLOBALROOT` + windows.ByteSliceToString(modules[i].FullPathName[:])
+ zero := uint32(0)
+ ret, _, _ := getFileVersionInfoSize.Call(uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(driverPath))), uintptr(unsafe.Pointer(&zero)))
+ if ret == 0 {
+ return
+ }
+ infoSize := uint32(ret)
+ versionInfo := make([]byte, infoSize)
+ ret, _, _ = getFileVersionInfo.Call(uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(driverPath))), 0, uintptr(infoSize), uintptr(unsafe.Pointer(&versionInfo[0])))
+ var fixedInfo *VS_FIXEDFILEINFO
+ fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
+ ret, _, _ = verQueryValue.Call(uintptr(unsafe.Pointer(&versionInfo[0])), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(`\`))), uintptr(unsafe.Pointer(&fixedInfo)), uintptr(unsafe.Pointer(&fixedInfoLen)))
+ if ret == 0 {
+ return
+ }
+ const minimumGoodVersion = (100 << 48) | (85 << 32) | (104 << 16) | (20800 << 0)
+ version := (uint64(fixedInfo.FileVersionMS) << 32) | uint64(fixedInfo.FileVersionLS)
+ if version >= minimumGoodVersion {
+ return
+ }
+ log.Println("Warning: the VirtIO network driver (NetKVM) is out of date and may cause known problems; please update to v100.85.104.20800 or later")
+ return
+ }
+}
diff --git a/manager/service.go b/manager/service.go
index af9004de..15ea88f0 100644
--- a/manager/service.go
+++ b/manager/service.go
@@ -56,6 +56,8 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
log.Println("Starting", version.UserAgent())
+ checkForPitfalls()
+
path, err := os.Executable()
if err != nil {
serviceError = services.ErrorDetermineExecutablePath