]>
Commit | Line | Data |
---|---|---|
da2e66ca LS |
1 | /* |
2 | * OpenVPN -- An application to securely tunnel IP networks | |
3 | * over a single UDP port, with support for SSL/TLS-based | |
4 | * session authentication and key exchange, | |
5 | * packet encryption, packet authentication, and | |
6 | * packet compression. | |
7 | * | |
b25c6d7e | 8 | * Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net> |
da2e66ca LS |
9 | * 2019 Lev Stipakov <lev@openvpn.net> |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License version 2 | |
13 | * as published by the Free Software Foundation. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License along | |
21 | * with this program; if not, write to the Free Software Foundation, Inc., | |
22 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
23 | */ | |
24 | ||
25 | #ifdef _WIN32 | |
26 | #ifndef OPENVPN_RING_BUFFER_H | |
27 | #define OPENVPN_RING_BUFFER_H | |
28 | ||
29 | #include <windows.h> | |
30 | #include <winioctl.h> | |
31 | ||
32 | #include <stdint.h> | |
33 | #include <stdbool.h> | |
34 | ||
35 | /* | |
36 | * Values below are taken from Wireguard Windows client | |
37 | * https://github.com/WireGuard/wireguard-go/blob/master/tun/wintun/ring_windows.go#L14 | |
38 | */ | |
39 | #define WINTUN_RING_CAPACITY 0x800000 | |
40 | #define WINTUN_RING_TRAILING_BYTES 0x10000 | |
41 | #define WINTUN_MAX_PACKET_SIZE 0xffff | |
42 | #define WINTUN_PACKET_ALIGN 4 | |
43 | ||
44 | #define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) | |
45 | ||
46 | /** | |
47 | * Wintun ring buffer | |
48 | * See https://github.com/WireGuard/wintun#ring-layout | |
49 | */ | |
50 | struct tun_ring | |
51 | { | |
52 | volatile ULONG head; | |
53 | volatile ULONG tail; | |
54 | volatile LONG alertable; | |
55 | UCHAR data[WINTUN_RING_CAPACITY + WINTUN_RING_TRAILING_BYTES]; | |
56 | }; | |
57 | ||
58 | /** | |
59 | * Struct for ring buffers registration | |
60 | * See https://github.com/WireGuard/wintun#registering-rings | |
61 | */ | |
62 | struct tun_register_rings | |
63 | { | |
64 | struct | |
65 | { | |
66 | ULONG ring_size; | |
67 | struct tun_ring *ring; | |
68 | HANDLE tail_moved; | |
69 | } send, receive; | |
70 | }; | |
71 | ||
72 | struct TUN_PACKET_HEADER | |
73 | { | |
74 | uint32_t size; | |
75 | }; | |
76 | ||
77 | struct TUN_PACKET | |
78 | { | |
79 | uint32_t size; | |
80 | UCHAR data[WINTUN_MAX_PACKET_SIZE]; | |
81 | }; | |
82 | ||
83 | /** | |
84 | * Registers ring buffers used to exchange data between | |
85 | * userspace openvpn process and wintun kernel driver, | |
86 | * see https://github.com/WireGuard/wintun#registering-rings | |
87 | * | |
88 | * @param device handle to opened wintun device | |
89 | * @param send_ring pointer to send ring | |
90 | * @param receive_ring pointer to receive ring | |
91 | * @param send_tail_moved event set by wintun to signal openvpn | |
92 | * that data is available for reading in send ring | |
93 | * @param receive_tail_moved event set by openvpn to signal wintun | |
94 | * that data has been written to receive ring | |
089fbe65 | 95 | * @return true if registration is successful, false otherwise - use GetLastError() |
da2e66ca | 96 | */ |
71371f04 | 97 | static inline bool |
6d19775a LS |
98 | register_ring_buffers(HANDLE device, |
99 | struct tun_ring *send_ring, | |
100 | struct tun_ring *receive_ring, | |
101 | HANDLE send_tail_moved, | |
102 | HANDLE receive_tail_moved) | |
103 | { | |
104 | struct tun_register_rings rr; | |
105 | BOOL res; | |
106 | DWORD bytes_returned; | |
107 | ||
108 | ZeroMemory(&rr, sizeof(rr)); | |
109 | ||
110 | rr.send.ring = send_ring; | |
111 | rr.send.ring_size = sizeof(struct tun_ring); | |
112 | rr.send.tail_moved = send_tail_moved; | |
113 | ||
114 | rr.receive.ring = receive_ring; | |
115 | rr.receive.ring_size = sizeof(struct tun_ring); | |
116 | rr.receive.tail_moved = receive_tail_moved; | |
117 | ||
118 | res = DeviceIoControl(device, TUN_IOCTL_REGISTER_RINGS, &rr, sizeof(rr), | |
abe49856 | 119 | NULL, 0, &bytes_returned, NULL); |
6d19775a LS |
120 | |
121 | return res != FALSE; | |
122 | } | |
da2e66ca LS |
123 | |
124 | #endif /* ifndef OPENVPN_RING_BUFFER_H */ | |
125 | #endif /* ifdef _WIN32 */ |