/* * 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-2021 OpenVPN Inc * 2019 Lev Stipakov * * 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 #include #include #include /* * 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 */