github.com/metacubex/sing-tun@v0.2.7-0.20240512075008-89e7c6208eec/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  }