diff options
author | Bernhard Schmidt <berni@debian.org> | 2020-09-01 16:52:17 +0200 |
---|---|---|
committer | Bernhard Schmidt <berni@debian.org> | 2020-09-01 16:52:17 +0200 |
commit | 9fc3b98112217f2d92a67977dbde0987cc7a1803 (patch) | |
tree | 29fcc8654ee65d9dd89ade797bea2f3d9dfd9cfd /src/openvpn/ring_buffer.h | |
parent | a8758c0e03eed188dcb9da0e4fd781a67c25bf1e (diff) | |
parent | 69b02b1f7fd609d84ace13ab04697158de2418a9 (diff) |
Merge branch 'debian/experimental-2.5'
Diffstat (limited to 'src/openvpn/ring_buffer.h')
-rw-r--r-- | src/openvpn/ring_buffer.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/openvpn/ring_buffer.h b/src/openvpn/ring_buffer.h new file mode 100644 index 0000000..4293f63 --- /dev/null +++ b/src/openvpn/ring_buffer.h @@ -0,0 +1,125 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2019 OpenVPN Inc <sales@openvpn.net> + * 2019 Lev Stipakov <lev@openvpn.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef _WIN32 +#ifndef OPENVPN_RING_BUFFER_H +#define OPENVPN_RING_BUFFER_H + +#include <windows.h> +#include <winioctl.h> + +#include <stdint.h> +#include <stdbool.h> + +/* + * Values below are taken from Wireguard Windows client + * https://github.com/WireGuard/wireguard-go/blob/master/tun/wintun/ring_windows.go#L14 + */ +#define WINTUN_RING_CAPACITY 0x800000 +#define WINTUN_RING_TRAILING_BYTES 0x10000 +#define WINTUN_MAX_PACKET_SIZE 0xffff +#define WINTUN_PACKET_ALIGN 4 + +#define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) + +/** + * Wintun ring buffer + * See https://github.com/WireGuard/wintun#ring-layout + */ +struct tun_ring +{ + volatile ULONG head; + volatile ULONG tail; + volatile LONG alertable; + UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES]; +}; + +/** + * Struct for ring buffers registration + * See https://github.com/WireGuard/wintun#registering-rings + */ +struct tun_register_rings +{ + struct + { + ULONG ring_size; + struct tun_ring *ring; + HANDLE tail_moved; + } send, receive; +}; + +struct TUN_PACKET_HEADER +{ + uint32_t size; +}; + +struct TUN_PACKET +{ + uint32_t size; + UCHAR data[WINTUN_MAX_PACKET_SIZE]; +}; + +/** + * Registers ring buffers used to exchange data between + * userspace openvpn process and wintun kernel driver, + * see https://github.com/WireGuard/wintun#registering-rings + * + * @param device handle to opened wintun device + * @param send_ring pointer to send ring + * @param receive_ring pointer to receive ring + * @param send_tail_moved event set by wintun to signal openvpn + * that data is available for reading in send ring + * @param receive_tail_moved event set by openvpn to signal wintun + * that data has been written to receive ring + * @return true if registration is successful, false otherwise - use GetLastError() + */ +static bool +register_ring_buffers(HANDLE device, + struct tun_ring *send_ring, + struct tun_ring *receive_ring, + HANDLE send_tail_moved, + HANDLE receive_tail_moved) +{ + struct tun_register_rings rr; + BOOL res; + DWORD bytes_returned; + + ZeroMemory(&rr, sizeof(rr)); + + rr.send.ring = send_ring; + rr.send.ring_size = sizeof(struct tun_ring); + rr.send.tail_moved = send_tail_moved; + + rr.receive.ring = receive_ring; + rr.receive.ring_size = sizeof(struct tun_ring); + rr.receive.tail_moved = receive_tail_moved; + + res = DeviceIoControl(device, TUN_IOCTL_REGISTER_RINGS, &rr, sizeof(rr), + NULL, 0, &bytes_returned, NULL); + + return res != FALSE; +} + +#endif /* ifndef OPENVPN_RING_BUFFER_H */ +#endif /* ifdef _WIN32 */ |