mirror of
https://git.zx2c4.com/wireguard-windows
synced 2024-11-10 16:59:18 +00:00
6ed37f30f5
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
184 lines
5.7 KiB
Go
184 lines
5.7 KiB
Go
/* 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))
|
|
}
|