summaryrefslogtreecommitdiff
path: root/src/openvpn/ring_buffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ring_buffer.h')
-rw-r--r--src/openvpn/ring_buffer.h125
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 */