github.com/bugfan/wireguard-go@v0.0.0-20230720020150-a7b2fa340c66/tun/wintun/wintun_windows.go (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. 4 */ 5 6 package wintun 7 8 import ( 9 "log" 10 "runtime" 11 "syscall" 12 "unsafe" 13 14 "golang.org/x/sys/windows" 15 ) 16 17 type loggerLevel int 18 19 const ( 20 logInfo loggerLevel = iota 21 logWarn 22 logErr 23 ) 24 25 const AdapterNameMax = 128 26 27 type Adapter struct { 28 handle uintptr 29 } 30 31 var ( 32 modwintun = newLazyDLL("wintun.dll", setupLogger) 33 procWintunCreateAdapter = modwintun.NewProc("WintunCreateAdapter") 34 procWintunOpenAdapter = modwintun.NewProc("WintunOpenAdapter") 35 procWintunCloseAdapter = modwintun.NewProc("WintunCloseAdapter") 36 procWintunDeleteDriver = modwintun.NewProc("WintunDeleteDriver") 37 procWintunGetAdapterLUID = modwintun.NewProc("WintunGetAdapterLUID") 38 procWintunGetRunningDriverVersion = modwintun.NewProc("WintunGetRunningDriverVersion") 39 ) 40 41 type TimestampedWriter interface { 42 WriteWithTimestamp(p []byte, ts int64) (n int, err error) 43 } 44 45 func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int { 46 if tw, ok := log.Default().Writer().(TimestampedWriter); ok { 47 tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100) 48 } else { 49 log.Println(windows.UTF16PtrToString(msg)) 50 } 51 return 0 52 } 53 54 func setupLogger(dll *lazyDLL) { 55 var callback uintptr 56 if runtime.GOARCH == "386" || runtime.GOARCH == "arm" { 57 callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int { 58 return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg) 59 }) 60 } else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" { 61 callback = windows.NewCallback(logMessage) 62 } 63 syscall.Syscall(dll.NewProc("WintunSetLogger").Addr(), 1, callback, 0, 0) 64 } 65 66 func closeAdapter(wintun *Adapter) { 67 syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) 68 } 69 70 // CreateAdapter creates a Wintun adapter. name is the cosmetic name of the adapter. 71 // tunnelType represents the type of adapter and should be "Wintun". requestedGUID is 72 // the GUID of the created network adapter, which then influences NLA generation 73 // deterministically. If it is set to nil, the GUID is chosen by the system at random, 74 // and hence a new NLA entry is created for each new adapter. 75 func CreateAdapter(name string, tunnelType string, requestedGUID *windows.GUID) (wintun *Adapter, err error) { 76 var name16 *uint16 77 name16, err = windows.UTF16PtrFromString(name) 78 if err != nil { 79 return 80 } 81 var tunnelType16 *uint16 82 tunnelType16, err = windows.UTF16PtrFromString(tunnelType) 83 if err != nil { 84 return 85 } 86 r0, _, e1 := syscall.Syscall(procWintunCreateAdapter.Addr(), 3, uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID))) 87 if r0 == 0 { 88 err = e1 89 return 90 } 91 wintun = &Adapter{handle: r0} 92 runtime.SetFinalizer(wintun, closeAdapter) 93 return 94 } 95 96 // OpenAdapter opens an existing Wintun adapter by name. 97 func OpenAdapter(name string) (wintun *Adapter, err error) { 98 var name16 *uint16 99 name16, err = windows.UTF16PtrFromString(name) 100 if err != nil { 101 return 102 } 103 r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 1, uintptr(unsafe.Pointer(name16)), 0, 0) 104 if r0 == 0 { 105 err = e1 106 return 107 } 108 wintun = &Adapter{handle: r0} 109 runtime.SetFinalizer(wintun, closeAdapter) 110 return 111 } 112 113 // Close closes a Wintun adapter. 114 func (wintun *Adapter) Close() (err error) { 115 runtime.SetFinalizer(wintun, nil) 116 r1, _, e1 := syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) 117 if r1 == 0 { 118 err = e1 119 } 120 return 121 } 122 123 // Uninstall removes the driver from the system if no drivers are currently in use. 124 func Uninstall() (err error) { 125 r1, _, e1 := syscall.Syscall(procWintunDeleteDriver.Addr(), 0, 0, 0, 0) 126 if r1 == 0 { 127 err = e1 128 } 129 return 130 } 131 132 // RunningVersion returns the version of the running Wintun driver. 133 func RunningVersion() (version uint32, err error) { 134 r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0) 135 version = uint32(r0) 136 if version == 0 { 137 err = e1 138 } 139 return 140 } 141 142 // LUID returns the LUID of the adapter. 143 func (wintun *Adapter) LUID() (luid uint64) { 144 syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0) 145 return 146 }