mirror of
https://git.zx2c4.com/wireguard-nt
synced 2024-11-11 11:59:25 +00:00
f394d011c3
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
247 lines
11 KiB
C
247 lines
11 KiB
C
/* SPDX-License-Identifier: GPL-2.0
|
|
*
|
|
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
|
*/
|
|
|
|
#include "../driver/ioctl.h"
|
|
#include "wireguard.h"
|
|
#include "adapter.h"
|
|
#include "logger.h"
|
|
#include <Windows.h>
|
|
#include <stdlib.h>
|
|
|
|
static_assert(sizeof(WG_IOCTL_INTERFACE) == sizeof(WIREGUARD_INTERFACE), "Interface struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_INTERFACE, Flags) == offsetof(WIREGUARD_INTERFACE, Flags),
|
|
"Interface->Flags struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_INTERFACE, Flags) == RTL_FIELD_SIZE(WIREGUARD_INTERFACE, Flags),
|
|
"Interface->Flags struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_INTERFACE, ListenPort) == offsetof(WIREGUARD_INTERFACE, ListenPort),
|
|
"Interface->ListenPort struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_INTERFACE, ListenPort) == RTL_FIELD_SIZE(WIREGUARD_INTERFACE, ListenPort),
|
|
"Interface->ListenPort struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_INTERFACE, PrivateKey) == offsetof(WIREGUARD_INTERFACE, PrivateKey),
|
|
"Interface->PrivateKey struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_INTERFACE, PrivateKey) == RTL_FIELD_SIZE(WIREGUARD_INTERFACE, PrivateKey),
|
|
"Interface->PrivateKey struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_INTERFACE, PublicKey) == offsetof(WIREGUARD_INTERFACE, PublicKey),
|
|
"Interface->PublicKey struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_INTERFACE, PublicKey) == RTL_FIELD_SIZE(WIREGUARD_INTERFACE, PublicKey),
|
|
"Interface->PublicKey struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_INTERFACE, PeersCount) == offsetof(WIREGUARD_INTERFACE, PeersCount),
|
|
"Interface->PeersCount struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_INTERFACE, PeersCount) == RTL_FIELD_SIZE(WIREGUARD_INTERFACE, PeersCount),
|
|
"Interface->PeersCount struct mismatch");
|
|
static_assert(
|
|
WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY == WIREGUARD_INTERFACE_HAS_PUBLIC_KEY,
|
|
"INTERFACE_HAS_PUBLIC_KEY flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY == WIREGUARD_INTERFACE_HAS_PRIVATE_KEY,
|
|
"INTERFACE_HAS_PRIVATE_KEY flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_INTERFACE_HAS_LISTEN_PORT == WIREGUARD_INTERFACE_HAS_LISTEN_PORT,
|
|
"INTERFACE_HAS_LISTEN_PORT flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_INTERFACE_REPLACE_PEERS == WIREGUARD_INTERFACE_REPLACE_PEERS,
|
|
"INTERFACE_REPLACE_PEERS flag mismatch");
|
|
static_assert(sizeof(WG_IOCTL_PEER) == sizeof(WIREGUARD_PEER), "Peer struct mismatch");
|
|
static_assert(offsetof(WG_IOCTL_PEER, Flags) == offsetof(WIREGUARD_PEER, Flags), "Peer->Flags struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, Flags) == RTL_FIELD_SIZE(WIREGUARD_PEER, Flags),
|
|
"Peer->Flags struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, ProtocolVersion) == offsetof(WIREGUARD_PEER, Reserved),
|
|
"Peer->Reserved struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, ProtocolVersion) == RTL_FIELD_SIZE(WIREGUARD_PEER, Reserved),
|
|
"Peer->Reserved struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, PublicKey) == offsetof(WIREGUARD_PEER, PublicKey),
|
|
"Peer->PublicKey struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, PublicKey) == RTL_FIELD_SIZE(WIREGUARD_PEER, PublicKey),
|
|
"Peer->PublicKey struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, PresharedKey) == offsetof(WIREGUARD_PEER, PresharedKey),
|
|
"Peer->PresharedKey struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, PresharedKey) == RTL_FIELD_SIZE(WIREGUARD_PEER, PresharedKey),
|
|
"Peer->PresharedKey struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, PersistentKeepalive) == offsetof(WIREGUARD_PEER, PersistentKeepalive),
|
|
"Peer->PersistentKeepalive struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, PersistentKeepalive) == RTL_FIELD_SIZE(WIREGUARD_PEER, PersistentKeepalive),
|
|
"Peer->PersistentKeepalive struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, Endpoint) == offsetof(WIREGUARD_PEER, Endpoint),
|
|
"Peer->Endpoint struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, Endpoint) == RTL_FIELD_SIZE(WIREGUARD_PEER, Endpoint),
|
|
"Peer->Endpoint struct mismatch");
|
|
static_assert(offsetof(WG_IOCTL_PEER, TxBytes) == offsetof(WIREGUARD_PEER, TxBytes), "Peer->TxBytes struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, TxBytes) == RTL_FIELD_SIZE(WIREGUARD_PEER, TxBytes),
|
|
"Peer->TxBytes struct mismatch");
|
|
static_assert(offsetof(WG_IOCTL_PEER, RxBytes) == offsetof(WIREGUARD_PEER, RxBytes), "Peer->RxBytes struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, RxBytes) == RTL_FIELD_SIZE(WIREGUARD_PEER, RxBytes),
|
|
"Peer->RxBytes struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, LastHandshake) == offsetof(WIREGUARD_PEER, LastHandshake),
|
|
"Peer->LastHandshake struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, LastHandshake) == RTL_FIELD_SIZE(WIREGUARD_PEER, LastHandshake),
|
|
"Peer->LastHandshake struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_PEER, AllowedIPsCount) == offsetof(WIREGUARD_PEER, AllowedIPsCount),
|
|
"Peer->AllowedIPsCount struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_PEER, AllowedIPsCount) == RTL_FIELD_SIZE(WIREGUARD_PEER, AllowedIPsCount),
|
|
"Peer->AllowedIPsCount struct mismatch");
|
|
static_assert(WG_IOCTL_PEER_HAS_PUBLIC_KEY == WIREGUARD_PEER_HAS_PUBLIC_KEY, "PEER_HAS_PUBLIC_KEY flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_PEER_HAS_PRESHARED_KEY == WIREGUARD_PEER_HAS_PRESHARED_KEY,
|
|
"PEER_HAS_PRESHARED_KEY flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE == WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE,
|
|
"PEER_HAS_PERSISTENT_KEEPALIVE flag mismatch");
|
|
static_assert(WG_IOCTL_PEER_HAS_ENDPOINT == WIREGUARD_PEER_HAS_ENDPOINT, "PEER_HAS_ENDPOINT flag mismatch");
|
|
static_assert(
|
|
WG_IOCTL_PEER_REPLACE_ALLOWED_IPS == WIREGUARD_PEER_REPLACE_ALLOWED_IPS,
|
|
"PEER_REPLACE_ALLOWED_IPS flag mismatch");
|
|
static_assert(WG_IOCTL_PEER_REMOVE == WIREGUARD_PEER_REMOVE, "PEER_REMOVE flag mismatch");
|
|
static_assert(WG_IOCTL_PEER_UPDATE_ONLY == WIREGUARD_PEER_UPDATE_ONLY, "PEER_UPDATE_ONLY flag mismatch");
|
|
static_assert(sizeof(WG_IOCTL_ALLOWED_IP) == sizeof(WIREGUARD_ALLOWED_IP), "Allowed IP struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_ALLOWED_IP, AddressFamily) == offsetof(WIREGUARD_ALLOWED_IP, AddressFamily),
|
|
"AllowedIp->AddressFamily struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_ALLOWED_IP, AddressFamily) == RTL_FIELD_SIZE(WIREGUARD_ALLOWED_IP, AddressFamily),
|
|
"AllowedIp->AddressFamily struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_ALLOWED_IP, Cidr) == offsetof(WIREGUARD_ALLOWED_IP, Cidr),
|
|
"AllowedIp->cidr struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_ALLOWED_IP, Cidr) == RTL_FIELD_SIZE(WIREGUARD_ALLOWED_IP, Cidr),
|
|
"AllowedIp->cidr struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_ALLOWED_IP, Address.V4) == offsetof(WIREGUARD_ALLOWED_IP, Address.V4),
|
|
"AllowedIp->Address.V4 struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_ALLOWED_IP, Address.V4) == RTL_FIELD_SIZE(WIREGUARD_ALLOWED_IP, Address.V4),
|
|
"AllowedIp->Address.V4 struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_ALLOWED_IP, Address.V6) == offsetof(WIREGUARD_ALLOWED_IP, Address.V6),
|
|
"AllowedIp->Address.V6 struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_ALLOWED_IP, Address.V6) == RTL_FIELD_SIZE(WIREGUARD_ALLOWED_IP, Address.V6),
|
|
"AllowedIp->Address.V6 struct mismatch");
|
|
static_assert(
|
|
offsetof(WG_IOCTL_ALLOWED_IP, Address) == offsetof(WIREGUARD_ALLOWED_IP, Address),
|
|
"AllowedIp->Address struct mismatch");
|
|
static_assert(
|
|
RTL_FIELD_SIZE(WG_IOCTL_ALLOWED_IP, Address) == RTL_FIELD_SIZE(WIREGUARD_ALLOWED_IP, Address),
|
|
"AllowedIp->Address struct mismatch");
|
|
static_assert(sizeof(WG_IOCTL_ADAPTER_STATE) == sizeof(WIREGUARD_ADAPTER_STATE), "Adapter state mismatch");
|
|
static_assert(WG_IOCTL_ADAPTER_STATE_DOWN == WIREGUARD_ADAPTER_STATE_DOWN, "Adapter state down mismatch");
|
|
static_assert(WG_IOCTL_ADAPTER_STATE_UP == WIREGUARD_ADAPTER_STATE_UP, "Adapter state up mismatch");
|
|
|
|
WIREGUARD_SET_ADAPTER_STATE_FUNC WireGuardSetAdapterState;
|
|
_Use_decl_annotations_
|
|
BOOL WINAPI
|
|
WireGuardSetAdapterState(WIREGUARD_ADAPTER *Adapter, WIREGUARD_ADAPTER_STATE State)
|
|
{
|
|
switch (State)
|
|
{
|
|
case WIREGUARD_ADAPTER_STATE_UP:
|
|
case WIREGUARD_ADAPTER_STATE_DOWN:
|
|
break;
|
|
default:
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
HANDLE ControlFile = AdapterOpenDeviceObject(Adapter);
|
|
if (ControlFile == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
DWORD BytesReturned;
|
|
if (!DeviceIoControl(ControlFile, WG_IOCTL_SET_ADAPTER_STATE, &State, sizeof(State), NULL, 0, &BytesReturned, NULL))
|
|
{
|
|
DWORD LastError = GetLastError();
|
|
CloseHandle(ControlFile);
|
|
SetLastError(LastError);
|
|
return FALSE;
|
|
}
|
|
CloseHandle(ControlFile);
|
|
return TRUE;
|
|
}
|
|
|
|
WIREGUARD_GET_ADAPTER_STATE_FUNC WireGuardGetAdapterState;
|
|
_Use_decl_annotations_
|
|
BOOL WINAPI
|
|
WireGuardGetAdapterState(WIREGUARD_ADAPTER *Adapter, WIREGUARD_ADAPTER_STATE *State)
|
|
{
|
|
HANDLE ControlFile = AdapterOpenDeviceObject(Adapter);
|
|
if (ControlFile == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
DWORD BytesReturned;
|
|
WG_IOCTL_ADAPTER_STATE Op = WG_IOCTL_ADAPTER_STATE_QUERY;
|
|
if (!DeviceIoControl(
|
|
ControlFile, WG_IOCTL_SET_ADAPTER_STATE, &Op, sizeof(Op), State, sizeof(*State), &BytesReturned, NULL))
|
|
{
|
|
DWORD LastError = GetLastError();
|
|
CloseHandle(ControlFile);
|
|
SetLastError(LastError);
|
|
return FALSE;
|
|
}
|
|
CloseHandle(ControlFile);
|
|
return TRUE;
|
|
}
|
|
|
|
WIREGUARD_SET_CONFIGURATION_FUNC WireGuardSetConfiguration;
|
|
_Use_decl_annotations_
|
|
BOOL WINAPI
|
|
WireGuardSetConfiguration(WIREGUARD_ADAPTER *Adapter, const WIREGUARD_INTERFACE *Config, DWORD Bytes)
|
|
{
|
|
HANDLE ControlFile = AdapterOpenDeviceObject(Adapter);
|
|
if (ControlFile == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
if (!DeviceIoControl(ControlFile, WG_IOCTL_SET, NULL, 0, (VOID *)Config, Bytes, &Bytes, NULL))
|
|
{
|
|
DWORD LastError = GetLastError();
|
|
CloseHandle(ControlFile);
|
|
SetLastError(LastError);
|
|
return FALSE;
|
|
}
|
|
CloseHandle(ControlFile);
|
|
return TRUE;
|
|
}
|
|
|
|
WIREGUARD_GET_CONFIGURATION_FUNC WireGuardGetConfiguration;
|
|
_Use_decl_annotations_
|
|
BOOL WINAPI
|
|
WireGuardGetConfiguration(WIREGUARD_ADAPTER *Adapter, WIREGUARD_INTERFACE *Config, DWORD *Bytes)
|
|
{
|
|
HANDLE ControlFile = AdapterOpenDeviceObject(Adapter);
|
|
if (ControlFile == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
if (!DeviceIoControl(ControlFile, WG_IOCTL_GET, NULL, 0, Config, *Bytes, Bytes, NULL))
|
|
{
|
|
DWORD LastError = GetLastError();
|
|
CloseHandle(ControlFile);
|
|
SetLastError(LastError);
|
|
return FALSE;
|
|
}
|
|
CloseHandle(ControlFile);
|
|
return TRUE;
|
|
}
|