github.com/apernet/sing-tun@v0.2.6-0.20240323130332-b9f6511036ad/internal/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 "runtime" 10 "syscall" 11 "unsafe" 12 13 "golang.org/x/sys/windows" 14 ) 15 16 type ( 17 Adapter struct { 18 handle uintptr 19 } 20 ) 21 22 var ( 23 modwintun = newLazyDLL("wintun.dll") 24 procWintunCreateAdapter = modwintun.NewProc("WintunCreateAdapter") 25 procWintunOpenAdapter = modwintun.NewProc("WintunOpenAdapter") 26 procWintunCloseAdapter = modwintun.NewProc("WintunCloseAdapter") 27 procWintunDeleteDriver = modwintun.NewProc("WintunDeleteDriver") 28 procWintunGetAdapterLUID = modwintun.NewProc("WintunGetAdapterLUID") 29 procWintunGetRunningDriverVersion = modwintun.NewProc("WintunGetRunningDriverVersion") 30 ) 31 32 func closeAdapter(wintun *Adapter) { 33 syscall.SyscallN(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) 34 } 35 36 // CreateAdapter creates a Wintun adapter. name is the cosmetic name of the adapter. 37 // tunnelType represents the type of adapter and should be "Wintun". requestedGUID is 38 // the GUID of the created network adapter, which then influences NLA generation 39 // deterministically. If it is set to nil, the GUID is chosen by the system at random, 40 // and hence a new NLA entry is created for each new adapter. 41 func CreateAdapter(name string, tunnelType string, requestedGUID *windows.GUID) (wintun *Adapter, err error) { 42 var name16 *uint16 43 name16, err = windows.UTF16PtrFromString(name) 44 if err != nil { 45 return 46 } 47 var tunnelType16 *uint16 48 tunnelType16, err = windows.UTF16PtrFromString(tunnelType) 49 if err != nil { 50 return 51 } 52 r0, _, e1 := syscall.Syscall(procWintunCreateAdapter.Addr(), 3, uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID))) 53 if r0 == 0 { 54 err = e1 55 return 56 } 57 wintun = &Adapter{handle: r0} 58 runtime.SetFinalizer(wintun, closeAdapter) 59 return 60 } 61 62 // OpenAdapter opens an existing Wintun adapter by name. 63 func OpenAdapter(name string) (wintun *Adapter, err error) { 64 var name16 *uint16 65 name16, err = windows.UTF16PtrFromString(name) 66 if err != nil { 67 return 68 } 69 r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 1, uintptr(unsafe.Pointer(name16)), 0, 0) 70 if r0 == 0 { 71 err = e1 72 return 73 } 74 wintun = &Adapter{handle: r0} 75 runtime.SetFinalizer(wintun, closeAdapter) 76 return 77 } 78 79 // Close closes a Wintun adapter. 80 func (wintun *Adapter) Close() (err error) { 81 runtime.SetFinalizer(wintun, nil) 82 r1, _, e1 := syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) 83 if r1 == 0 { 84 err = e1 85 } 86 return 87 } 88 89 // Uninstall removes the driver from the system if no drivers are currently in use. 90 func Uninstall() (err error) { 91 r1, _, e1 := syscall.Syscall(procWintunDeleteDriver.Addr(), 0, 0, 0, 0) 92 if r1 == 0 { 93 err = e1 94 } 95 return 96 } 97 98 // RunningVersion returns the version of the running Wintun driver. 99 func RunningVersion() (version uint32, err error) { 100 r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0) 101 version = uint32(r0) 102 if version == 0 { 103 err = e1 104 } 105 return 106 } 107 108 // LUID returns the LUID of the adapter. 109 func (wintun *Adapter) LUID() (luid uint64) { 110 syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0) 111 return 112 }