aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/driver/configuration_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'driver/configuration_windows.go')
-rw-r--r--driver/configuration_windows.go183
1 files changed, 183 insertions, 0 deletions
diff --git a/driver/configuration_windows.go b/driver/configuration_windows.go
new file mode 100644
index 00000000..d838dcf2
--- /dev/null
+++ b/driver/configuration_windows.go
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type AdapterState uint32
+
+const (
+ AdapterStateDown AdapterState = 0
+ AdapterStateUp AdapterState = 1
+)
+
+type AllowedIP struct {
+ Address [16]byte
+ AddressFamily winipcfg.AddressFamily
+ Cidr uint8
+ _ [4]byte
+}
+
+type PeerFlag uint32
+
+const (
+ PeerHasPublicKey PeerFlag = 1 << 0
+ PeerHasPresharedKey PeerFlag = 1 << 1
+ PeerHasPersistentKeepalive PeerFlag = 1 << 2
+ PeerHasEndpoint PeerFlag = 1 << 3
+ PeerReplaceAllowedIPs PeerFlag = 1 << 5
+ PeerRemove PeerFlag = 1 << 6
+ PeerUpdateOnly PeerFlag = 1 << 7
+)
+
+type Peer struct {
+ Flags PeerFlag
+ _ uint32
+ PublicKey [32]byte
+ PresharedKey [32]byte
+ PersistentKeepalive uint16
+ _ uint16
+ Endpoint winipcfg.RawSockaddrInet
+ TxBytes uint64
+ RxBytes uint64
+ LastHandshake uint64
+ AllowedIPsCount uint32
+ _ [4]byte
+}
+
+type InterfaceFlag uint32
+
+const (
+ InterfaceHasPublicKey InterfaceFlag = 1 << 0
+ InterfaceHasPrivateKey InterfaceFlag = 1 << 1
+ InterfaceHasListenPort InterfaceFlag = 1 << 2
+ InterfaceReplacePeers InterfaceFlag = 1 << 3
+)
+
+type Interface struct {
+ Flags InterfaceFlag
+ ListenPort uint16
+ PrivateKey [32]byte
+ PublicKey [32]byte
+ PeerCount uint32
+ _ [4]byte
+}
+
+var (
+ procWireGuardSetAdapterState = modwireguard.NewProc("WireGuardSetAdapterState")
+ procWireGuardGetAdapterState = modwireguard.NewProc("WireGuardGetAdapterState")
+ procWireGuardSetConfiguration = modwireguard.NewProc("WireGuardSetConfiguration")
+ procWireGuardGetConfiguration = modwireguard.NewProc("WireGuardGetConfiguration")
+)
+
+// SetAdapterState sets the adapter either Up or Down.
+func (wireguard *Adapter) SetAdapterState(adapterState AdapterState) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetAdapterState.Addr(), wireguard.handle, uintptr(adapterState))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// AdapterState returns the current state of the adapter.
+func (wireguard *Adapter) AdapterState() (adapterState AdapterState, err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetAdapterState.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&adapterState)))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// SetConfiguration sets the adapter configuration.
+func (wireguard *Adapter) SetConfiguration(interfaze *Interface, size uint32) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(interfaze)), uintptr(size))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// Configuration gets the adapter configuration.
+func (wireguard *Adapter) Configuration() (interfaze *Interface, err error) {
+ size := wireguard.lastGetGuessSize
+ if size == 0 {
+ size = 512
+ }
+ for {
+ buf := make([]byte, size)
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&size)))
+ if r0 != 0 {
+ wireguard.lastGetGuessSize = size
+ return (*Interface)(unsafe.Pointer(&buf[0])), nil
+ }
+ if e1 != windows.ERROR_MORE_DATA {
+ return nil, e1
+ }
+ }
+}
+
+// FirstPeer returns the first peer attached to the interface.
+func (interfaze *Interface) FirstPeer() *Peer {
+ return (*Peer)(unsafe.Add(unsafe.Pointer(interfaze), unsafe.Sizeof(*interfaze)))
+}
+
+// NextPeer returns the subsequent peer of the current one.
+func (peer *Peer) NextPeer() *Peer {
+ return (*Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(peer)) + unsafe.Sizeof(*peer) + uintptr(peer.AllowedIPsCount)*unsafe.Sizeof(AllowedIP{})))
+}
+
+// FirstAllowedIP returns the first allowed IP attached to the peer.
+func (peer *Peer) FirstAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(peer), unsafe.Sizeof(*peer)))
+}
+
+// NextAllowedIP returns the subsequent allowed IP of the current one.
+func (allowedIP *AllowedIP) NextAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(allowedIP), unsafe.Sizeof(*allowedIP)))
+}
+
+type ConfigBuilder struct {
+ buffer []byte
+}
+
+// Preallocate reserves memory in the config builder to reduce allocations of append operations.
+func (builder *ConfigBuilder) Preallocate(size uint32) {
+ if builder.buffer == nil {
+ builder.buffer = make([]byte, 0, size)
+ }
+}
+
+// AppendInterface appends an interface to the building configuration. This should be called first.
+func (builder *ConfigBuilder) AppendInterface(interfaze *Interface) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(interfaze)), unsafe.Sizeof(*interfaze))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendPeer appends a peer to the building configuration. This should be called after an interface has been added.
+func (builder *ConfigBuilder) AppendPeer(peer *Peer) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(peer)), unsafe.Sizeof(*peer))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendAllowedIP appends an allowed IP to the building configuration. This should be called after a peer has been added.
+func (builder *ConfigBuilder) AppendAllowedIP(allowedIP *AllowedIP) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(allowedIP)), unsafe.Sizeof(*allowedIP))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// Interface assembles the configuration and returns the interface and length to be passed to SetConfiguration.
+func (builder *ConfigBuilder) Interface() (*Interface, uint32) {
+ if builder.buffer == nil {
+ return nil, 0
+ }
+ return (*Interface)(unsafe.Pointer(&builder.buffer[0])), uint32(len(builder.buffer))
+}