diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-29 12:47:16 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-08-29 13:22:17 -0600 |
commit | 353f0956bccf4919f7764166f1dd0f2c8bb7cca2 (patch) | |
tree | 7a086d5a4c93f86a54c2e8e659cf9866b64ef018 /tun/wintun | |
parent | fa7763c268d2f5b93aa76f673ae0db7e740cf08d (diff) |
wintun: move ring constants into module
Diffstat (limited to 'tun/wintun')
-rw-r--r-- | tun/wintun/ring.go | 97 | ||||
-rw-r--r-- | tun/wintun/wintun_windows.go | 4 |
2 files changed, 99 insertions, 2 deletions
diff --git a/tun/wintun/ring.go b/tun/wintun/ring.go new file mode 100644 index 0000000..8f46bc9 --- /dev/null +++ b/tun/wintun/ring.go @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package wintun + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +const ( + PacketAlignment = 4 // Number of bytes packets are aligned to in rings + PacketSizeMax = 0xffff // Maximum packet size + PacketCapacity = 0x800000 // Ring capacity, 8MiB + PacketTrailingSize = uint32(unsafe.Sizeof(PacketHeader{})) + ((PacketSizeMax + (PacketAlignment - 1)) &^ (PacketAlignment - 1)) - PacketAlignment + ioctlRegisterRings = (51820 << 16) | (0x970 << 2) | 0 /*METHOD_BUFFERED*/ | (0x3 /*FILE_READ_DATA | FILE_WRITE_DATA*/ << 14) +) + +type PacketHeader struct { + Size uint32 +} + +type Packet struct { + PacketHeader + Data [PacketSizeMax]byte +} + +type Ring struct { + Head uint32 + Tail uint32 + Alertable int32 + Data [PacketCapacity + PacketTrailingSize]byte +} + +type RingDescriptor struct { + Send, Receive struct { + Size uint32 + Ring *Ring + TailMoved windows.Handle + } +} + +// Wrap returns value modulo ring capacity +func (rb *Ring) Wrap(value uint32) uint32 { + return value & (PacketCapacity - 1) +} + +// Aligns a packet size to PacketAlignment +func PacketAlign(size uint32) uint32 { + return (size + (PacketAlignment - 1)) &^ (PacketAlignment - 1) +} + +func (descriptor *RingDescriptor) Init() (err error) { + descriptor.Send.Size = uint32(unsafe.Sizeof(Ring{})) + descriptor.Send.Ring = &Ring{} + descriptor.Send.TailMoved, err = windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return + } + + descriptor.Receive.Size = uint32(unsafe.Sizeof(Ring{})) + descriptor.Receive.Ring = &Ring{} + descriptor.Receive.TailMoved, err = windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + windows.CloseHandle(descriptor.Send.TailMoved) + return + } + + return +} + +func (descriptor *RingDescriptor) Close() { + if descriptor.Send.TailMoved != 0 { + windows.CloseHandle(descriptor.Send.TailMoved) + descriptor.Send.TailMoved = 0 + } + if descriptor.Send.TailMoved != 0 { + windows.CloseHandle(descriptor.Receive.TailMoved) + descriptor.Receive.TailMoved = 0 + } +} + +func (wintun *Interface) Register(descriptor *RingDescriptor) (windows.Handle, error) { + handle, err := wintun.handle() + if err != nil { + return 0, err + } + var bytesReturned uint32 + err = windows.DeviceIoControl(handle, ioctlRegisterRings, (*byte)(unsafe.Pointer(descriptor)), uint32(unsafe.Sizeof(*descriptor)), nil, 0, &bytesReturned, nil) + if err != nil { + return 0, err + } + return handle, nil +} diff --git a/tun/wintun/wintun_windows.go b/tun/wintun/wintun_windows.go index fb8b908..e726748 100644 --- a/tun/wintun/wintun_windows.go +++ b/tun/wintun/wintun_windows.go @@ -698,8 +698,8 @@ func (wintun *Interface) deviceData() (setupapi.DevInfo, *setupapi.DevInfoData, return 0, nil, windows.ERROR_OBJECT_NOT_FOUND } -// Handle returns a handle to the interface device object. -func (wintun *Interface) Handle() (windows.Handle, error) { +// handle returns a handle to the interface device object. +func (wintun *Interface) handle() (windows.Handle, error) { interfaces, err := setupapi.CM_Get_Device_Interface_List(wintun.devInstanceID, &deviceInterfaceNetGUID, setupapi.CM_GET_DEVICE_INTERFACE_LIST_PRESENT) if err != nil { return windows.InvalidHandle, fmt.Errorf("Error listing NDIS interfaces: %v", err) |