1
0
mirror of https://git.zx2c4.com/wireguard-windows synced 2024-11-10 16:59:18 +00:00
wireguard-windows/driver/driver_windows.go
Jason A. Donenfeld 6ed37f30f5 global: bump date
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2022-01-06 17:28:13 +01:00

171 lines
5.1 KiB
Go

/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"log"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
type loggerLevel int
const (
logInfo loggerLevel = iota
logWarn
logErr
)
const AdapterNameMax = 128
type Adapter struct {
handle uintptr
lastGetGuessSize uint32
}
var (
modwireguard = newLazyDLL("wireguard.dll", setupLogger)
procWireGuardCreateAdapter = modwireguard.NewProc("WireGuardCreateAdapter")
procWireGuardOpenAdapter = modwireguard.NewProc("WireGuardOpenAdapter")
procWireGuardCloseAdapter = modwireguard.NewProc("WireGuardCloseAdapter")
procWireGuardDeleteDriver = modwireguard.NewProc("WireGuardDeleteDriver")
procWireGuardGetAdapterLUID = modwireguard.NewProc("WireGuardGetAdapterLUID")
procWireGuardGetRunningDriverVersion = modwireguard.NewProc("WireGuardGetRunningDriverVersion")
procWireGuardSetAdapterLogging = modwireguard.NewProc("WireGuardSetAdapterLogging")
)
type TimestampedWriter interface {
WriteWithTimestamp(p []byte, ts int64) (n int, err error)
}
func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int {
if tw, ok := log.Default().Writer().(TimestampedWriter); ok {
tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100)
} else {
log.Println(windows.UTF16PtrToString(msg))
}
return 0
}
func setupLogger(dll *lazyDLL) {
var callback uintptr
if runtime.GOARCH == "386" {
callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "arm" {
callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
callback = windows.NewCallback(logMessage)
}
syscall.SyscallN(dll.NewProc("WireGuardSetLogger").Addr(), callback)
}
func closeAdapter(wireguard *Adapter) {
syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
}
// CreateAdapter creates a WireGuard adapter. name is the cosmetic name of the adapter.
// tunnelType represents the type of adapter and should be "WireGuard". requestedGUID is
// the GUID of the created network adapter, 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 adapter.
func CreateAdapter(name, tunnelType string, requestedGUID *windows.GUID) (wireguard *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
var tunnelType16 *uint16
tunnelType16, err = windows.UTF16PtrFromString(tunnelType)
if err != nil {
return
}
r0, _, e1 := syscall.SyscallN(procWireGuardCreateAdapter.Addr(), uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID)))
if r0 == 0 {
err = e1
return
}
wireguard = &Adapter{handle: r0}
runtime.SetFinalizer(wireguard, closeAdapter)
return
}
// OpenAdapter opens an existing WireGuard adapter by name.
func OpenAdapter(name string) (wireguard *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
r0, _, e1 := syscall.SyscallN(procWireGuardOpenAdapter.Addr(), uintptr(unsafe.Pointer(name16)))
if r0 == 0 {
err = e1
return
}
wireguard = &Adapter{handle: r0}
runtime.SetFinalizer(wireguard, closeAdapter)
return
}
// Close closes a WireGuard adapter.
func (wireguard *Adapter) Close() (err error) {
runtime.SetFinalizer(wireguard, nil)
r1, _, e1 := syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
if r1 == 0 {
err = e1
}
return
}
// Uninstall removes the driver from the system if no drivers are currently in use.
func Uninstall() (err error) {
r1, _, e1 := syscall.SyscallN(procWireGuardDeleteDriver.Addr())
if r1 == 0 {
err = e1
}
return
}
type AdapterLogState uint32
const (
AdapterLogOff AdapterLogState = 0
AdapterLogOn AdapterLogState = 1
AdapterLogOnWithPrefix AdapterLogState = 2
)
// SetLogging enables or disables logging on the WireGuard adapter.
func (wireguard *Adapter) SetLogging(logState AdapterLogState) (err error) {
r1, _, e1 := syscall.SyscallN(procWireGuardSetAdapterLogging.Addr(), wireguard.handle, uintptr(logState))
if r1 == 0 {
err = e1
}
return
}
// RunningVersion returns the version of the loaded driver.
func RunningVersion() (version uint32, err error) {
r0, _, e1 := syscall.SyscallN(procWireGuardGetRunningDriverVersion.Addr())
version = uint32(r0)
if version == 0 {
err = e1
}
return
}
// LUID returns the LUID of the adapter.
func (wireguard *Adapter) LUID() (luid winipcfg.LUID) {
syscall.SyscallN(procWireGuardGetAdapterLUID.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&luid)))
return
}