40 #if defined(__MINGW32__)
41 const IN_ADDR in4addr_any = { 0 };
48 const char *device_guid;
71 for (
int i = 0; i < 20; ++i)
73 MIB_IPINTERFACE_ROW row = {.InterfaceIndex = idx, .Family = AF_INET};
74 if (GetIpInterfaceEntry(&row) != ERROR_NOT_FOUND)
93 DWORD bytes_returned = 0;
95 &bytes_returned, NULL))
97 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_START_VPN) failed");
111 typedef BOOL (WINAPI *get_overlapped_result_ex_t)(HANDLE, LPOVERLAPPED, LPDWORD, DWORD, BOOL);
112 get_overlapped_result_ex_t get_overlapped_result_ex =
113 (get_overlapped_result_ex_t)GetProcAddress(GetModuleHandle(
"Kernel32.dll"),
114 "GetOverlappedResultEx");
116 if (get_overlapped_result_ex == NULL)
118 msg(
M_ERR,
"Failed to load GetOverlappedResult()");
121 DWORD timeout_msec = timeout * 1000;
122 const int poll_interval_ms = 50;
124 while (timeout_msec > 0)
126 timeout_msec -= poll_interval_ms;
129 if (get_overlapped_result_ex(handle, ov, &transferred, poll_interval_ms, FALSE) != 0)
135 DWORD err = GetLastError();
136 if ((err != WAIT_TIMEOUT) && (err != ERROR_IO_INCOMPLETE))
145 if (*signal_received)
160 struct addrinfo *bind,
int timeout,
167 struct sockaddr *local = NULL;
168 struct sockaddr *remote = remoteaddr->ai_addr;
170 if (remoteaddr->ai_protocol == IPPROTO_TCP
171 || remoteaddr->ai_socktype == SOCK_STREAM)
183 while (bind && !local)
185 if (bind->ai_family == remote->sa_family)
187 local = bind->ai_addr;
189 bind = bind->ai_next;
195 msg(
M_FATAL,
"DCO: Socket bind failed: Address to bind lacks %s record",
199 if (remote->sa_family == AF_INET6)
201 peer.
Remote.
Addr6 = *((SOCKADDR_IN6 *)(remoteaddr->ai_addr));
213 else if (remote->sa_family == AF_INET)
215 peer.
Remote.
Addr4 = *((SOCKADDR_IN *)(remoteaddr->ai_addr));
232 OVERLAPPED ov = { 0 };
233 if (!DeviceIoControl(handle,
OVPN_IOCTL_NEW_PEER, &peer,
sizeof(peer), NULL, 0, NULL, &ov))
235 DWORD err = GetLastError();
236 if (err != ERROR_IO_PENDING)
238 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_NEW_PEER) failed");
249 struct sockaddr *localaddr,
struct sockaddr *remoteaddr,
250 struct in_addr *remote_in4,
struct in6_addr *remote_in6)
261 DWORD bytes_returned = 0;
263 0, NULL, 0, &bytes_returned, NULL))
273 int keepalive_interval,
int keepalive_timeout,
int mss)
275 msg(
D_DCO_DEBUG,
"%s: peer-id %d, keepalive %d/%d, mss %d", __func__,
276 peerid, keepalive_interval, keepalive_timeout, mss);
284 DWORD bytes_returned = 0;
286 sizeof(peer), NULL, 0, &bytes_returned, NULL))
297 const uint8_t *encrypt_key,
const uint8_t *encrypt_iv,
298 const uint8_t *decrypt_key,
const uint8_t *decrypt_iv,
299 const char *ciphername)
302 __func__, slot, keyid, peerid, ciphername);
304 const int nonce_len = 8;
308 ZeroMemory(&crypto_data,
sizeof(crypto_data));
310 crypto_data.
CipherAlg = dco_get_cipher(ciphername);
311 crypto_data.
KeyId = keyid;
312 crypto_data.
PeerId = peerid;
315 CopyMemory(crypto_data.
Encrypt.
Key, encrypt_key, key_len);
319 CopyMemory(crypto_data.
Decrypt.
Key, decrypt_key, key_len);
325 DWORD bytes_returned = 0;
328 sizeof(crypto_data), NULL, 0, &bytes_returned, NULL))
330 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_NEW_KEY) failed");
338 msg(
D_DCO,
"%s: peer-id %d, slot %d called but ignored", __func__, peerid,
349 DWORD bytes_returned = 0;
351 &bytes_returned, NULL))
353 msg(
M_ERR,
"DeviceIoControl(OVPN_IOCTL_SWAP_KEYS) failed");
363 HANDLE h = CreateFile(
"\\\\.\\ovpn-dco", GENERIC_READ | GENERIC_WRITE,
364 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
366 if (h != INVALID_HANDLE_VALUE)
372 DWORD err = GetLastError();
373 if (err == ERROR_ACCESS_DENIED)
382 msg(msglevel,
"Note: ovpn-dco-win driver is missing, disabling data channel offload.");
393 HANDLE h = CreateFile(
"\\\\.\\ovpn-dco", GENERIC_READ | GENERIC_WRITE,
394 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, NULL);
396 if (h == INVALID_HANDLE_VALUE)
401 DWORD bytes_returned = 0;
403 &version,
sizeof(version), &bytes_returned, NULL))
445 DWORD bytes_returned = 0;
447 &stats,
sizeof(stats), &bytes_returned, NULL))
478 NTSTATUS
status = BCryptOpenAlgorithmProvider(&h, L
"CHACHA20_POLY1305", NULL, 0);
479 if (BCRYPT_SUCCESS(
status))
481 BCryptCloseAlgorithmProvider(h, 0);
482 return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
486 return "AES-128-GCM:AES-256-GCM:AES-192-GCM";