golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/driver/configuration_windows.go (about)

     1  /* SPDX-License-Identifier: MIT
     2   *
     3   * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
     4   */
     5  
     6  package driver
     7  
     8  import (
     9  	"syscall"
    10  	"unsafe"
    11  
    12  	"golang.org/x/sys/windows"
    13  	"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
    14  )
    15  
    16  type AdapterState uint32
    17  
    18  const (
    19  	AdapterStateDown AdapterState = 0
    20  	AdapterStateUp   AdapterState = 1
    21  )
    22  
    23  type AllowedIP struct {
    24  	Address       [16]byte
    25  	AddressFamily winipcfg.AddressFamily
    26  	Cidr          uint8
    27  	_             [4]byte
    28  }
    29  
    30  type PeerFlag uint32
    31  
    32  const (
    33  	PeerHasPublicKey           PeerFlag = 1 << 0
    34  	PeerHasPresharedKey        PeerFlag = 1 << 1
    35  	PeerHasPersistentKeepalive PeerFlag = 1 << 2
    36  	PeerHasEndpoint            PeerFlag = 1 << 3
    37  	PeerReplaceAllowedIPs      PeerFlag = 1 << 5
    38  	PeerRemove                 PeerFlag = 1 << 6
    39  	PeerUpdateOnly             PeerFlag = 1 << 7
    40  )
    41  
    42  type Peer struct {
    43  	Flags               PeerFlag
    44  	_                   uint32
    45  	PublicKey           [32]byte
    46  	PresharedKey        [32]byte
    47  	PersistentKeepalive uint16
    48  	_                   uint16
    49  	Endpoint            winipcfg.RawSockaddrInet
    50  	TxBytes             uint64
    51  	RxBytes             uint64
    52  	LastHandshake       uint64
    53  	AllowedIPsCount     uint32
    54  	_                   [4]byte
    55  }
    56  
    57  type InterfaceFlag uint32
    58  
    59  const (
    60  	InterfaceHasPublicKey  InterfaceFlag = 1 << 0
    61  	InterfaceHasPrivateKey InterfaceFlag = 1 << 1
    62  	InterfaceHasListenPort InterfaceFlag = 1 << 2
    63  	InterfaceReplacePeers  InterfaceFlag = 1 << 3
    64  )
    65  
    66  type Interface struct {
    67  	Flags      InterfaceFlag
    68  	ListenPort uint16
    69  	PrivateKey [32]byte
    70  	PublicKey  [32]byte
    71  	PeerCount  uint32
    72  	_          [4]byte
    73  }
    74  
    75  var (
    76  	procWireGuardSetAdapterState  = modwireguard.NewProc("WireGuardSetAdapterState")
    77  	procWireGuardGetAdapterState  = modwireguard.NewProc("WireGuardGetAdapterState")
    78  	procWireGuardSetConfiguration = modwireguard.NewProc("WireGuardSetConfiguration")
    79  	procWireGuardGetConfiguration = modwireguard.NewProc("WireGuardGetConfiguration")
    80  )
    81  
    82  // SetAdapterState sets the adapter either Up or Down.
    83  func (wireguard *Adapter) SetAdapterState(adapterState AdapterState) (err error) {
    84  	r0, _, e1 := syscall.SyscallN(procWireGuardSetAdapterState.Addr(), wireguard.handle, uintptr(adapterState))
    85  	if r0 == 0 {
    86  		err = e1
    87  	}
    88  	return
    89  }
    90  
    91  // AdapterState returns the current state of the adapter.
    92  func (wireguard *Adapter) AdapterState() (adapterState AdapterState, err error) {
    93  	r0, _, e1 := syscall.SyscallN(procWireGuardGetAdapterState.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&adapterState)))
    94  	if r0 == 0 {
    95  		err = e1
    96  	}
    97  	return
    98  }
    99  
   100  // SetConfiguration sets the adapter configuration.
   101  func (wireguard *Adapter) SetConfiguration(interfaze *Interface, size uint32) (err error) {
   102  	r0, _, e1 := syscall.SyscallN(procWireGuardSetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(interfaze)), uintptr(size))
   103  	if r0 == 0 {
   104  		err = e1
   105  	}
   106  	return
   107  }
   108  
   109  // Configuration gets the adapter configuration.
   110  func (wireguard *Adapter) Configuration() (interfaze *Interface, err error) {
   111  	size := wireguard.lastGetGuessSize
   112  	if size == 0 {
   113  		size = 512
   114  	}
   115  	for {
   116  		buf := make([]byte, size)
   117  		r0, _, e1 := syscall.SyscallN(procWireGuardGetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&size)))
   118  		if r0 != 0 {
   119  			wireguard.lastGetGuessSize = size
   120  			return (*Interface)(unsafe.Pointer(&buf[0])), nil
   121  		}
   122  		if e1 != windows.ERROR_MORE_DATA {
   123  			return nil, e1
   124  		}
   125  	}
   126  }
   127  
   128  // FirstPeer returns the first peer attached to the interface.
   129  func (interfaze *Interface) FirstPeer() *Peer {
   130  	return (*Peer)(unsafe.Add(unsafe.Pointer(interfaze), unsafe.Sizeof(*interfaze)))
   131  }
   132  
   133  // NextPeer returns the subsequent peer of the current one.
   134  func (peer *Peer) NextPeer() *Peer {
   135  	return (*Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(peer)) + unsafe.Sizeof(*peer) + uintptr(peer.AllowedIPsCount)*unsafe.Sizeof(AllowedIP{})))
   136  }
   137  
   138  // FirstAllowedIP returns the first allowed IP attached to the peer.
   139  func (peer *Peer) FirstAllowedIP() *AllowedIP {
   140  	return (*AllowedIP)(unsafe.Add(unsafe.Pointer(peer), unsafe.Sizeof(*peer)))
   141  }
   142  
   143  // NextAllowedIP returns the subsequent allowed IP of the current one.
   144  func (allowedIP *AllowedIP) NextAllowedIP() *AllowedIP {
   145  	return (*AllowedIP)(unsafe.Add(unsafe.Pointer(allowedIP), unsafe.Sizeof(*allowedIP)))
   146  }
   147  
   148  type ConfigBuilder struct {
   149  	buffer []byte
   150  }
   151  
   152  // Preallocate reserves memory in the config builder to reduce allocations of append operations.
   153  func (builder *ConfigBuilder) Preallocate(size uint32) {
   154  	if builder.buffer == nil {
   155  		builder.buffer = make([]byte, 0, size)
   156  	}
   157  }
   158  
   159  // AppendInterface appends an interface to the building configuration. This should be called first.
   160  func (builder *ConfigBuilder) AppendInterface(interfaze *Interface) {
   161  	newBytes := unsafe.Slice((*byte)(unsafe.Pointer(interfaze)), unsafe.Sizeof(*interfaze))
   162  	builder.buffer = append(builder.buffer, newBytes...)
   163  }
   164  
   165  // AppendPeer appends a peer to the building configuration. This should be called after an interface has been added.
   166  func (builder *ConfigBuilder) AppendPeer(peer *Peer) {
   167  	newBytes := unsafe.Slice((*byte)(unsafe.Pointer(peer)), unsafe.Sizeof(*peer))
   168  	builder.buffer = append(builder.buffer, newBytes...)
   169  }
   170  
   171  // AppendAllowedIP appends an allowed IP to the building configuration. This should be called after a peer has been added.
   172  func (builder *ConfigBuilder) AppendAllowedIP(allowedIP *AllowedIP) {
   173  	newBytes := unsafe.Slice((*byte)(unsafe.Pointer(allowedIP)), unsafe.Sizeof(*allowedIP))
   174  	builder.buffer = append(builder.buffer, newBytes...)
   175  }
   176  
   177  // Interface assembles the configuration and returns the interface and length to be passed to SetConfiguration.
   178  func (builder *ConfigBuilder) Interface() (*Interface, uint32) {
   179  	if builder.buffer == nil {
   180  		return nil, 0
   181  	}
   182  	return (*Interface)(unsafe.Pointer(&builder.buffer[0])), uint32(len(builder.buffer))
   183  }