From 09e36b24160c57862cccf4883ae24735fae6f242 Mon Sep 17 00:00:00 2001
From: Mark Puha
Date: Fri, 13 Jun 2025 20:25:07 +0200
Subject: [PATCH] feat: special handshake continue
---
contrib/embeddable-wg-library/wireguard.c | 4 +-
contrib/peer-approver/approve.sh | 3 +-
contrib/peer-approver/notification-listener.c | 21 +-
src/config.c | 12 +-
src/containers.h | 4 +-
src/ipc-freebsd.h | 2 +-
src/ipc-linux.h | 45 +
src/ipc-uapi.h | 7 +
src/ipc-windows.h | 1139 ++++++++++-------
src/netlink.h | 1117 ++++++++--------
src/showconf.c | 3 +
src/uapi/linux/linux/wireguard.h | 8 +
src/uapi/openbsd/net/if_wg.h | 164 ++-
src/uapi/windows/wireguard.h | 143 ++-
14 files changed, 1552 insertions(+), 1120 deletions(-)
diff --git a/contrib/embeddable-wg-library/wireguard.c b/contrib/embeddable-wg-library/wireguard.c
index 0ba767b..12234e5 100644
--- a/contrib/embeddable-wg-library/wireguard.c
+++ b/contrib/embeddable-wg-library/wireguard.c
@@ -72,7 +72,8 @@ enum wgdevice_attribute {
enum wgpeer_flag {
WGPEER_F_REMOVE_ME = 1U << 0,
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
- WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3
+ WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
+ WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4
};
enum wgpeer_attribute {
WGPEER_A_UNSPEC,
@@ -87,6 +88,7 @@ enum wgpeer_attribute {
WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
+ WGPEER_A_SPECIAL_HANDSHAKE,
__WGPEER_A_LAST
};
diff --git a/contrib/peer-approver/approve.sh b/contrib/peer-approver/approve.sh
index b4ecfe9..e711a6c 100755
--- a/contrib/peer-approver/approve.sh
+++ b/contrib/peer-approver/approve.sh
@@ -5,6 +5,7 @@ INTERFACE_NAME=$2
PUBLIC_KEY=$3
ENDPOINT=$4
ADVANCED_SECURITY=$5
+SPECIAL_HANDSHAKE=$6
ACCOUNT_STR=`grep "${PUBLIC_KEY}" "${ACCOUNTS_FILE}"`
@@ -19,7 +20,7 @@ PSK=$(echo ${ACCOUNT[2]}|tr -d '"')
PSK_FILE=$(tempfile)
echo "${PSK}" > "${PSK_FILE}"
-awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}"
+awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}" special-handshake "${SPECIAL_HANDSHAKE}"
EXIT_CODE=$?
rm -f "{$PSK_FILE}"
diff --git a/contrib/peer-approver/notification-listener.c b/contrib/peer-approver/notification-listener.c
index a264673..0057e71 100644
--- a/contrib/peer-approver/notification-listener.c
+++ b/contrib/peer-approver/notification-listener.c
@@ -116,18 +116,19 @@ static int get_endpoint(struct nlattr *peer[], char **endpoint_ip)
return 0;
}
-static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security)
+static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security, bool special_handshake)
{
char** new_argv = malloc((cb_argc + 2) * sizeof *new_argv);
new_argv[0] = cb_argv[1];
- for (int i = 2; i < cb_argc - 3; i++) {
+ for (int i = 2; i < cb_argc - 4; i++) {
new_argv[i - 1] = cb_argv[i];
}
- new_argv[cb_argc - 4] = ifname;
- new_argv[cb_argc - 3] = pubkey;
- new_argv[cb_argc - 2] = endpoint_ip;
- new_argv[cb_argc - 1] = (advanced_security ? "on\0" : "off\0");
+ new_argv[cb_argc - 5] = ifname;
+ new_argv[cb_argc - 4] = pubkey;
+ new_argv[cb_argc - 3] = endpoint_ip;
+ new_argv[cb_argc - 2] = (advanced_security ? "on\0" : "off\0");
+ new_argv[cb_argc - 1] = (special_handshake ? "on\0" : "off\0");
new_argv[cb_argc] = NULL;
int child_pid = fork(), ret;
@@ -156,6 +157,7 @@ static int netlink_callback(struct nl_msg *msg, void *arg)
char *ifname, *pubkey, *endpoint_ip;
bool advanced_security = false;
+ bool special_handshake = false;
int cb_ret;
switch (gnlh->cmd) {
@@ -179,7 +181,10 @@ static int netlink_callback(struct nl_msg *msg, void *arg)
if (nla_get_flag(peer[WGPEER_A_ADVANCED_SECURITY])) {
advanced_security = true;
}
- if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security)) {
+ if (nla_get_flag(peer[WGPEER_A_SPECIAL_HANDSHAKE])) {
+ special_handshake = true;
+ }
+ if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security, special_handshake)) {
prerr("failed to execute callback script: %d!\n", cb_ret);
return NL_SKIP;
}
@@ -260,4 +265,4 @@ int main(int argc, char *argv[])
}
cleanup_and_exit(EXIT_FAILURE);
-}
\ No newline at end of file
+}
diff --git a/src/config.c b/src/config.c
index 6a60f77..176dc15 100644
--- a/src/config.c
+++ b/src/config.c
@@ -606,7 +606,7 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_string(&ctx->device->j3, "J3", value);
if (ret)
ctx->device->flags |= WGDEVICE_HAS_J3;
- } else if (key_match("ITIME")) {
+ } else if (key_match("Itime")) {
ret = parse_uint32(&ctx->device->itime, "Itime", value);
if (ret)
ctx->device->flags |= WGDEVICE_HAS_ITIME;
@@ -631,6 +631,10 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value);
if (ret)
ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
+ } else if (key_match("SpecialHandshake")) {
+ ret = parse_bool(&ctx->last_peer->special_handshake, "SpecialHandshake", value);
+ if (ret)
+ ctx->last_peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
} else
goto error;
} else
@@ -934,6 +938,12 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
argv += 2;
argc -= 2;
+ } else if (!strcmp(argv[0], "special-handshake") && argc >= 2 && peer) {
+ if (!parse_bool(&peer->special_handshake, "SpecialHandshake", argv[1]))
+ goto error;
+ peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
+ argv += 2;
+ argc -= 2;
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
goto error;
diff --git a/src/containers.h b/src/containers.h
index b8fabfc..376230e 100644
--- a/src/containers.h
+++ b/src/containers.h
@@ -53,7 +53,8 @@ enum
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4,
- WGPEER_HAS_ADVANCED_SECURITY = 1U << 5
+ WGPEER_HAS_ADVANCED_SECURITY = 1U << 5,
+ WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6
};
struct wgpeer
@@ -75,6 +76,7 @@ struct wgpeer
uint16_t persistent_keepalive_interval;
bool advanced_security;
+ bool special_handshake;
struct wgallowedip *first_allowedip, *last_allowedip;
struct wgpeer* next_peer;
diff --git a/src/ipc-freebsd.h b/src/ipc-freebsd.h
index 83f42fa..7fe3b12 100644
--- a/src/ipc-freebsd.h
+++ b/src/ipc-freebsd.h
@@ -251,7 +251,7 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
if (nvlist_exists_binary(nvl_device, "itime"))
{
number = nvlist_get_number(nvl_device, "itime");
- if (number <= INT32_MAX)
+ if (number <= UINT32_MAX)
{
dev->itime = number;
dev->flags |= WGDEVICE_HAS_ITIME;
diff --git a/src/ipc-linux.h b/src/ipc-linux.h
index 862bb18..d228c67 100644
--- a/src/ipc-linux.h
+++ b/src/ipc-linux.h
@@ -6,6 +6,7 @@
#include "containers.h"
#include "encoding.h"
#include "netlink.h"
+#include "uapi/linux/linux/wireguard.h"
#include
#include
#include
@@ -191,6 +192,25 @@ again:
mnl_attr_put_u32(nlh, WGDEVICE_A_H3, dev->underload_packet_magic_header);
if (dev->flags & WGDEVICE_HAS_H4)
mnl_attr_put_u32(nlh, WGDEVICE_A_H4, dev->transport_packet_magic_header);
+ if (dev->flags & WGDEVICE_HAS_I1)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_I1, dev->i1);
+ if (dev->flags & WGDEVICE_HAS_I2)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_I2, dev->i2);
+ if (dev->flags & WGDEVICE_HAS_I3)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_I3, dev->i3);
+ if (dev->flags & WGDEVICE_HAS_I4)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_I4, dev->i4);
+ if (dev->flags & WGDEVICE_HAS_I5)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_I5, dev->i5);
+ if (dev->flags & WGDEVICE_HAS_J1)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_J1, dev->j1);
+ if (dev->flags & WGDEVICE_HAS_J2)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_J2, dev->j2);
+ if (dev->flags & WGDEVICE_HAS_J3)
+ mnl_attr_put_strz(nlh, WGDEVICE_A_J3, dev->j3);
+ if (dev->flags & WGDEVICE_HAS_ITIME)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_ITIME, dev->itime);
+
if (dev->flags & WGDEVICE_HAS_FWMARK)
mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
if (dev->flags & WGDEVICE_REPLACE_PEERS)
@@ -269,6 +289,13 @@ again:
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
}
+ if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)
+ {
+ if (peer->special_handshake)
+ mnl_attr_put_check(
+ nlh, SOCKET_BUFFER_SIZE, WGPEER_A_SPECIAL_HANDSHAKE, 0, NULL);
+ flags |= WGPEER_F_HAS_SPECIAL_HANDSHAKE;
+ }
if (flags)
{
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
@@ -489,6 +516,13 @@ static int parse_peer(const struct nlattr* attr, void* data)
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
peer->advanced_security = false;
}
+ else if (
+ flags & WGPEER_F_HAS_SPECIAL_HANDSHAKE &&
+ !(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE))
+ {
+ peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
+ peer->special_handshake = false;
+ }
}
break;
case WGPEER_A_ADVANCED_SECURITY:
@@ -502,6 +536,17 @@ static int parse_peer(const struct nlattr* attr, void* data)
}
}
break;
+ case WGPEER_A_SPECIAL_HANDSHAKE:
+ if (!mnl_attr_validate(attr, MNL_TYPE_FLAG))
+ {
+ peer->special_handshake = true;
+
+ if (!(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE))
+ {
+ peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
+ }
+ }
+ break;
case WGPEER_A_ALLOWEDIPS:
return mnl_attr_parse_nested(attr, parse_allowedips, peer);
}
diff --git a/src/ipc-uapi.h b/src/ipc-uapi.h
index da45969..563243f 100644
--- a/src/ipc-uapi.h
+++ b/src/ipc-uapi.h
@@ -89,6 +89,8 @@ static int userspace_set_device(struct wgdevice* dev)
if (dev->flags & WGDEVICE_HAS_ITIME)
fprintf(f, "itime=%u\n", dev->itime);
+ printf("i1: %s\n", dev->i1);
+
for_each_wgpeer(dev, peer)
{
key_to_hex(hex, peer->public_key);
@@ -98,6 +100,11 @@ static int userspace_set_device(struct wgdevice* dev)
ret = -EINVAL;
goto out;
}
+ if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)
+ {
+ ret = -EINVAL;
+ goto out;
+ }
if (peer->flags & WGPEER_REMOVE_ME)
{
fprintf(f, "remove=true\n");
diff --git a/src/ipc-windows.h b/src/ipc-windows.h
index 7925cf0..7695446 100644
--- a/src/ipc-windows.h
+++ b/src/ipc-windows.h
@@ -4,529 +4,774 @@
*/
#include "containers.h"
-#include
-#include
#include
-#include
-#include
-#include
#include
-#include
+#include
#include
+#include
+#include
+#include
+#include
+#include
#define IPC_SUPPORTS_KERNEL_INTERFACE
-static bool have_cached_kernel_interfaces;
+static bool have_cached_kernel_interfaces;
static struct hashtable cached_kernel_interfaces;
static const DEVPROPKEY devpkey_name = DEVPKEY_WG_NAME;
-extern bool is_win7;
+extern bool is_win7;
-static int kernel_get_wireguard_interfaces(struct string_list *list)
+static int kernel_get_wireguard_interfaces(struct string_list* list)
{
- HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
- bool will_have_cached_kernel_interfaces = true;
+ HDEVINFO dev_info = SetupDiGetClassDevsExW(
+ &GUID_DEVCLASS_NET,
+ is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard",
+ NULL,
+ DIGCF_PRESENT,
+ NULL,
+ NULL,
+ NULL);
+ bool will_have_cached_kernel_interfaces = true;
- if (dev_info == INVALID_HANDLE_VALUE) {
- errno = EACCES;
- return -errno;
- }
+ if (dev_info == INVALID_HANDLE_VALUE)
+ {
+ errno = EACCES;
+ return -errno;
+ }
- for (DWORD i = 0;; ++i) {
- DWORD buf_len;
- WCHAR adapter_name[MAX_ADAPTER_NAME];
- SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) };
- DEVPROPTYPE prop_type;
- ULONG status, problem_code;
- char *interface_name;
- struct hashtable_entry *entry;
+ for (DWORD i = 0;; ++i)
+ {
+ DWORD buf_len;
+ WCHAR adapter_name[MAX_ADAPTER_NAME];
+ SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)};
+ DEVPROPTYPE prop_type;
+ ULONG status, problem_code;
+ char* interface_name;
+ struct hashtable_entry* entry;
- if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
- break;
- continue;
- }
+ if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data))
+ {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ break;
+ continue;
+ }
- if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
- &prop_type, (PBYTE)adapter_name,
- sizeof(adapter_name), NULL, 0) ||
- prop_type != DEVPROP_TYPE_STRING)
- continue;
- adapter_name[_countof(adapter_name) - 1] = L'0';
- if (!adapter_name[0])
- continue;
- buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL);
- if (!buf_len)
- continue;
- interface_name = malloc(buf_len);
- if (!interface_name)
- continue;
- buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
- if (!buf_len) {
- free(interface_name);
- continue;
- }
+ if (!SetupDiGetDevicePropertyW(
+ dev_info,
+ &dev_info_data,
+ &devpkey_name,
+ &prop_type,
+ (PBYTE)adapter_name,
+ sizeof(adapter_name),
+ NULL,
+ 0) ||
+ prop_type != DEVPROP_TYPE_STRING)
+ continue;
+ adapter_name[_countof(adapter_name) - 1] = L'0';
+ if (!adapter_name[0])
+ continue;
+ buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL);
+ if (!buf_len)
+ continue;
+ interface_name = malloc(buf_len);
+ if (!interface_name)
+ continue;
+ buf_len = WideCharToMultiByte(
+ CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
+ if (!buf_len)
+ {
+ free(interface_name);
+ continue;
+ }
- if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS &&
- (status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED))
- string_list_add(list, interface_name);
+ if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) ==
+ CR_SUCCESS &&
+ (status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED))
+ string_list_add(list, interface_name);
- entry = hashtable_find_or_insert_entry(&cached_kernel_interfaces, interface_name);
- free(interface_name);
- if (!entry)
- continue;
+ entry = hashtable_find_or_insert_entry(&cached_kernel_interfaces, interface_name);
+ free(interface_name);
+ if (!entry)
+ continue;
- if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- continue;
- entry->value = calloc(sizeof(WCHAR), buf_len);
- if (!entry->value)
- continue;
- if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, entry->value, buf_len, &buf_len)) {
- free(entry->value);
- entry->value = NULL;
- continue;
- }
+ if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ continue;
+ entry->value = calloc(sizeof(WCHAR), buf_len);
+ if (!entry->value)
+ continue;
+ if (!SetupDiGetDeviceInstanceIdW(
+ dev_info, &dev_info_data, entry->value, buf_len, &buf_len))
+ {
+ free(entry->value);
+ entry->value = NULL;
+ continue;
+ }
- will_have_cached_kernel_interfaces = true;
- }
- SetupDiDestroyDeviceInfoList(dev_info);
- have_cached_kernel_interfaces = will_have_cached_kernel_interfaces;
- return 0;
+ will_have_cached_kernel_interfaces = true;
+ }
+ SetupDiDestroyDeviceInfoList(dev_info);
+ have_cached_kernel_interfaces = will_have_cached_kernel_interfaces;
+ return 0;
}
-static HANDLE kernel_interface_handle(const char *iface)
+static HANDLE kernel_interface_handle(const char* iface)
{
- HDEVINFO dev_info;
- WCHAR *interfaces = NULL;
- HANDLE handle;
+ HDEVINFO dev_info;
+ WCHAR* interfaces = NULL;
+ HANDLE handle;
- if (have_cached_kernel_interfaces) {
- struct hashtable_entry *entry = hashtable_find_entry(&cached_kernel_interfaces, iface);
- if (entry) {
- DWORD buf_len;
- if (CM_Get_Device_Interface_List_SizeW(
- &buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
- goto err_hash;
- interfaces = calloc(buf_len, sizeof(*interfaces));
- if (!interfaces)
- goto err_hash;
- if (CM_Get_Device_Interface_ListW(
- (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value, interfaces, buf_len,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
- free(interfaces);
- interfaces = NULL;
- goto err_hash;
- }
- handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, 0, NULL);
- free(interfaces);
- if (handle == INVALID_HANDLE_VALUE)
- goto err_hash;
- return handle;
-err_hash:
- errno = EACCES;
- return NULL;
- }
- }
+ if (have_cached_kernel_interfaces)
+ {
+ struct hashtable_entry* entry =
+ hashtable_find_entry(&cached_kernel_interfaces, iface);
+ if (entry)
+ {
+ DWORD buf_len;
+ if (CM_Get_Device_Interface_List_SizeW(
+ &buf_len,
+ (GUID*)&GUID_DEVINTERFACE_NET,
+ (DEVINSTID_W)entry->value,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
+ goto err_hash;
+ interfaces = calloc(buf_len, sizeof(*interfaces));
+ if (!interfaces)
+ goto err_hash;
+ if (CM_Get_Device_Interface_ListW(
+ (GUID*)&GUID_DEVINTERFACE_NET,
+ (DEVINSTID_W)entry->value,
+ interfaces,
+ buf_len,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
+ !interfaces[0])
+ {
+ free(interfaces);
+ interfaces = NULL;
+ goto err_hash;
+ }
+ handle = CreateFileW(
+ interfaces,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ free(interfaces);
+ if (handle == INVALID_HANDLE_VALUE)
+ goto err_hash;
+ return handle;
+ err_hash:
+ errno = EACCES;
+ return NULL;
+ }
+ }
- dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
- if (dev_info == INVALID_HANDLE_VALUE)
- return NULL;
+ dev_info = SetupDiGetClassDevsExW(
+ &GUID_DEVCLASS_NET,
+ is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard",
+ NULL,
+ DIGCF_PRESENT,
+ NULL,
+ NULL,
+ NULL);
+ if (dev_info == INVALID_HANDLE_VALUE)
+ return NULL;
- for (DWORD i = 0; !interfaces; ++i) {
- bool found;
- DWORD buf_len;
- WCHAR *buf, adapter_name[MAX_ADAPTER_NAME];
- SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) };
- DEVPROPTYPE prop_type;
- char *interface_name;
+ for (DWORD i = 0; !interfaces; ++i)
+ {
+ bool found;
+ DWORD buf_len;
+ WCHAR * buf, adapter_name[MAX_ADAPTER_NAME];
+ SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)};
+ DEVPROPTYPE prop_type;
+ char* interface_name;
- if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
- break;
- continue;
- }
+ if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data))
+ {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ break;
+ continue;
+ }
- if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
- &prop_type, (PBYTE)adapter_name,
- sizeof(adapter_name), NULL, 0) ||
- prop_type != DEVPROP_TYPE_STRING)
- continue;
- adapter_name[_countof(adapter_name) - 1] = L'0';
- if (!adapter_name[0])
- continue;
- buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL);
- if (!buf_len)
- continue;
- interface_name = malloc(buf_len);
- if (!interface_name)
- continue;
- buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
- if (!buf_len) {
- free(interface_name);
- continue;
- }
- found = !strcmp(interface_name, iface);
- free(interface_name);
- if (!found)
- continue;
+ if (!SetupDiGetDevicePropertyW(
+ dev_info,
+ &dev_info_data,
+ &devpkey_name,
+ &prop_type,
+ (PBYTE)adapter_name,
+ sizeof(adapter_name),
+ NULL,
+ 0) ||
+ prop_type != DEVPROP_TYPE_STRING)
+ continue;
+ adapter_name[_countof(adapter_name) - 1] = L'0';
+ if (!adapter_name[0])
+ continue;
+ buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL);
+ if (!buf_len)
+ continue;
+ interface_name = malloc(buf_len);
+ if (!interface_name)
+ continue;
+ buf_len = WideCharToMultiByte(
+ CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
+ if (!buf_len)
+ {
+ free(interface_name);
+ continue;
+ }
+ found = !strcmp(interface_name, iface);
+ free(interface_name);
+ if (!found)
+ continue;
- if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- continue;
- buf = calloc(sizeof(*buf), buf_len);
- if (!buf)
- continue;
- if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, buf, buf_len, &buf_len))
- goto cleanup_instance_id;
- if (CM_Get_Device_Interface_List_SizeW(
- &buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
- goto cleanup_instance_id;
- interfaces = calloc(buf_len, sizeof(*interfaces));
- if (!interfaces)
- goto cleanup_instance_id;
- if (CM_Get_Device_Interface_ListW(
- (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf, interfaces, buf_len,
- CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
- free(interfaces);
- interfaces = NULL;
- goto cleanup_instance_id;
- }
-cleanup_instance_id:
- free(buf);
- }
- SetupDiDestroyDeviceInfoList(dev_info);
- if (!interfaces) {
- errno = ENOENT;
- return NULL;
- }
- handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, 0, NULL);
- free(interfaces);
- if (handle == INVALID_HANDLE_VALUE) {
- errno = EACCES;
- return NULL;
- }
- return handle;
+ if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ continue;
+ buf = calloc(sizeof(*buf), buf_len);
+ if (!buf)
+ continue;
+ if (!SetupDiGetDeviceInstanceIdW(
+ dev_info, &dev_info_data, buf, buf_len, &buf_len))
+ goto cleanup_instance_id;
+ if (CM_Get_Device_Interface_List_SizeW(
+ &buf_len,
+ (GUID*)&GUID_DEVINTERFACE_NET,
+ (DEVINSTID_W)buf,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
+ goto cleanup_instance_id;
+ interfaces = calloc(buf_len, sizeof(*interfaces));
+ if (!interfaces)
+ goto cleanup_instance_id;
+ if (CM_Get_Device_Interface_ListW(
+ (GUID*)&GUID_DEVINTERFACE_NET,
+ (DEVINSTID_W)buf,
+ interfaces,
+ buf_len,
+ CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
+ !interfaces[0])
+ {
+ free(interfaces);
+ interfaces = NULL;
+ goto cleanup_instance_id;
+ }
+ cleanup_instance_id:
+ free(buf);
+ }
+ SetupDiDestroyDeviceInfoList(dev_info);
+ if (!interfaces)
+ {
+ errno = ENOENT;
+ return NULL;
+ }
+ handle = CreateFileW(
+ interfaces,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ free(interfaces);
+ if (handle == INVALID_HANDLE_VALUE)
+ {
+ errno = EACCES;
+ return NULL;
+ }
+ return handle;
}
-static int kernel_get_device(struct wgdevice **device, const char *iface)
+static int kernel_get_device(struct wgdevice** device, const char* iface)
{
- WG_IOCTL_INTERFACE *wg_iface;
- WG_IOCTL_PEER *wg_peer;
- WG_IOCTL_ALLOWED_IP *wg_aip;
- void *buf = NULL;
- DWORD buf_len = 0;
- HANDLE handle = kernel_interface_handle(iface);
- struct wgdevice *dev;
- struct wgpeer *peer;
- struct wgallowedip *aip;
- int ret;
+ WG_IOCTL_INTERFACE* wg_iface;
+ WG_IOCTL_PEER* wg_peer;
+ WG_IOCTL_ALLOWED_IP* wg_aip;
+ void* buf = NULL;
+ DWORD buf_len = 0;
+ HANDLE handle = kernel_interface_handle(iface);
+ struct wgdevice* dev;
+ struct wgpeer* peer;
+ struct wgallowedip* aip;
+ int ret;
- *device = NULL;
+ *device = NULL;
- if (!handle)
- return -errno;
+ if (!handle)
+ return -errno;
- while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) {
- free(buf);
- if (GetLastError() != ERROR_MORE_DATA) {
- errno = EACCES;
- return -errno;
- }
- buf = malloc(buf_len);
- if (!buf)
- return -errno;
- }
+ while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL))
+ {
+ free(buf);
+ if (GetLastError() != ERROR_MORE_DATA)
+ {
+ errno = EACCES;
+ return -errno;
+ }
+ buf = malloc(buf_len);
+ if (!buf)
+ return -errno;
+ }
- wg_iface = (WG_IOCTL_INTERFACE *)buf;
- dev = calloc(1, sizeof(*dev));
- if (!dev)
- goto out;
- strncpy(dev->name, iface, sizeof(dev->name));
- dev->name[sizeof(dev->name) - 1] = '\0';
+ wg_iface = (WG_IOCTL_INTERFACE*)buf;
+ dev = calloc(1, sizeof(*dev));
+ if (!dev)
+ goto out;
+ strncpy(dev->name, iface, sizeof(dev->name));
+ dev->name[sizeof(dev->name) - 1] = '\0';
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT) {
- dev->listen_port = wg_iface->ListenPort;
- dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
- }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT)
+ {
+ dev->listen_port = wg_iface->ListenPort;
+ dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
+ }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY) {
- memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key));
- dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
- }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY)
+ {
+ memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key));
+ dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
+ }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY) {
- memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key));
- dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
- }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY)
+ {
+ memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key));
+ dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
+ }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC) {
- dev->junk_packet_count = wg_iface->JunkPacketCount;
- dev->flags |= WGDEVICE_HAS_JC;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN) {
- dev->junk_packet_min_size = wg_iface->JunkPacketMinSize;
- dev->flags |= WGDEVICE_HAS_JMIN;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX) {
- dev->junk_packet_max_size = wg_iface->JunkPacketMaxSize;
- dev->flags |= WGDEVICE_HAS_JMAX;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1) {
- dev->init_packet_junk_size = wg_iface->InitPacketJunkSize;
- dev->flags |= WGDEVICE_HAS_S1;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2) {
- dev->response_packet_junk_size = wg_iface->ResponsePacketJunkSize;
- dev->flags |= WGDEVICE_HAS_S2;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1) {
- dev->init_packet_magic_header = wg_iface->InitPacketMagicHeader;
- dev->flags |= WGDEVICE_HAS_H1;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2) {
- dev->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader;
- dev->flags |= WGDEVICE_HAS_H2;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3) {
- dev->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader;
- dev->flags |= WGDEVICE_HAS_H3;
- }
- if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4) {
- dev->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader;
- dev->flags |= WGDEVICE_HAS_H4;
- }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC)
+ {
+ dev->junk_packet_count = wg_iface->JunkPacketCount;
+ dev->flags |= WGDEVICE_HAS_JC;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN)
+ {
+ dev->junk_packet_min_size = wg_iface->JunkPacketMinSize;
+ dev->flags |= WGDEVICE_HAS_JMIN;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX)
+ {
+ dev->junk_packet_max_size = wg_iface->JunkPacketMaxSize;
+ dev->flags |= WGDEVICE_HAS_JMAX;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1)
+ {
+ dev->init_packet_junk_size = wg_iface->InitPacketJunkSize;
+ dev->flags |= WGDEVICE_HAS_S1;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2)
+ {
+ dev->response_packet_junk_size = wg_iface->ResponsePacketJunkSize;
+ dev->flags |= WGDEVICE_HAS_S2;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1)
+ {
+ dev->init_packet_magic_header = wg_iface->InitPacketMagicHeader;
+ dev->flags |= WGDEVICE_HAS_H1;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2)
+ {
+ dev->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader;
+ dev->flags |= WGDEVICE_HAS_H2;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3)
+ {
+ dev->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader;
+ dev->flags |= WGDEVICE_HAS_H3;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4)
+ {
+ dev->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader;
+ dev->flags |= WGDEVICE_HAS_H4;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_I1)
+ {
+ const size_t i1_size = strlen((char*)wg_iface->I1) + 1;
+ dev->i1 = (char*)malloc(i1_size);
+ memcpy(dev->i1, wg_iface->I1, i1_size);
+ dev->flags |= WGDEVICE_HAS_I1;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_I2)
+ {
+ const size_t i2_size = strlen((char*)wg_iface->I2) + 1;
+ dev->i2 = (char*)malloc(i2_size);
+ memcpy(dev->i2, wg_iface->I2, i2_size);
+ dev->flags |= WGDEVICE_HAS_I2;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_I3)
+ {
+ const size_t i3_size = strlen((char*)wg_iface->I3) + 1;
+ dev->i3 = (char*)malloc(i3_size);
+ memcpy(dev->i3, wg_iface->I3, i3_size);
+ dev->flags |= WGDEVICE_HAS_I3;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_I4)
+ {
+ const size_t i4_size = strlen((char*)wg_iface->I4) + 1;
+ dev->i4 = (char*)malloc(i4_size);
+ memcpy(dev->i4, wg_iface->I4, i4_size);
+ dev->flags |= WGDEVICE_HAS_I4;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_I5)
+ {
+ const size_t i5_size = strlen((char*)wg_iface->I5) + 1;
+ dev->i5 = (char*)malloc(i5_size);
+ memcpy(dev->i5, wg_iface->I5, i5_size);
+ dev->flags |= WGDEVICE_HAS_I5;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_J1)
+ {
+ const size_t j1_size = strlen((char*)wg_iface->J1) + 1;
+ dev->j1 = (char*)malloc(j1_size);
+ memcpy(dev->j1, wg_iface->J1, j1_size);
+ dev->flags |= WGDEVICE_HAS_J1;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_J2)
+ {
+ const size_t j2_size = strlen((char*)wg_iface->J2) + 1;
+ dev->j2 = (char*)malloc(j2_size);
+ memcpy(dev->j2, wg_iface->J2, j2_size);
+ dev->flags |= WGDEVICE_HAS_J2;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_J3)
+ {
+ const size_t j3_size = strlen((char*)wg_iface->J3) + 1;
+ dev->j3 = (char*)malloc(j3_size);
+ memcpy(dev->j3, wg_iface->J3, j3_size);
+ dev->flags |= WGDEVICE_HAS_J3;
+ }
+ if (wg_iface->Flags & WG_IOCTL_INTERFACE_ITIME)
+ {
+ dev->itime = wg_iface->Itime;
+ dev->flags |= WGDEVICE_HAS_ITIME;
+ }
- wg_peer = buf + sizeof(WG_IOCTL_INTERFACE);
- for (ULONG i = 0; i < wg_iface->PeersCount; ++i) {
- peer = calloc(1, sizeof(*peer));
- if (!peer)
- goto out;
+ wg_peer = buf + sizeof(WG_IOCTL_INTERFACE);
+ for (ULONG i = 0; i < wg_iface->PeersCount; ++i)
+ {
+ peer = calloc(1, sizeof(*peer));
+ if (!peer)
+ goto out;
- if (dev->first_peer == NULL)
- dev->first_peer = peer;
- else
- dev->last_peer->next_peer = peer;
- dev->last_peer = peer;
+ if (dev->first_peer == NULL)
+ dev->first_peer = peer;
+ else
+ dev->last_peer->next_peer = peer;
+ dev->last_peer = peer;
- if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY) {
- memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key));
- peer->flags |= WGPEER_HAS_PUBLIC_KEY;
- }
+ if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY)
+ {
+ memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key));
+ peer->flags |= WGPEER_HAS_PUBLIC_KEY;
+ }
- if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY) {
- memcpy(peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
- if (!key_is_zero(peer->preshared_key))
- peer->flags |= WGPEER_HAS_PRESHARED_KEY;
- }
+ if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY)
+ {
+ memcpy(
+ peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
+ if (!key_is_zero(peer->preshared_key))
+ peer->flags |= WGPEER_HAS_PRESHARED_KEY;
+ }
- if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE) {
- peer->persistent_keepalive_interval = wg_peer->PersistentKeepalive;
- peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
- }
+ if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE)
+ {
+ peer->persistent_keepalive_interval = wg_peer->PersistentKeepalive;
+ peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
+ }
- if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT) {
- if (wg_peer->Endpoint.si_family == AF_INET)
- peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4;
- else if (wg_peer->Endpoint.si_family == AF_INET6)
- peer->endpoint.addr6 = wg_peer->Endpoint.Ipv6;
- }
+ if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT)
+ {
+ if (wg_peer->Endpoint.si_family == AF_INET)
+ peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4;
+ else if (wg_peer->Endpoint.si_family == AF_INET6)
+ peer->endpoint.addr6 = wg_peer->Endpoint.Ipv6;
+ }
- peer->rx_bytes = wg_peer->RxBytes;
- peer->tx_bytes = wg_peer->TxBytes;
+ peer->rx_bytes = wg_peer->RxBytes;
+ peer->tx_bytes = wg_peer->TxBytes;
- if (wg_peer->LastHandshake) {
- peer->last_handshake_time.tv_sec = wg_peer->LastHandshake / 10000000 - 11644473600LL;
- peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100;
- }
+ if (wg_peer->LastHandshake)
+ {
+ peer->last_handshake_time.tv_sec =
+ wg_peer->LastHandshake / 10000000 - 11644473600LL;
+ peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100;
+ }
- wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
- for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j) {
- aip = calloc(1, sizeof(*aip));
- if (!aip)
- goto out;
+ wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
+ for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j)
+ {
+ aip = calloc(1, sizeof(*aip));
+ if (!aip)
+ goto out;
- if (peer->first_allowedip == NULL)
- peer->first_allowedip = aip;
- else
- peer->last_allowedip->next_allowedip = aip;
- peer->last_allowedip = aip;
+ if (peer->first_allowedip == NULL)
+ peer->first_allowedip = aip;
+ else
+ peer->last_allowedip->next_allowedip = aip;
+ peer->last_allowedip = aip;
- aip->family = wg_aip->AddressFamily;
- if (wg_aip->AddressFamily == AF_INET) {
- memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4));
- aip->cidr = wg_aip->Cidr;
- } else if (wg_aip->AddressFamily == AF_INET6) {
- memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6));
- aip->cidr = wg_aip->Cidr;
- }
- ++wg_aip;
- }
- wg_peer = (WG_IOCTL_PEER *)wg_aip;
- }
- *device = dev;
- errno = 0;
+ aip->family = wg_aip->AddressFamily;
+ if (wg_aip->AddressFamily == AF_INET)
+ {
+ memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4));
+ aip->cidr = wg_aip->Cidr;
+ }
+ else if (wg_aip->AddressFamily == AF_INET6)
+ {
+ memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6));
+ aip->cidr = wg_aip->Cidr;
+ }
+ ++wg_aip;
+ }
+ wg_peer = (WG_IOCTL_PEER*)wg_aip;
+ }
+ *device = dev;
+ errno = 0;
out:
- ret = -errno;
- free(buf);
- CloseHandle(handle);
- return ret;
+ ret = -errno;
+ free(buf);
+ CloseHandle(handle);
+ return ret;
}
-static int kernel_set_device(struct wgdevice *dev)
+static int kernel_set_device(struct wgdevice* dev)
{
- WG_IOCTL_INTERFACE *wg_iface = NULL;
- WG_IOCTL_PEER *wg_peer;
- WG_IOCTL_ALLOWED_IP *wg_aip;
- DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
- HANDLE handle = kernel_interface_handle(dev->name);
- struct wgpeer *peer;
- struct wgallowedip *aip;
- size_t peer_count, aip_count;
- int ret = 0;
+ WG_IOCTL_INTERFACE* wg_iface = NULL;
+ WG_IOCTL_PEER* wg_peer;
+ WG_IOCTL_ALLOWED_IP* wg_aip;
+ DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
+ HANDLE handle = kernel_interface_handle(dev->name);
+ struct wgpeer* peer;
+ struct wgallowedip* aip;
+ size_t peer_count, aip_count;
+ int ret = 0;
- if (!handle)
- return -errno;
+ if (!handle)
+ return -errno;
- for_each_wgpeer(dev, peer) {
- if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) {
- errno = EOVERFLOW;
- goto out;
- }
- buf_len += sizeof(WG_IOCTL_PEER);
- for_each_wgallowedip(peer, aip) {
- if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) {
- errno = EOVERFLOW;
- goto out;
- }
- buf_len += sizeof(WG_IOCTL_ALLOWED_IP);
- }
- }
- wg_iface = calloc(1, buf_len);
- if (!wg_iface)
- goto out;
+ for_each_wgpeer(dev, peer)
+ {
+ if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER))
+ {
+ errno = EOVERFLOW;
+ goto out;
+ }
+ buf_len += sizeof(WG_IOCTL_PEER);
+ for_each_wgallowedip(peer, aip)
+ {
+ if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP))
+ {
+ errno = EOVERFLOW;
+ goto out;
+ }
+ buf_len += sizeof(WG_IOCTL_ALLOWED_IP);
+ }
+ }
+ wg_iface = calloc(1, buf_len);
+ if (!wg_iface)
+ goto out;
- if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
- memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
- wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY;
- }
+ if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
+ {
+ memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY;
+ }
- if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) {
- wg_iface->ListenPort = dev->listen_port;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT;
- }
+ if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
+ {
+ wg_iface->ListenPort = dev->listen_port;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT;
+ }
- if (dev->flags & WGDEVICE_REPLACE_PEERS)
- wg_iface->Flags |= WG_IOCTL_INTERFACE_REPLACE_PEERS;
+ if (dev->flags & WGDEVICE_REPLACE_PEERS)
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_REPLACE_PEERS;
- if (dev->flags & WGDEVICE_HAS_JC) {
- wg_iface->JunkPacketCount = dev->junk_packet_count;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_JC;
- }
+ if (dev->flags & WGDEVICE_HAS_JC)
+ {
+ wg_iface->JunkPacketCount = dev->junk_packet_count;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_JC;
+ }
- if (dev->flags & WGDEVICE_HAS_JMIN) {
- wg_iface->JunkPacketMinSize = dev->junk_packet_min_size;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN;
- }
+ if (dev->flags & WGDEVICE_HAS_JMIN)
+ {
+ wg_iface->JunkPacketMinSize = dev->junk_packet_min_size;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN;
+ }
- if (dev->flags & WGDEVICE_HAS_JMAX) {
- wg_iface->JunkPacketMaxSize = dev->junk_packet_max_size;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX;
- }
+ if (dev->flags & WGDEVICE_HAS_JMAX)
+ {
+ wg_iface->JunkPacketMaxSize = dev->junk_packet_max_size;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX;
+ }
- if (dev->flags & WGDEVICE_HAS_S1) {
- wg_iface->InitPacketJunkSize = dev->init_packet_junk_size;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_S1;
- }
+ if (dev->flags & WGDEVICE_HAS_S1)
+ {
+ wg_iface->InitPacketJunkSize = dev->init_packet_junk_size;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_S1;
+ }
- if (dev->flags & WGDEVICE_HAS_S2) {
- wg_iface->ResponsePacketJunkSize = dev->response_packet_junk_size;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_S2;
- }
+ if (dev->flags & WGDEVICE_HAS_S2)
+ {
+ wg_iface->ResponsePacketJunkSize = dev->response_packet_junk_size;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_S2;
+ }
- if (dev->flags & WGDEVICE_HAS_H1) {
- wg_iface->InitPacketMagicHeader = dev->init_packet_magic_header;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_H1;
- }
+ if (dev->flags & WGDEVICE_HAS_H1)
+ {
+ wg_iface->InitPacketMagicHeader = dev->init_packet_magic_header;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_H1;
+ }
- if (dev->flags & WGDEVICE_HAS_H2) {
- wg_iface->ResponsePacketMagicHeader = dev->response_packet_magic_header;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_H2;
- }
+ if (dev->flags & WGDEVICE_HAS_H2)
+ {
+ wg_iface->ResponsePacketMagicHeader = dev->response_packet_magic_header;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_H2;
+ }
- if (dev->flags & WGDEVICE_HAS_H3) {
- wg_iface->UnderloadPacketMagicHeader = dev->underload_packet_magic_header;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_H3;
- }
+ if (dev->flags & WGDEVICE_HAS_H3)
+ {
+ wg_iface->UnderloadPacketMagicHeader = dev->underload_packet_magic_header;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_H3;
+ }
- if (dev->flags & WGDEVICE_HAS_H4) {
- wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header;
- wg_iface->Flags |= WG_IOCTL_INTERFACE_H4;
- }
+ if (dev->flags & WGDEVICE_HAS_H4)
+ {
+ wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header;
+ wg_iface->Flags |= WG_IOCTL_INTERFACE_H4;
+ }
+ if (dev->flags & WG_DEVICE_HAS_I1)
+ {
+ const size_t i1_size = strlen(dev->i1);
+ wg_iface->I1 = (UCHAR*)malloc(i1_size + 1);
+ memcpy(wg_iface->I1, dev->i1, i1_size);
+ dev->flags |= WG_IOCTL_INTERFACE_I1;
+ }
+ if (dev->flags & WG_DEVICE_HAS_I2)
+ {
+ const size_t i2_size = strlen(dev->i2);
+ wg_iface->I2 = (UCHAR*)malloc(i2_size + 1);
+ memcpy(wg_iface->I2, dev->i2, i2_size);
+ dev->flags |= WG_IOCTL_INTERFACE_I2;
+ }
+ if (dev->flags & WG_DEVICE_HAS_I3)
+ {
+ const size_t i3_size = strlen(dev->i3);
+ wg_iface->I3 = (UCHAR*)malloc(i3_size + 1);
+ memcpy(wg_iface->I3, dev->i3, i3_size);
+ dev->flags |= WG_IOCTL_INTERFACE_I3;
+ }
+ if (dev->flags & WG_DEVICE_HAS_I4)
+ {
+ const size_t i4_size = strlen(dev->i4);
+ wg_iface->I4 = (UCHAR*)malloc(i4_size + 1);
+ memcpy(wg_iface->I4, dev->i4, i4_size);
+ dev->flags |= WG_IOCTL_INTERFACE_I4;
+ }
+ if (dev->flags & WG_DEVICE_HAS_I5)
+ {
+ const size_t i5_size = strlen(dev->i5);
+ wg_iface->I5 = (UCHAR*)malloc(i5_size + 1);
+ memcpy(wg_iface->I5, dev->i5, i5_size);
+ dev->flags |= WG_IOCTL_INTERFACE_I5;
+ }
+ if (dev->flags & WG_DEVICE_HAS_J1)
+ {
+ const size_t j1_size = strlen(dev->j1);
+ wg_iface->J1 = (UCHAR*)malloc(j1_size + 1);
+ memcpy(wg_iface->J1, dev->j1, j1_size);
+ dev->flags |= WG_IOCTL_INTERFACE_J1;
+ }
+ if (dev->flags & WG_DEVICE_HAS_J2)
+ {
+ const size_t j2_size = strlen(dev->j2);
+ wg_iface->J2 = (UCHAR*)malloc(j2_size + 1);
+ memcpy(wg_iface->J2, dev->j2, j2_size);
+ dev->flags |= WG_IOCTL_INTERFACE_J2;
+ }
+ if (dev->flags & WG_DEVICE_HAS_J3)
+ {
+ const size_t j3_size = strlen(dev->j3);
+ wg_iface->J3 = (UCHAR*)malloc(j3_size + 1);
+ memcpy(wg_iface->J3, dev->j3, j3_size);
+ dev->flags |= WG_IOCTL_INTERFACE_J3;
+ }
+ if (dev->flags & WG_DEVICE_HAS_ITIME)
+ {
+ wg_iface->Itime = dev->Itime;
+ wg_iface->flags |= WG_IOCTL_INTERFACE_HAS_ITIME;
+ }
- peer_count = 0;
- wg_peer = (void *)wg_iface + sizeof(WG_IOCTL_INTERFACE);
- for_each_wgpeer(dev, peer) {
- wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY;
- memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey));
+ peer_count = 0;
+ wg_peer = (void*)wg_iface + sizeof(WG_IOCTL_INTERFACE);
+ for_each_wgpeer(dev, peer)
+ {
+ wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY;
+ memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey));
- if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
- memcpy(wg_peer->PresharedKey, peer->preshared_key, sizeof(wg_peer->PresharedKey));
- wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY;
- }
+ if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
+ {
+ memcpy(
+ wg_peer->PresharedKey,
+ peer->preshared_key,
+ sizeof(wg_peer->PresharedKey));
+ wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY;
+ }
- if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
- wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval;
- wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE;
- }
+ if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
+ {
+ wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval;
+ wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE;
+ }
- if (peer->endpoint.addr.sa_family == AF_INET) {
- wg_peer->Endpoint.Ipv4 = peer->endpoint.addr4;
- wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
- } else if (peer->endpoint.addr.sa_family == AF_INET6) {
- wg_peer->Endpoint.Ipv6 = peer->endpoint.addr6;
- wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
- }
+ if (peer->endpoint.addr.sa_family == AF_INET)
+ {
+ wg_peer->Endpoint.Ipv4 = peer->endpoint.addr4;
+ wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
+ }
+ else if (peer->endpoint.addr.sa_family == AF_INET6)
+ {
+ wg_peer->Endpoint.Ipv6 = peer->endpoint.addr6;
+ wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
+ }
- if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
- wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS;
+ if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
+ wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS;
- if (peer->flags & WGPEER_REMOVE_ME)
- wg_peer->Flags |= WG_IOCTL_PEER_REMOVE;
+ if (peer->flags & WGPEER_REMOVE_ME)
+ wg_peer->Flags |= WG_IOCTL_PEER_REMOVE;
- aip_count = 0;
- wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
- for_each_wgallowedip(peer, aip) {
- wg_aip->AddressFamily = aip->family;
- wg_aip->Cidr = aip->cidr;
+ aip_count = 0;
+ wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
+ for_each_wgallowedip(peer, aip)
+ {
+ wg_aip->AddressFamily = aip->family;
+ wg_aip->Cidr = aip->cidr;
- if (aip->family == AF_INET)
- wg_aip->Address.V4 = aip->ip4;
- else if (aip->family == AF_INET6)
- wg_aip->Address.V6 = aip->ip6;
- else
- continue;
- ++aip_count;
- ++wg_aip;
- }
- wg_peer->AllowedIPsCount = aip_count;
- ++peer_count;
- wg_peer = (WG_IOCTL_PEER *)wg_aip;
- }
- wg_iface->PeersCount = peer_count;
+ if (aip->family == AF_INET)
+ wg_aip->Address.V4 = aip->ip4;
+ else if (aip->family == AF_INET6)
+ wg_aip->Address.V6 = aip->ip6;
+ else
+ continue;
+ ++aip_count;
+ ++wg_aip;
+ }
+ wg_peer->AllowedIPsCount = aip_count;
+ ++peer_count;
+ wg_peer = (WG_IOCTL_PEER*)wg_aip;
+ }
+ wg_iface->PeersCount = peer_count;
- if (!DeviceIoControl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) {
- errno = EACCES;
- goto out;
- }
- errno = 0;
+ if (!DeviceIoControl(
+ handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL))
+ {
+ errno = EACCES;
+ goto out;
+ }
+ errno = 0;
out:
- ret = -errno;
- free(wg_iface);
- CloseHandle(handle);
- return ret;
+ ret = -errno;
+ free(wg_iface);
+ CloseHandle(handle);
+ return ret;
}
diff --git a/src/netlink.h b/src/netlink.h
index f9729ee..08f1382 100644
--- a/src/netlink.h
+++ b/src/netlink.h
@@ -6,792 +6,853 @@
/* This is a minimized version of libmnl meant to be #include'd */
-#include
-#include
-#include
-#include
-#include
-#include
#include
-#include
-#include
-#include
-#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#define MNL_SOCKET_AUTOPID 0
#define MNL_ALIGNTO 4
-#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
+#define MNL_ALIGN(len) (((len) + MNL_ALIGNTO - 1) & ~(MNL_ALIGNTO - 1))
#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
-enum mnl_attr_data_type {
- MNL_TYPE_UNSPEC,
- MNL_TYPE_U8,
- MNL_TYPE_U16,
- MNL_TYPE_U32,
- MNL_TYPE_U64,
- MNL_TYPE_STRING,
- MNL_TYPE_FLAG,
- MNL_TYPE_MSECS,
- MNL_TYPE_NESTED,
- MNL_TYPE_NESTED_COMPAT,
- MNL_TYPE_NUL_STRING,
- MNL_TYPE_BINARY,
- MNL_TYPE_MAX,
+enum mnl_attr_data_type
+{
+ MNL_TYPE_UNSPEC,
+ MNL_TYPE_U8,
+ MNL_TYPE_U16,
+ MNL_TYPE_U32,
+ MNL_TYPE_U64,
+ MNL_TYPE_STRING,
+ MNL_TYPE_FLAG,
+ MNL_TYPE_MSECS,
+ MNL_TYPE_NESTED,
+ MNL_TYPE_NESTED_COMPAT,
+ MNL_TYPE_NUL_STRING,
+ MNL_TYPE_BINARY,
+ MNL_TYPE_MAX,
};
-#define mnl_attr_for_each(attr, nlh, offset) \
- for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
- mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
- (attr) = mnl_attr_next(attr))
+#define mnl_attr_for_each(attr, nlh, offset) \
+ for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
+ mnl_attr_ok((attr), (char*)mnl_nlmsg_get_payload_tail(nlh) - (char*)(attr)); \
+ (attr) = mnl_attr_next(attr))
-#define mnl_attr_for_each_nested(attr, nest) \
- for ((attr) = mnl_attr_get_payload(nest); \
- mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
- (attr) = mnl_attr_next(attr))
+#define mnl_attr_for_each_nested(attr, nest) \
+ for ((attr) = mnl_attr_get_payload(nest); mnl_attr_ok( \
+ (attr), \
+ (char*)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - \
+ (char*)(attr)); \
+ (attr) = mnl_attr_next(attr))
-#define mnl_attr_for_each_payload(payload, payload_size) \
- for ((attr) = (payload); \
- mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
- (attr) = mnl_attr_next(attr))
+#define mnl_attr_for_each_payload(payload, payload_size) \
+ for ((attr) = (payload); \
+ mnl_attr_ok((attr), (char*)(payload) + payload_size - (char*)(attr)); \
+ (attr) = mnl_attr_next(attr))
-#define MNL_CB_ERROR -1
-#define MNL_CB_STOP 0
-#define MNL_CB_OK 1
+#define MNL_CB_ERROR -1
+#define MNL_CB_STOP 0
+#define MNL_CB_OK 1
-typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
-typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
+typedef int (*mnl_attr_cb_t)(const struct nlattr* attr, void* data);
+typedef int (*mnl_cb_t)(const struct nlmsghdr* nlh, void* data);
#ifndef MNL_ARRAY_SIZE
-#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+#define MNL_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
static size_t mnl_ideal_socket_buffer_size(void)
{
- static size_t size = 0;
+ static size_t size = 0;
- if (size)
- return size;
- size = (size_t)sysconf(_SC_PAGESIZE);
- if (size > 8192)
- size = 8192;
- return size;
+ if (size)
+ return size;
+ size = (size_t)sysconf(_SC_PAGESIZE);
+ if (size > 8192)
+ size = 8192;
+ return size;
}
-static size_t mnl_nlmsg_size(size_t len)
+static size_t mnl_nlmsg_size(size_t len) { return len + MNL_NLMSG_HDRLEN; }
+
+static struct nlmsghdr* mnl_nlmsg_put_header(void* buf)
{
- return len + MNL_NLMSG_HDRLEN;
+ int len = MNL_ALIGN(sizeof(struct nlmsghdr));
+ struct nlmsghdr* nlh = buf;
+
+ memset(buf, 0, len);
+ nlh->nlmsg_len = len;
+ return nlh;
}
-static struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
+static void* mnl_nlmsg_put_extra_header(struct nlmsghdr* nlh, size_t size)
{
- int len = MNL_ALIGN(sizeof(struct nlmsghdr));
- struct nlmsghdr *nlh = buf;
-
- memset(buf, 0, len);
- nlh->nlmsg_len = len;
- return nlh;
+ char* ptr = (char*)nlh + nlh->nlmsg_len;
+ size_t len = MNL_ALIGN(size);
+ nlh->nlmsg_len += len;
+ memset(ptr, 0, len);
+ return ptr;
}
-static void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
+static void* mnl_nlmsg_get_payload(const struct nlmsghdr* nlh)
{
- char *ptr = (char *)nlh + nlh->nlmsg_len;
- size_t len = MNL_ALIGN(size);
- nlh->nlmsg_len += len;
- memset(ptr, 0, len);
- return ptr;
+ return (void*)nlh + MNL_NLMSG_HDRLEN;
}
-static void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
+static void* mnl_nlmsg_get_payload_offset(const struct nlmsghdr* nlh, size_t offset)
{
- return (void *)nlh + MNL_NLMSG_HDRLEN;
+ return (void*)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
}
-static void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
+static bool mnl_nlmsg_ok(const struct nlmsghdr* nlh, int len)
{
- return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
+ return len >= (int)sizeof(struct nlmsghdr) &&
+ nlh->nlmsg_len >= sizeof(struct nlmsghdr) && (int)nlh->nlmsg_len <= len;
}
-static bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
+static struct nlmsghdr* mnl_nlmsg_next(const struct nlmsghdr* nlh, int* len)
{
- return len >= (int)sizeof(struct nlmsghdr) &&
- nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
- (int)nlh->nlmsg_len <= len;
+ *len -= MNL_ALIGN(nlh->nlmsg_len);
+ return (struct nlmsghdr*)((void*)nlh + MNL_ALIGN(nlh->nlmsg_len));
}
-static struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
+static void* mnl_nlmsg_get_payload_tail(const struct nlmsghdr* nlh)
{
- *len -= MNL_ALIGN(nlh->nlmsg_len);
- return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
+ return (void*)nlh + MNL_ALIGN(nlh->nlmsg_len);
}
-static void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
+static bool mnl_nlmsg_seq_ok(const struct nlmsghdr* nlh, unsigned int seq)
{
- return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
+ return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
}
-static bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
+static bool mnl_nlmsg_portid_ok(const struct nlmsghdr* nlh, unsigned int portid)
{
- return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
+ return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
}
-static bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
+static uint16_t mnl_attr_get_type(const struct nlattr* attr)
{
- return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
+ return attr->nla_type & NLA_TYPE_MASK;
}
-static uint16_t mnl_attr_get_type(const struct nlattr *attr)
+static uint16_t mnl_attr_get_payload_len(const struct nlattr* attr)
{
- return attr->nla_type & NLA_TYPE_MASK;
+ return attr->nla_len - MNL_ATTR_HDRLEN;
}
-static uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
+static void* mnl_attr_get_payload(const struct nlattr* attr)
{
- return attr->nla_len - MNL_ATTR_HDRLEN;
+ return (void*)attr + MNL_ATTR_HDRLEN;
}
-static void *mnl_attr_get_payload(const struct nlattr *attr)
+static bool mnl_attr_ok(const struct nlattr* attr, int len)
{
- return (void *)attr + MNL_ATTR_HDRLEN;
+ return len >= (int)sizeof(struct nlattr) && attr->nla_len >= sizeof(struct nlattr) &&
+ (int)attr->nla_len <= len;
}
-static bool mnl_attr_ok(const struct nlattr *attr, int len)
+static struct nlattr* mnl_attr_next(const struct nlattr* attr)
{
- return len >= (int)sizeof(struct nlattr) &&
- attr->nla_len >= sizeof(struct nlattr) &&
- (int)attr->nla_len <= len;
+ return (struct nlattr*)((void*)attr + MNL_ALIGN(attr->nla_len));
}
-static struct nlattr *mnl_attr_next(const struct nlattr *attr)
+static int mnl_attr_type_valid(const struct nlattr* attr, uint16_t max)
{
- return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
+ if (mnl_attr_get_type(attr) > max)
+ {
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ return 1;
}
-static int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
+static int __mnl_attr_validate(
+ const struct nlattr* attr,
+ enum mnl_attr_data_type type,
+ size_t exp_len)
{
- if (mnl_attr_get_type(attr) > max) {
- errno = EOPNOTSUPP;
- return -1;
- }
- return 1;
-}
+ uint16_t attr_len = mnl_attr_get_payload_len(attr);
+ const char* attr_data = mnl_attr_get_payload(attr);
-static int __mnl_attr_validate(const struct nlattr *attr,
- enum mnl_attr_data_type type, size_t exp_len)
-{
- uint16_t attr_len = mnl_attr_get_payload_len(attr);
- const char *attr_data = mnl_attr_get_payload(attr);
+ if (attr_len < exp_len)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ switch (type)
+ {
+ case MNL_TYPE_FLAG:
+ if (attr_len > 0)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_NUL_STRING:
+ if (attr_len == 0)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ if (attr_data[attr_len - 1] != '\0')
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_STRING:
+ if (attr_len == 0)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ case MNL_TYPE_NESTED:
- if (attr_len < exp_len) {
- errno = ERANGE;
- return -1;
- }
- switch(type) {
- case MNL_TYPE_FLAG:
- if (attr_len > 0) {
- errno = ERANGE;
- return -1;
- }
- break;
- case MNL_TYPE_NUL_STRING:
- if (attr_len == 0) {
- errno = ERANGE;
- return -1;
- }
- if (attr_data[attr_len-1] != '\0') {
- errno = EINVAL;
- return -1;
- }
- break;
- case MNL_TYPE_STRING:
- if (attr_len == 0) {
- errno = ERANGE;
- return -1;
- }
- break;
- case MNL_TYPE_NESTED:
+ if (attr_len == 0)
+ break;
- if (attr_len == 0)
- break;
+ if (attr_len < MNL_ATTR_HDRLEN)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ break;
+ default:
- if (attr_len < MNL_ATTR_HDRLEN) {
- errno = ERANGE;
- return -1;
- }
- break;
- default:
-
- break;
- }
- if (exp_len && attr_len > exp_len) {
- errno = ERANGE;
- return -1;
- }
- return 0;
+ break;
+ }
+ if (exp_len && attr_len > exp_len)
+ {
+ errno = ERANGE;
+ return -1;
+ }
+ return 0;
}
static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
- [MNL_TYPE_U8] = sizeof(uint8_t),
- [MNL_TYPE_U16] = sizeof(uint16_t),
- [MNL_TYPE_U32] = sizeof(uint32_t),
- [MNL_TYPE_U64] = sizeof(uint64_t),
- [MNL_TYPE_MSECS] = sizeof(uint64_t),
+ [MNL_TYPE_U8] = sizeof(uint8_t),
+ [MNL_TYPE_U16] = sizeof(uint16_t),
+ [MNL_TYPE_U32] = sizeof(uint32_t),
+ [MNL_TYPE_U64] = sizeof(uint64_t),
+ [MNL_TYPE_MSECS] = sizeof(uint64_t),
};
-static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
+static int mnl_attr_validate(const struct nlattr* attr, enum mnl_attr_data_type type)
{
- int exp_len;
+ int exp_len;
- if (type >= MNL_TYPE_MAX) {
- errno = EINVAL;
- return -1;
- }
- exp_len = mnl_attr_data_type_len[type];
- return __mnl_attr_validate(attr, type, exp_len);
+ if (type >= MNL_TYPE_MAX)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ exp_len = mnl_attr_data_type_len[type];
+ return __mnl_attr_validate(attr, type, exp_len);
}
-static int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
- mnl_attr_cb_t cb, void *data)
+static int mnl_attr_parse(
+ const struct nlmsghdr* nlh,
+ unsigned int offset,
+ mnl_attr_cb_t cb,
+ void* data)
{
- int ret = MNL_CB_OK;
- const struct nlattr *attr;
+ int ret = MNL_CB_OK;
+ const struct nlattr* attr;
- mnl_attr_for_each(attr, nlh, offset)
- if ((ret = cb(attr, data)) <= MNL_CB_STOP)
- return ret;
- return ret;
+ mnl_attr_for_each(
+ attr, nlh, offset) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
+ return ret;
}
-static int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
- void *data)
+static int
+mnl_attr_parse_nested(const struct nlattr* nested, mnl_attr_cb_t cb, void* data)
{
- int ret = MNL_CB_OK;
- const struct nlattr *attr;
+ int ret = MNL_CB_OK;
+ const struct nlattr* attr;
- mnl_attr_for_each_nested(attr, nested)
- if ((ret = cb(attr, data)) <= MNL_CB_STOP)
- return ret;
- return ret;
+ mnl_attr_for_each_nested(
+ attr, nested) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
+ return ret;
}
-static uint8_t mnl_attr_get_u8(const struct nlattr *attr)
+static uint8_t mnl_attr_get_u8(const struct nlattr* attr)
{
- return *((uint8_t *)mnl_attr_get_payload(attr));
+ return *((uint8_t*)mnl_attr_get_payload(attr));
}
-static uint16_t mnl_attr_get_u16(const struct nlattr *attr)
+static uint16_t mnl_attr_get_u16(const struct nlattr* attr)
{
- return *((uint16_t *)mnl_attr_get_payload(attr));
+ return *((uint16_t*)mnl_attr_get_payload(attr));
}
-static uint32_t mnl_attr_get_u32(const struct nlattr *attr)
+static uint32_t mnl_attr_get_u32(const struct nlattr* attr)
{
- return *((uint32_t *)mnl_attr_get_payload(attr));
+ return *((uint32_t*)mnl_attr_get_payload(attr));
}
-static uint64_t mnl_attr_get_u64(const struct nlattr *attr)
+static uint64_t mnl_attr_get_u64(const struct nlattr* attr)
{
- uint64_t tmp;
- memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
- return tmp;
+ uint64_t tmp;
+ memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
+ return tmp;
}
-static const char *mnl_attr_get_str(const struct nlattr *attr)
+static const char* mnl_attr_get_str(const struct nlattr* attr)
{
- return mnl_attr_get_payload(attr);
+ return mnl_attr_get_payload(attr);
}
-static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len,
- const void *data)
+static void
+mnl_attr_put(struct nlmsghdr* nlh, uint16_t type, size_t len, const void* data)
{
- struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
- uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
- int pad;
+ struct nlattr* attr = mnl_nlmsg_get_payload_tail(nlh);
+ uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
+ int pad;
- attr->nla_type = type;
- attr->nla_len = payload_len;
- memcpy(mnl_attr_get_payload(attr), data, len);
- nlh->nlmsg_len += MNL_ALIGN(payload_len);
- pad = MNL_ALIGN(len) - len;
- if (pad > 0)
- memset(mnl_attr_get_payload(attr) + len, 0, pad);
+ attr->nla_type = type;
+ attr->nla_len = payload_len;
+ memcpy(mnl_attr_get_payload(attr), data, len);
+
+ nlh->nlmsg_len += MNL_ALIGN(payload_len);
+ pad = MNL_ALIGN(len) - len;
+ if (pad > 0)
+ memset(mnl_attr_get_payload(attr) + len, 0, pad);
}
-static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
+static void mnl_attr_put_u16(struct nlmsghdr* nlh, uint16_t type, uint16_t data)
{
- mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
+ mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
}
-static void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
+static void mnl_attr_put_u32(struct nlmsghdr* nlh, uint16_t type, uint32_t data)
{
- mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
+ mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
}
-static void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
+static void mnl_attr_put_strz(struct nlmsghdr* nlh, uint16_t type, const char* data)
{
- mnl_attr_put(nlh, type, strlen(data)+1, data);
+ mnl_attr_put(nlh, type, strlen(data) + 1, data);
}
-static struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
+static struct nlattr* mnl_attr_nest_start(struct nlmsghdr* nlh, uint16_t type)
{
- struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
+ struct nlattr* start = mnl_nlmsg_get_payload_tail(nlh);
- start->nla_type = NLA_F_NESTED | type;
- nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
- return start;
+ start->nla_type = NLA_F_NESTED | type;
+ nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
+ return start;
}
-static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
- uint16_t type, size_t len, const void *data)
+static bool mnl_attr_put_check(
+ struct nlmsghdr* nlh,
+ size_t buflen,
+ uint16_t type,
+ size_t len,
+ const void* data)
{
- if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
- return false;
- mnl_attr_put(nlh, type, len, data);
- return true;
+ if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
+ return false;
+ mnl_attr_put(nlh, type, len, data);
+ return true;
}
-static bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
- uint16_t type, uint8_t data)
+static bool
+mnl_attr_put_u8_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint8_t data)
{
- return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
}
-static bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
- uint16_t type, uint16_t data)
+static bool
+mnl_attr_put_u16_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint16_t data)
{
- return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
}
-static bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
- uint16_t type, uint32_t data)
+static bool
+mnl_attr_put_u32_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint32_t data)
{
- return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
+ return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
}
-static struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen,
- uint16_t type)
+static struct nlattr*
+mnl_attr_nest_start_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type)
{
- if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
- return NULL;
- return mnl_attr_nest_start(nlh, type);
+ if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
+ return NULL;
+ return mnl_attr_nest_start(nlh, type);
}
-static void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
+static void mnl_attr_nest_end(struct nlmsghdr* nlh, struct nlattr* start)
{
- start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
+ start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
}
-static void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
+static void mnl_attr_nest_cancel(struct nlmsghdr* nlh, struct nlattr* start)
{
- nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
+ nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
}
-static int mnl_cb_noop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+static int mnl_cb_noop(
+ __attribute__((unused)) const struct nlmsghdr* nlh,
+ __attribute__((unused)) void* data)
{
- return MNL_CB_OK;
+ return MNL_CB_OK;
}
-static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+static int mnl_cb_error(const struct nlmsghdr* nlh, __attribute__((unused)) void* data)
{
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
+ const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh);
- if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
- errno = EBADMSG;
- return MNL_CB_ERROR;
- }
+ if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
+ {
+ errno = EBADMSG;
+ return MNL_CB_ERROR;
+ }
- if (err->error < 0)
- errno = -err->error;
- else
- errno = err->error;
+ if (err->error < 0)
+ errno = -err->error;
+ else
+ errno = err->error;
- return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+ return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
}
-static int mnl_cb_stop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
+static int mnl_cb_stop(
+ __attribute__((unused)) const struct nlmsghdr* nlh,
+ __attribute__((unused)) void* data)
{
- return MNL_CB_STOP;
+ return MNL_CB_STOP;
}
static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
- [NLMSG_NOOP] = mnl_cb_noop,
- [NLMSG_ERROR] = mnl_cb_error,
- [NLMSG_DONE] = mnl_cb_stop,
- [NLMSG_OVERRUN] = mnl_cb_noop,
+ [NLMSG_NOOP] = mnl_cb_noop,
+ [NLMSG_ERROR] = mnl_cb_error,
+ [NLMSG_DONE] = mnl_cb_stop,
+ [NLMSG_OVERRUN] = mnl_cb_noop,
};
-static int __mnl_cb_run(const void *buf, size_t numbytes,
- unsigned int seq, unsigned int portid,
- mnl_cb_t cb_data, void *data,
- const mnl_cb_t *cb_ctl_array,
- unsigned int cb_ctl_array_len)
+static int __mnl_cb_run(
+ const void* buf,
+ size_t numbytes,
+ unsigned int seq,
+ unsigned int portid,
+ mnl_cb_t cb_data,
+ void* data,
+ const mnl_cb_t* cb_ctl_array,
+ unsigned int cb_ctl_array_len)
{
- int ret = MNL_CB_OK, len = numbytes;
- const struct nlmsghdr *nlh = buf;
+ int ret = MNL_CB_OK, len = numbytes;
+ const struct nlmsghdr* nlh = buf;
- while (mnl_nlmsg_ok(nlh, len)) {
+ while (mnl_nlmsg_ok(nlh, len))
+ {
- if (!mnl_nlmsg_portid_ok(nlh, portid)) {
- errno = ESRCH;
- return -1;
- }
+ if (!mnl_nlmsg_portid_ok(nlh, portid))
+ {
+ errno = ESRCH;
+ return -1;
+ }
- if (!mnl_nlmsg_seq_ok(nlh, seq)) {
- errno = EPROTO;
- return -1;
- }
+ if (!mnl_nlmsg_seq_ok(nlh, seq))
+ {
+ errno = EPROTO;
+ return -1;
+ }
- if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
- errno = EINTR;
- return -1;
- }
+ if (nlh->nlmsg_flags & NLM_F_DUMP_INTR)
+ {
+ errno = EINTR;
+ return -1;
+ }
- if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
- if (cb_data){
- ret = cb_data(nlh, data);
- if (ret <= MNL_CB_STOP)
- goto out;
- }
- } else if (nlh->nlmsg_type < cb_ctl_array_len) {
- if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
- ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
- if (ret <= MNL_CB_STOP)
- goto out;
- }
- } else if (default_cb_array[nlh->nlmsg_type]) {
- ret = default_cb_array[nlh->nlmsg_type](nlh, data);
- if (ret <= MNL_CB_STOP)
- goto out;
- }
- nlh = mnl_nlmsg_next(nlh, &len);
- }
+ if (nlh->nlmsg_type >= NLMSG_MIN_TYPE)
+ {
+ if (cb_data)
+ {
+ ret = cb_data(nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ }
+ else if (nlh->nlmsg_type < cb_ctl_array_len)
+ {
+ if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type])
+ {
+ ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ }
+ else if (default_cb_array[nlh->nlmsg_type])
+ {
+ ret = default_cb_array[nlh->nlmsg_type](nlh, data);
+ if (ret <= MNL_CB_STOP)
+ goto out;
+ }
+ nlh = mnl_nlmsg_next(nlh, &len);
+ }
out:
- return ret;
+ return ret;
}
-static int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
- unsigned int portid, mnl_cb_t cb_data, void *data,
- const mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
+static int mnl_cb_run2(
+ const void* buf,
+ size_t numbytes,
+ unsigned int seq,
+ unsigned int portid,
+ mnl_cb_t cb_data,
+ void* data,
+ const mnl_cb_t* cb_ctl_array,
+ unsigned int cb_ctl_array_len)
{
- return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
- cb_ctl_array, cb_ctl_array_len);
+ return __mnl_cb_run(
+ buf, numbytes, seq, portid, cb_data, data, cb_ctl_array, cb_ctl_array_len);
}
-static int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
- unsigned int portid, mnl_cb_t cb_data, void *data)
+static int mnl_cb_run(
+ const void* buf,
+ size_t numbytes,
+ unsigned int seq,
+ unsigned int portid,
+ mnl_cb_t cb_data,
+ void* data)
{
- return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
+ return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
}
-struct mnl_socket {
- int fd;
- struct sockaddr_nl addr;
+struct mnl_socket
+{
+ int fd;
+ struct sockaddr_nl addr;
};
-static unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
+static unsigned int mnl_socket_get_portid(const struct mnl_socket* nl)
{
- return nl->addr.nl_pid;
+ return nl->addr.nl_pid;
}
-static struct mnl_socket *__mnl_socket_open(int bus, int flags)
+static struct mnl_socket* __mnl_socket_open(int bus, int flags)
{
- struct mnl_socket *nl;
+ struct mnl_socket* nl;
- nl = calloc(1, sizeof(struct mnl_socket));
- if (nl == NULL)
- return NULL;
+ nl = calloc(1, sizeof(struct mnl_socket));
+ if (nl == NULL)
+ return NULL;
- nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
- if (nl->fd == -1) {
- free(nl);
- return NULL;
- }
+ nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
+ if (nl->fd == -1)
+ {
+ free(nl);
+ return NULL;
+ }
- return nl;
+ return nl;
}
-static struct mnl_socket *mnl_socket_open(int bus)
+static struct mnl_socket* mnl_socket_open(int bus) { return __mnl_socket_open(bus, 0); }
+
+static int mnl_socket_bind(struct mnl_socket* nl, unsigned int groups, pid_t pid)
{
- return __mnl_socket_open(bus, 0);
+ int ret;
+ socklen_t addr_len;
+
+ nl->addr.nl_family = AF_NETLINK;
+ nl->addr.nl_groups = groups;
+ nl->addr.nl_pid = pid;
+
+ ret = bind(nl->fd, (struct sockaddr*)&nl->addr, sizeof(nl->addr));
+ if (ret < 0)
+ return ret;
+
+ addr_len = sizeof(nl->addr);
+ ret = getsockname(nl->fd, (struct sockaddr*)&nl->addr, &addr_len);
+ if (ret < 0)
+ return ret;
+
+ if (addr_len != sizeof(nl->addr))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if (nl->addr.nl_family != AF_NETLINK)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
}
-static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
+static ssize_t mnl_socket_sendto(const struct mnl_socket* nl, const void* buf, size_t len)
{
- int ret;
- socklen_t addr_len;
-
- nl->addr.nl_family = AF_NETLINK;
- nl->addr.nl_groups = groups;
- nl->addr.nl_pid = pid;
-
- ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
- if (ret < 0)
- return ret;
-
- addr_len = sizeof(nl->addr);
- ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
- if (ret < 0)
- return ret;
-
- if (addr_len != sizeof(nl->addr)) {
- errno = EINVAL;
- return -1;
- }
- if (nl->addr.nl_family != AF_NETLINK) {
- errno = EINVAL;
- return -1;
- }
- return 0;
+ static const struct sockaddr_nl snl = {.nl_family = AF_NETLINK};
+ return sendto(nl->fd, buf, len, 0, (struct sockaddr*)&snl, sizeof(snl));
}
-static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf,
- size_t len)
+static ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_t bufsiz)
{
- static const struct sockaddr_nl snl = {
- .nl_family = AF_NETLINK
- };
- return sendto(nl->fd, buf, len, 0,
- (struct sockaddr *) &snl, sizeof(snl));
+ ssize_t ret;
+ struct sockaddr_nl addr;
+ struct iovec iov = {
+ .iov_base = buf,
+ .iov_len = bufsiz,
+ };
+ struct msghdr msg = {
+ .msg_name = &addr,
+ .msg_namelen = sizeof(struct sockaddr_nl),
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = NULL,
+ .msg_controllen = 0,
+ .msg_flags = 0,
+ };
+ ret = recvmsg(nl->fd, &msg, 0);
+ if (ret == -1)
+ return ret;
+
+ if (msg.msg_flags & MSG_TRUNC)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+ if (msg.msg_namelen != sizeof(struct sockaddr_nl))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return ret;
}
-static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf,
- size_t bufsiz)
+static int mnl_socket_close(struct mnl_socket* nl)
{
- ssize_t ret;
- struct sockaddr_nl addr;
- struct iovec iov = {
- .iov_base = buf,
- .iov_len = bufsiz,
- };
- struct msghdr msg = {
- .msg_name = &addr,
- .msg_namelen = sizeof(struct sockaddr_nl),
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_flags = 0,
- };
- ret = recvmsg(nl->fd, &msg, 0);
- if (ret == -1)
- return ret;
-
- if (msg.msg_flags & MSG_TRUNC) {
- errno = ENOSPC;
- return -1;
- }
- if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
- errno = EINVAL;
- return -1;
- }
- return ret;
-}
-
-static int mnl_socket_close(struct mnl_socket *nl)
-{
- int ret = close(nl->fd);
- free(nl);
- return ret;
+ int ret = close(nl->fd);
+ free(nl);
+ return ret;
}
/* This is a wrapper for generic netlink, originally from Jiri Pirko : */
-struct mnlg_socket {
- struct mnl_socket *nl;
- char *buf;
- uint16_t id;
- uint8_t version;
- unsigned int seq;
- unsigned int portid;
+struct mnlg_socket
+{
+ struct mnl_socket* nl;
+ char* buf;
+ uint16_t id;
+ uint8_t version;
+ unsigned int seq;
+ unsigned int portid;
};
-static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
- uint16_t flags, uint16_t id,
- uint8_t version)
+static struct nlmsghdr* __mnlg_msg_prepare(
+ struct mnlg_socket* nlg,
+ uint8_t cmd,
+ uint16_t flags,
+ uint16_t id,
+ uint8_t version)
{
- struct nlmsghdr *nlh;
- struct genlmsghdr *genl;
+ struct nlmsghdr* nlh;
+ struct genlmsghdr* genl;
- nlh = mnl_nlmsg_put_header(nlg->buf);
- nlh->nlmsg_type = id;
- nlh->nlmsg_flags = flags;
- nlg->seq = time(NULL);
- nlh->nlmsg_seq = nlg->seq;
+ nlh = mnl_nlmsg_put_header(nlg->buf);
+ nlh->nlmsg_type = id;
+ nlh->nlmsg_flags = flags;
+ nlg->seq = time(NULL);
+ nlh->nlmsg_seq = nlg->seq;
- genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
- genl->cmd = cmd;
- genl->version = version;
+ genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
+ genl->cmd = cmd;
+ genl->version = version;
- return nlh;
+ return nlh;
}
-static struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
- uint16_t flags)
+static struct nlmsghdr*
+mnlg_msg_prepare(struct mnlg_socket* nlg, uint8_t cmd, uint16_t flags)
{
- return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
+ return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
}
-static int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
+static int mnlg_socket_send(struct mnlg_socket* nlg, const struct nlmsghdr* nlh)
{
- return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
+ return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
}
-static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
+static int mnlg_cb_noop(const struct nlmsghdr* nlh, void* data)
{
- (void)nlh;
- (void)data;
- return MNL_CB_OK;
+ (void)nlh;
+ (void)data;
+ return MNL_CB_OK;
}
-static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
+static int mnlg_cb_error(const struct nlmsghdr* nlh, void* data)
{
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
- (void)data;
+ const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh);
+ (void)data;
- if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
- errno = EBADMSG;
- return MNL_CB_ERROR;
- }
- /* Netlink subsystems returns the errno value with different signess */
- if (err->error < 0)
- errno = -err->error;
- else
- errno = err->error;
+ if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
+ {
+ errno = EBADMSG;
+ return MNL_CB_ERROR;
+ }
+ /* Netlink subsystems returns the errno value with different signess */
+ if (err->error < 0)
+ errno = -err->error;
+ else
+ errno = err->error;
- return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+ return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
}
-static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
+static int mnlg_cb_stop(const struct nlmsghdr* nlh, void* data)
{
- (void)data;
- if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) {
- int error = *(int *)mnl_nlmsg_get_payload(nlh);
- /* Netlink subsystems returns the errno value with different signess */
- if (error < 0)
- errno = -error;
- else
- errno = error;
+ (void)data;
+ if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int)))
+ {
+ int error = *(int*)mnl_nlmsg_get_payload(nlh);
+ /* Netlink subsystems returns the errno value with different signess */
+ if (error < 0)
+ errno = -error;
+ else
+ errno = error;
- return error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
- }
- return MNL_CB_STOP;
+ return error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
+ }
+ return MNL_CB_STOP;
}
static const mnl_cb_t mnlg_cb_array[] = {
- [NLMSG_NOOP] = mnlg_cb_noop,
- [NLMSG_ERROR] = mnlg_cb_error,
- [NLMSG_DONE] = mnlg_cb_stop,
- [NLMSG_OVERRUN] = mnlg_cb_noop,
+ [NLMSG_NOOP] = mnlg_cb_noop,
+ [NLMSG_ERROR] = mnlg_cb_error,
+ [NLMSG_DONE] = mnlg_cb_stop,
+ [NLMSG_OVERRUN] = mnlg_cb_noop,
};
-static int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
+static int mnlg_socket_recv_run(struct mnlg_socket* nlg, mnl_cb_t data_cb, void* data)
{
- int err;
+ int err;
- do {
- err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
- mnl_ideal_socket_buffer_size());
- if (err <= 0)
- break;
- err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
- data_cb, data, mnlg_cb_array, MNL_ARRAY_SIZE(mnlg_cb_array));
- } while (err > 0);
+ do
+ {
+ err = mnl_socket_recvfrom(nlg->nl, nlg->buf, mnl_ideal_socket_buffer_size());
+ if (err <= 0)
+ break;
+ err = mnl_cb_run2(
+ nlg->buf,
+ err,
+ nlg->seq,
+ nlg->portid,
+ data_cb,
+ data,
+ mnlg_cb_array,
+ MNL_ARRAY_SIZE(mnlg_cb_array));
+ } while (err > 0);
- return err;
+ return err;
}
-static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
+static int get_family_id_attr_cb(const struct nlattr* attr, void* data)
{
- const struct nlattr **tb = data;
- int type = mnl_attr_get_type(attr);
+ const struct nlattr** tb = data;
+ int type = mnl_attr_get_type(attr);
- if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
- return MNL_CB_ERROR;
+ if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
+ return MNL_CB_ERROR;
- if (type == CTRL_ATTR_FAMILY_ID &&
- mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
- return MNL_CB_ERROR;
- tb[type] = attr;
- return MNL_CB_OK;
+ if (type == CTRL_ATTR_FAMILY_ID && mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
+ return MNL_CB_ERROR;
+ tb[type] = attr;
+ return MNL_CB_OK;
}
-static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
+static int get_family_id_cb(const struct nlmsghdr* nlh, void* data)
{
- uint16_t *p_id = data;
- struct nlattr *tb[CTRL_ATTR_MAX + 1] = { 0 };
+ uint16_t* p_id = data;
+ struct nlattr* tb[CTRL_ATTR_MAX + 1] = {0};
- mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
- if (!tb[CTRL_ATTR_FAMILY_ID])
- return MNL_CB_ERROR;
- *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
- return MNL_CB_OK;
+ mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
+ if (!tb[CTRL_ATTR_FAMILY_ID])
+ return MNL_CB_ERROR;
+ *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
+ return MNL_CB_OK;
}
-static struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
+static struct mnlg_socket* mnlg_socket_open(const char* family_name, uint8_t version)
{
- struct mnlg_socket *nlg;
- struct nlmsghdr *nlh;
- int err;
+ struct mnlg_socket* nlg;
+ struct nlmsghdr* nlh;
+ int err;
- nlg = malloc(sizeof(*nlg));
- if (!nlg)
- return NULL;
- nlg->id = 0;
+ nlg = malloc(sizeof(*nlg));
+ if (!nlg)
+ return NULL;
+ nlg->id = 0;
- err = -ENOMEM;
- nlg->buf = malloc(mnl_ideal_socket_buffer_size());
- if (!nlg->buf)
- goto err_buf_alloc;
+ err = -ENOMEM;
+ nlg->buf = malloc(mnl_ideal_socket_buffer_size());
+ if (!nlg->buf)
+ goto err_buf_alloc;
- nlg->nl = mnl_socket_open(NETLINK_GENERIC);
- if (!nlg->nl) {
- err = -errno;
- goto err_mnl_socket_open;
- }
+ nlg->nl = mnl_socket_open(NETLINK_GENERIC);
+ if (!nlg->nl)
+ {
+ err = -errno;
+ goto err_mnl_socket_open;
+ }
- if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
- err = -errno;
- goto err_mnl_socket_bind;
- }
+ if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0)
+ {
+ err = -errno;
+ goto err_mnl_socket_bind;
+ }
- nlg->portid = mnl_socket_get_portid(nlg->nl);
+ nlg->portid = mnl_socket_get_portid(nlg->nl);
- nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
- NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
- mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
+ nlh = __mnlg_msg_prepare(
+ nlg, CTRL_CMD_GETFAMILY, NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
+ mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
- if (mnlg_socket_send(nlg, nlh) < 0) {
- err = -errno;
- goto err_mnlg_socket_send;
- }
+ if (mnlg_socket_send(nlg, nlh) < 0)
+ {
+ err = -errno;
+ goto err_mnlg_socket_send;
+ }
- errno = 0;
- if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0) {
- errno = errno == ENOENT ? EPROTONOSUPPORT : errno;
- err = errno ? -errno : -ENOSYS;
- goto err_mnlg_socket_recv_run;
- }
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0)
+ {
+ errno = errno == ENOENT ? EPROTONOSUPPORT : errno;
+ err = errno ? -errno : -ENOSYS;
+ goto err_mnlg_socket_recv_run;
+ }
- nlg->version = version;
- errno = 0;
- return nlg;
+ nlg->version = version;
+ errno = 0;
+ return nlg;
err_mnlg_socket_recv_run:
err_mnlg_socket_send:
err_mnl_socket_bind:
- mnl_socket_close(nlg->nl);
+ mnl_socket_close(nlg->nl);
err_mnl_socket_open:
- free(nlg->buf);
+ free(nlg->buf);
err_buf_alloc:
- free(nlg);
- errno = -err;
- return NULL;
+ free(nlg);
+ errno = -err;
+ return NULL;
}
-static void mnlg_socket_close(struct mnlg_socket *nlg)
+static void mnlg_socket_close(struct mnlg_socket* nlg)
{
- mnl_socket_close(nlg->nl);
- free(nlg->buf);
- free(nlg);
+ mnl_socket_close(nlg->nl);
+ free(nlg->buf);
+ free(nlg);
}
diff --git a/src/showconf.c b/src/showconf.c
index 0f9622c..5aba185 100644
--- a/src/showconf.c
+++ b/src/showconf.c
@@ -94,6 +94,9 @@ int showconf_main(int argc, const char *argv[])
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off");
}
+ if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE) {
+ printf("SpecialHandshake = %s\n", peer->special_handshake ? "on" : "off");
+ }
if (peer->first_allowedip)
printf("AllowedIPs = ");
for_each_wgallowedip(peer, allowedip) {
diff --git a/src/uapi/linux/linux/wireguard.h b/src/uapi/linux/linux/wireguard.h
index c4849bb..cca01ab 100644
--- a/src/uapi/linux/linux/wireguard.h
+++ b/src/uapi/linux/linux/wireguard.h
@@ -114,6 +114,9 @@
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
* techniques provided by AmneziaWG should
* be used.
+ * WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake
+ * techniques provided by AmneziaWG should
+ * be used.
* 0: NLA_NESTED
* ...
* ...
@@ -147,6 +150,9 @@
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
* techniques provided by AmneziaWG should
* be used.
+ * WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake
+ * techniques provided by AmneziaWG should
+ * be used.
*
*/
@@ -210,6 +216,7 @@ enum wgpeer_flag {
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_F_UPDATE_ONLY = 1U << 2,
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
+ WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4,
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
WGPEER_F_UPDATE_ONLY
};
@@ -226,6 +233,7 @@ enum wgpeer_attribute {
WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
+ WGPEER_A_SPECIAL_HANDSHAKE,
__WGPEER_A_LAST
};
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
diff --git a/src/uapi/openbsd/net/if_wg.h b/src/uapi/openbsd/net/if_wg.h
index f768a32..9bc3b91 100644
--- a/src/uapi/openbsd/net/if_wg.h
+++ b/src/uapi/openbsd/net/if_wg.h
@@ -7,13 +7,12 @@
#ifndef __IF_WG_H__
#define __IF_WG_H__
-#include
#include
+#include
#include
#include
-
/*
* This is the public interface to the WireGuard network interface.
*
@@ -25,87 +24,112 @@
#define SIOCSWG _IOWR('i', 210, struct wg_data_io)
#define SIOCGWG _IOWR('i', 211, struct wg_data_io)
-#define a_ipv4 a_addr.addr_ipv4
-#define a_ipv6 a_addr.addr_ipv6
+#define a_ipv4 a_addr.addr_ipv4
+#define a_ipv6 a_addr.addr_ipv6
-struct wg_aip_io {
- sa_family_t a_af;
- int a_cidr;
- union wg_aip_addr {
- struct in_addr addr_ipv4;
- struct in6_addr addr_ipv6;
- } a_addr;
+struct wg_aip_io
+{
+ sa_family_t a_af;
+ int a_cidr;
+ union wg_aip_addr
+ {
+ struct in_addr addr_ipv4;
+ struct in6_addr addr_ipv6;
+ } a_addr;
};
-#define WG_PEER_HAS_PUBLIC (1 << 0)
-#define WG_PEER_HAS_PSK (1 << 1)
-#define WG_PEER_HAS_PKA (1 << 2)
-#define WG_PEER_HAS_ENDPOINT (1 << 3)
-#define WG_PEER_REPLACE_AIPS (1 << 4)
-#define WG_PEER_REMOVE (1 << 5)
-#define WG_PEER_UPDATE (1 << 6)
+#define WG_PEER_HAS_PUBLIC (1 << 0)
+#define WG_PEER_HAS_PSK (1 << 1)
+#define WG_PEER_HAS_PKA (1 << 2)
+#define WG_PEER_HAS_ENDPOINT (1 << 3)
+#define WG_PEER_REPLACE_AIPS (1 << 4)
+#define WG_PEER_REMOVE (1 << 5)
+#define WG_PEER_UPDATE (1 << 6)
-#define p_sa p_endpoint.sa_sa
-#define p_sin p_endpoint.sa_sin
-#define p_sin6 p_endpoint.sa_sin6
+#define p_sa p_endpoint.sa_sa
+#define p_sin p_endpoint.sa_sin
+#define p_sin6 p_endpoint.sa_sin6
-struct wg_peer_io {
- int p_flags;
- int p_protocol_version;
- uint8_t p_public[WG_KEY_LEN];
- uint8_t p_psk[WG_KEY_LEN];
- uint16_t p_pka;
- union wg_peer_endpoint {
- struct sockaddr sa_sa;
- struct sockaddr_in sa_sin;
- struct sockaddr_in6 sa_sin6;
- } p_endpoint;
- uint64_t p_txbytes;
- uint64_t p_rxbytes;
- struct timespec p_last_handshake; /* nanotime */
- size_t p_aips_count;
- struct wg_aip_io p_aips[];
+struct wg_peer_io
+{
+ int p_flags;
+ int p_protocol_version;
+ uint8_t p_public[WG_KEY_LEN];
+ uint8_t p_psk[WG_KEY_LEN];
+ uint16_t p_pka;
+ union wg_peer_endpoint
+ {
+ struct sockaddr sa_sa;
+ struct sockaddr_in sa_sin;
+ struct sockaddr_in6 sa_sin6;
+ } p_endpoint;
+ uint64_t p_txbytes;
+ uint64_t p_rxbytes;
+ struct timespec p_last_handshake; /* nanotime */
+ size_t p_aips_count;
+ struct wg_aip_io p_aips[];
};
-#define WG_INTERFACE_HAS_PUBLIC (1 << 0)
-#define WG_INTERFACE_HAS_PRIVATE (1 << 1)
-#define WG_INTERFACE_HAS_PORT (1 << 2)
-#define WG_INTERFACE_HAS_RTABLE (1 << 3)
-#define WG_INTERFACE_REPLACE_PEERS (1 << 4)
-#define WG_INTERFACE_DEVICE_HAS_JC (1 << 5)
+#define WG_INTERFACE_HAS_PUBLIC (1 << 0)
+#define WG_INTERFACE_HAS_PRIVATE (1 << 1)
+#define WG_INTERFACE_HAS_PORT (1 << 2)
+#define WG_INTERFACE_HAS_RTABLE (1 << 3)
+#define WG_INTERFACE_REPLACE_PEERS (1 << 4)
+#define WG_INTERFACE_DEVICE_HAS_JC (1 << 5)
#define WG_INTERFACE_DEVICE_HAS_JMIN (1 << 6)
#define WG_INTERFACE_DEVICE_HAS_JMAX (1 << 7)
-#define WG_INTERFACE_DEVICE_HAS_S1 (1 << 8)
-#define WG_INTERFACE_DEVICE_HAS_S2 (1 << 9)
-#define WG_INTERFACE_DEVICE_HAS_H1 (1 << 10)
-#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11)
-#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12)
-#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13)
+#define WG_INTERFACE_DEVICE_HAS_S1 (1 << 8)
+#define WG_INTERFACE_DEVICE_HAS_S2 (1 << 9)
+#define WG_INTERFACE_DEVICE_HAS_H1 (1 << 10)
+#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11)
+#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12)
+#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13)
+#define WG_INTERFACE_DEVICE_HAS_I1 (1 << 14)
+#define WG_INTERFACE_DEVICE_HAS_I2 (1 << 15)
+#define WG_INTERFACE_DEVICE_HAS_I3 (1 << 16)
+#define WG_INTERFACE_DEVICE_HAS_I4 (1 << 17)
+#define WG_INTERFACE_DEVICE_HAS_I5 (1 << 18)
+#define WG_INTERFACE_DEVICE_HAS_J1 (1 << 19)
+#define WG_INTERFACE_DEVICE_HAS_J2 (1 << 20)
+#define WG_INTERFACE_DEVICE_HAS_J3 (1 << 21)
+#define WG_INTERFACE_DEVICE_HAS_ITIME (1 << 22)
-struct wg_interface_io {
- uint16_t i_flags;
- in_port_t i_port;
- int i_rtable;
- uint8_t i_public[WG_KEY_LEN];
- uint8_t i_private[WG_KEY_LEN];
- size_t i_peers_count;
- struct wg_peer_io i_peers[];
+struct wg_interface_io
+{
+ uint16_t i_flags;
+ in_port_t i_port;
+ int i_rtable;
+ uint8_t i_public[WG_KEY_LEN];
+ uint8_t i_private[WG_KEY_LEN];
+ size_t i_peers_count;
+ struct wg_peer_io i_peers[];
- uint16_t i_junk_packet_count;
- uint16_t i_junk_packet_min_size;
- uint16_t i_junk_packet_max_size;
- uint16_t i_init_packet_junk_size;
- uint16_t i_response_packet_junk_size;
- uint32_t i_init_packet_magic_header;
- uint32_t i_response_packet_magic_header;
- uint32_t i_underload_packet_magic_header;
- uint32_t i_transport_packet_magic_header;
+ uint16_t i_junk_packet_count;
+ uint16_t i_junk_packet_min_size;
+ uint16_t i_junk_packet_max_size;
+ uint16_t i_init_packet_junk_size;
+ uint16_t i_response_packet_junk_size;
+ uint32_t i_init_packet_magic_header;
+ uint32_t i_response_packet_magic_header;
+ uint32_t i_underload_packet_magic_header;
+ uint32_t i_transport_packet_magic_header;
+
+ uint8_t* i_i1;
+ uint8_t* i_i2;
+ uint8_t* i_i3;
+ uint8_t* i_i4;
+ uint8_t* i_i5;
+ uint8_t* i_j1;
+ uint8_t* i_j2;
+ uint8_t* i_j3;
+ uint32_t i_itime;
};
-struct wg_data_io {
- char wgd_name[IFNAMSIZ];
- size_t wgd_size; /* total size of the memory pointed to by wgd_interface */
- struct wg_interface_io *wgd_interface;
+struct wg_data_io
+{
+ char wgd_name[IFNAMSIZ];
+ size_t wgd_size; /* total size of the memory pointed to by wgd_interface */
+ struct wg_interface_io* wgd_interface;
};
#endif /* __IF_WG_H__ */
diff --git a/src/uapi/windows/wireguard.h b/src/uapi/windows/wireguard.h
index 917d785..1b99427 100644
--- a/src/uapi/windows/wireguard.h
+++ b/src/uapi/windows/wireguard.h
@@ -6,94 +6,113 @@
#ifndef _WIREGUARD_NT_H
#define _WIREGUARD_NT_H
+#include
+#include
#include
#include
#include
-#include
-#include
#define WG_KEY_LEN 32
typedef struct _WG_IOCTL_ALLOWED_IP
{
- union
- {
- IN_ADDR V4;
- IN6_ADDR V6;
- } Address;
- ADDRESS_FAMILY AddressFamily;
- UCHAR Cidr;
+ union
+ {
+ IN_ADDR V4;
+ IN6_ADDR V6;
+ } Address;
+ ADDRESS_FAMILY AddressFamily;
+ UCHAR Cidr;
} __attribute__((aligned(8))) WG_IOCTL_ALLOWED_IP;
typedef enum
{
- WG_IOCTL_PEER_HAS_PUBLIC_KEY = 1 << 0,
- WG_IOCTL_PEER_HAS_PRESHARED_KEY = 1 << 1,
- WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2,
- WG_IOCTL_PEER_HAS_ENDPOINT = 1 << 3,
- WG_IOCTL_PEER_HAS_PROTOCOL_VERSION = 1 << 4,
- WG_IOCTL_PEER_REPLACE_ALLOWED_IPS = 1 << 5,
- WG_IOCTL_PEER_REMOVE = 1 << 6,
- WG_IOCTL_PEER_UPDATE = 1 << 7
+ WG_IOCTL_PEER_HAS_PUBLIC_KEY = 1 << 0,
+ WG_IOCTL_PEER_HAS_PRESHARED_KEY = 1 << 1,
+ WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2,
+ WG_IOCTL_PEER_HAS_ENDPOINT = 1 << 3,
+ WG_IOCTL_PEER_HAS_PROTOCOL_VERSION = 1 << 4,
+ WG_IOCTL_PEER_REPLACE_ALLOWED_IPS = 1 << 5,
+ WG_IOCTL_PEER_REMOVE = 1 << 6,
+ WG_IOCTL_PEER_UPDATE = 1 << 7
} WG_IOCTL_PEER_FLAG;
typedef struct _WG_IOCTL_PEER
{
- WG_IOCTL_PEER_FLAG Flags;
- ULONG ProtocolVersion; /* 0 = latest protocol, 1 = this protocol. */
- UCHAR PublicKey[WG_KEY_LEN];
- UCHAR PresharedKey[WG_KEY_LEN];
- USHORT PersistentKeepalive;
- SOCKADDR_INET Endpoint;
- ULONG64 TxBytes;
- ULONG64 RxBytes;
- ULONG64 LastHandshake;
- ULONG AllowedIPsCount;
+ WG_IOCTL_PEER_FLAG Flags;
+ ULONG ProtocolVersion; /* 0 = latest protocol, 1 = this protocol. */
+ UCHAR PublicKey[WG_KEY_LEN];
+ UCHAR PresharedKey[WG_KEY_LEN];
+ USHORT PersistentKeepalive;
+ SOCKADDR_INET Endpoint;
+ ULONG64 TxBytes;
+ ULONG64 RxBytes;
+ ULONG64 LastHandshake;
+ ULONG AllowedIPsCount;
} __attribute__((aligned(8))) WG_IOCTL_PEER;
typedef enum
{
- WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY = 1 << 0,
- WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY = 1 << 1,
- WG_IOCTL_INTERFACE_HAS_LISTEN_PORT = 1 << 2,
- WG_IOCTL_INTERFACE_REPLACE_PEERS = 1 << 3,
- WG_IOCTL_INTERFACE_PEERS = 1 << 4,
- WG_IOCTL_INTERFACE_JC = 1 << 5,
- WG_IOCTL_INTERFACE_JMIN = 1 << 6,
- WG_IOCTL_INTERFACE_JMAX = 1 << 7,
- WG_IOCTL_INTERFACE_S1 = 1 << 8,
- WG_IOCTL_INTERFACE_S2 = 1 << 9,
- WG_IOCTL_INTERFACE_H1 = 1 << 10,
- WG_IOCTL_INTERFACE_H2 = 1 << 11,
- WG_IOCTL_INTERFACE_H3 = 1 << 12,
- WG_IOCTL_INTERFACE_H4 = 1 << 13
+ WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY = 1 << 0,
+ WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY = 1 << 1,
+ WG_IOCTL_INTERFACE_HAS_LISTEN_PORT = 1 << 2,
+ WG_IOCTL_INTERFACE_REPLACE_PEERS = 1 << 3,
+ WG_IOCTL_INTERFACE_PEERS = 1 << 4,
+ WG_IOCTL_INTERFACE_JC = 1 << 5,
+ WG_IOCTL_INTERFACE_JMIN = 1 << 6,
+ WG_IOCTL_INTERFACE_JMAX = 1 << 7,
+ WG_IOCTL_INTERFACE_S1 = 1 << 8,
+ WG_IOCTL_INTERFACE_S2 = 1 << 9,
+ WG_IOCTL_INTERFACE_H1 = 1 << 10,
+ WG_IOCTL_INTERFACE_H2 = 1 << 11,
+ WG_IOCTL_INTERFACE_H3 = 1 << 12,
+ WG_IOCTL_INTERFACE_H4 = 1 << 13,
+ WG_IOCTL_INTERFACE_I1 = 1U << 14,
+ WG_IOCTL_INTERFACE_I2 = 1U << 15,
+ WG_IOCTL_INTERFACE_I3 = 1U << 16,
+ WG_IOCTL_INTERFACE_I4 = 1U << 17,
+ WG_IOCTL_INTERFACE_I5 = 1U << 18,
+ WG_IOCTL_INTERFACE_J1 = 1U << 19,
+ WG_IOCTL_INTERFACE_J2 = 1U << 20,
+ WG_IOCTL_INTERFACE_J3 = 1U << 21,
+ WG_IOCTL_INTERFACE_ITIME = 1U << 22
} WG_IOCTL_INTERFACE_FLAG;
typedef struct _WG_IOCTL_INTERFACE
{
- WG_IOCTL_INTERFACE_FLAG Flags;
- USHORT ListenPort;
- UCHAR PrivateKey[WG_KEY_LEN];
- UCHAR PublicKey[WG_KEY_LEN];
- ULONG PeersCount;
- USHORT JunkPacketCount;
- USHORT JunkPacketMinSize;
- USHORT JunkPacketMaxSize;
- USHORT InitPacketJunkSize;
- USHORT ResponsePacketJunkSize;
- ULONG InitPacketMagicHeader;
- ULONG ResponsePacketMagicHeader;
- ULONG UnderloadPacketMagicHeader;
- ULONG TransportPacketMagicHeader;
+ WG_IOCTL_INTERFACE_FLAG Flags;
+ USHORT ListenPort;
+ UCHAR PrivateKey[WG_KEY_LEN];
+ UCHAR PublicKey[WG_KEY_LEN];
+ ULONG PeersCount;
+ USHORT JunkPacketCount;
+ USHORT JunkPacketMinSize;
+ USHORT JunkPacketMaxSize;
+ USHORT InitPacketJunkSize;
+ USHORT ResponsePacketJunkSize;
+ ULONG InitPacketMagicHeader;
+ ULONG ResponsePacketMagicHeader;
+ ULONG UnderloadPacketMagicHeader;
+ ULONG TransportPacketMagicHeader;
+ UCHAR* I1;
+ UCHAR* I2;
+ UCHAR* I3;
+ UCHAR* I4;
+ UCHAR* I5;
+ UCHAR* J1;
+ UCHAR* J2;
+ UCHAR* J3;
+ ULONG Itime;
} __attribute__((aligned(8))) WG_IOCTL_INTERFACE;
-#define WG_IOCTL_GET CTL_CODE(45208U, 321, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
-#define WG_IOCTL_SET CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
-
-#define DEVPKEY_WG_NAME (DEVPROPKEY) { \
- { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, \
- DEVPROPID_FIRST_USABLE + 1 \
- }
+#define WG_IOCTL_GET \
+ CTL_CODE(45208U, 321, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define WG_IOCTL_SET \
+ CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define DEVPKEY_WG_NAME \
+ (DEVPROPKEY){ \
+ {0x65726957, 0x7547, 0x7261, {0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79}}, \
+ DEVPROPID_FIRST_USABLE + 1}
#endif