From 71219488c11aa63636c8d4f231dbd72d2d31ac8e Mon Sep 17 00:00:00 2001
From: Mark Puha
Date: Thu, 12 Jun 2025 20:15:01 +0200
Subject: [PATCH] feat: first batch of awg-1.5
---
contrib/embeddable-wg-library/wireguard.c | 9 +
src/config.c | 135 ++-
src/containers.h | 248 +++--
src/ipc-linux.h | 1202 ++++++++++++---------
src/showconf.c | 19 +
src/uapi/linux/linux/wireguard.h | 9 +
6 files changed, 990 insertions(+), 632 deletions(-)
diff --git a/contrib/embeddable-wg-library/wireguard.c b/contrib/embeddable-wg-library/wireguard.c
index 500f33d..0ba767b 100644
--- a/contrib/embeddable-wg-library/wireguard.c
+++ b/contrib/embeddable-wg-library/wireguard.c
@@ -57,6 +57,15 @@ enum wgdevice_attribute {
WGDEVICE_A_H2,
WGDEVICE_A_H3,
WGDEVICE_A_H4,
+ WGDEVICE_A_I1,
+ WGDEVICE_A_I2,
+ WGDEVICE_A_I3,
+ WGDEVICE_A_I4,
+ WGDEVICE_A_I5,
+ WGDEVICE_A_J1,
+ WGDEVICE_A_J2,
+ WGDEVICE_A_J3,
+ WGDEVICE_A_ITIME,
__WGDEVICE_A_LAST
};
diff --git a/src/config.c b/src/config.c
index f663b7d..6801840 100644
--- a/src/config.c
+++ b/src/config.c
@@ -410,13 +410,29 @@ err:
return false;
}
+static inline bool parse_string(char **device_value, const char *name, const char *value) {
+ size_t len = strlen(value);
+ if (!len) {
+ fprintf(stderr, "Unable to parse empty string for: %s\n", name);
+ return false;
+ }
+
+ if( len >= MAX_AWG_JUNK_LEN) {
+ fprintf(stderr, "Unable to process hex string longer than: %d\n", MAX_AWG_JUNK_LEN);
+ return false;
+ }
+ *device_value = strdup(value);
+
+ return true;
+}
+
static inline bool parse_uint16(uint16_t *device_value, const char *name, const char *value) {
if (!strlen(value)) {
fprintf(stderr, "Unable to parse empty string\n");
return false;
}
-
+
char *end;
uint32_t ret;
ret = strtoul(value, &end, 10);
@@ -558,6 +574,42 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_uint32(&ctx->device->transport_packet_magic_header, "H4", value);
if (ret)
ctx->device->flags |= WGDEVICE_HAS_H4;
+ } else if (key_match("I1")) {
+ ret = parse_string(&ctx->device->i1, "I1", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_I1;
+ } else if (key_match("I2")) {
+ ret = parse_string(&ctx->device->i2, "I2", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_I2;
+ } else if (key_match("I3")) {
+ ret = parse_string(&ctx->device->i3, "I3", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_I3;
+ } else if (key_match("I4")) {
+ ret = parse_string(&ctx->device->i4, "I4", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_I4;
+ } else if (key_match("I5")) {
+ ret = parse_string(&ctx->device->i5, "I5", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_I5;
+ } else if (key_match("J1")) {
+ ret = parse_string(&ctx->device->j1, "J1", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_J1;
+ } else if (key_match("J2")) {
+ ret = parse_string(&ctx->device->j2, "J2", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_J2;
+ } else if (key_match("J3")) {
+ ret = parse_string(&ctx->device->j3, "J3", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_J3;
+ } else if (key_match("ITIME")) {
+ ret = parse_string(&ctx->device->itime, "Itime", value);
+ if (ret)
+ ctx->device->flags |= WGDEVICE_HAS_ITIME;
} else
goto error;
} else if (ctx->is_peer_section) {
@@ -703,66 +755,129 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
} else if (!strcmp(argv[0], "jc") && argc >= 2 && !peer) {
if (!parse_uint16(&device->junk_packet_count, "jc", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_JC;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "jmin") && argc >= 2 && !peer) {
if (!parse_uint16(&device->junk_packet_min_size, "jmin", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_JMIN;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "jmax") && argc >= 2 && !peer) {
if (!parse_uint16(&device->junk_packet_max_size, "jmax", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_JMAX;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "s1") && argc >= 2 && !peer) {
if (!parse_uint16(&device->init_packet_junk_size, "s1", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_S1;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "s2") && argc >= 2 && !peer) {
if (!parse_uint16(&device->response_packet_junk_size, "s2", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_S2;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "h1") && argc >= 2 && !peer) {
if (!parse_uint32(&device->init_packet_magic_header, "h1", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_H1;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "h2") && argc >= 2 && !peer) {
if (!parse_uint32(&device->response_packet_magic_header, "h2", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_H2;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "h3") && argc >= 2 && !peer) {
if (!parse_uint32(&device->underload_packet_magic_header, "h3", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_H3;
argv += 2;
argc -= 2;
} else if (!strcmp(argv[0], "h4") && argc >= 2 && !peer) {
if (!parse_uint32(&device->transport_packet_magic_header, "h4", argv[1]))
goto error;
-
+
device->flags |= WGDEVICE_HAS_H4;
argv += 2;
argc -= 2;
+ } else if (!strcmp(argv[0], "i1") && argc >= 2 && !peer) {
+ if (!parse_string(&device->i1, "i1", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_I1;
+ argv += 2;
+ argc -= 2;
+ } else if (!strcmp(argv[0], "i2") && argc >= 2 && !peer) {
+ if (!parse_string(&device->i2, "i2", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_I2;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "i3") && argc >= 2 && !peer) {
+ if (!parse_string(&device->i3, "i3", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_I3;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "i4") && argc >= 2 && !peer) {
+ if (!parse_string(&device->i4, "i4", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_I4;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "i5") && argc >= 2 && !peer) {
+ if (!parse_string(&device->i5, "i5", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_I5;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "j1") && argc >= 2 && !peer) {
+ if (!parse_string(&device->j1, "j1", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_J1;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "j2") && argc >= 2 && !peer) {
+ if (!parse_string(&device->j2, "j2", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_J2;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "j3") && argc >= 2 && !peer) {
+ if (!parse_string(&device->j3, "j3", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_J3;
+ argv += 2;
+ argc -=2;
+ } else if (!strcmp(argv[0], "itime") && argc >= 2 && !peer) {
+ if (!parse_string(&device->itime, "itime", argv[1]))
+ goto error;
+
+ device->flags |= WGDEVICE_HAS_ITIME;
+ argv += 2;
+ argc -=2;
} else if (!strcmp(argv[0], "peer") && argc >= 2) {
struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
diff --git a/src/containers.h b/src/containers.h
index 8f93bb5..d6589e0 100644
--- a/src/containers.h
+++ b/src/containers.h
@@ -6,13 +6,13 @@
#ifndef CONTAINERS_H
#define CONTAINERS_H
-#include
-#include
-#include
-#include
-#include
#include
#include
+#include
+#include
+#include
+#include
+#include
#if defined(__linux__)
#include
#elif defined(__OpenBSD__)
@@ -23,108 +23,146 @@
#define WG_KEY_LEN 32
#endif
+#ifndef MAX_AWG_JUNK_LEN
+#define MAX_AWG_JUNK_LEN 5 * 1024
+#endif
+
/* Cross platform __kernel_timespec */
-struct timespec64 {
- int64_t tv_sec;
- int64_t tv_nsec;
-};
-
-struct wgallowedip {
- uint16_t family;
- union {
- struct in_addr ip4;
- struct in6_addr ip6;
- };
- uint8_t cidr;
- struct wgallowedip *next_allowedip;
-};
-
-enum {
- WGPEER_REMOVE_ME = 1U << 0,
- WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
- 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
-};
-
-struct wgpeer {
- uint32_t flags;
-
- uint8_t public_key[WG_KEY_LEN];
- uint8_t preshared_key[WG_KEY_LEN];
-
- union {
- struct sockaddr addr;
- struct sockaddr_in addr4;
- struct sockaddr_in6 addr6;
- } endpoint;
-
- struct timespec64 last_handshake_time;
- uint64_t rx_bytes, tx_bytes;
- uint16_t persistent_keepalive_interval;
-
- bool advanced_security;
-
- struct wgallowedip *first_allowedip, *last_allowedip;
- struct wgpeer *next_peer;
-};
-
-enum {
- WGDEVICE_REPLACE_PEERS = 1U << 0,
- WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
- WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
- WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
- WGDEVICE_HAS_FWMARK = 1U << 4,
- WGDEVICE_HAS_JC = 1U << 5,
- WGDEVICE_HAS_JMIN = 1U << 6,
- WGDEVICE_HAS_JMAX = 1U << 7,
- WGDEVICE_HAS_S1 = 1U << 8,
- WGDEVICE_HAS_S2 = 1U << 9,
- WGDEVICE_HAS_H1 = 1U << 10,
- WGDEVICE_HAS_H2 = 1U << 11,
- WGDEVICE_HAS_H3 = 1U << 12,
- WGDEVICE_HAS_H4 = 1U << 13
-};
-
-struct wgdevice {
- char name[IFNAMSIZ];
- uint32_t ifindex;
-
- uint32_t flags;
-
- uint8_t public_key[WG_KEY_LEN];
- uint8_t private_key[WG_KEY_LEN];
-
- uint32_t fwmark;
- uint16_t listen_port;
-
- struct wgpeer *first_peer, *last_peer;
-
- uint16_t junk_packet_count;
- uint16_t junk_packet_min_size;
- uint16_t junk_packet_max_size;
- uint16_t init_packet_junk_size;
- uint16_t response_packet_junk_size;
- uint32_t init_packet_magic_header;
- uint32_t response_packet_magic_header;
- uint32_t underload_packet_magic_header;
- uint32_t transport_packet_magic_header;
-};
-
-#define for_each_wgpeer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
-#define for_each_wgallowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)
-
-static inline void free_wgdevice(struct wgdevice *dev)
+struct timespec64
{
- if (!dev)
- return;
- for (struct wgpeer *peer = dev->first_peer, *np = peer ? peer->next_peer : NULL; peer; peer = np, np = peer ? peer->next_peer : NULL) {
- for (struct wgallowedip *allowedip = peer->first_allowedip, *na = allowedip ? allowedip->next_allowedip : NULL; allowedip; allowedip = na, na = allowedip ? allowedip->next_allowedip : NULL)
- free(allowedip);
- free(peer);
- }
- free(dev);
+ int64_t tv_sec;
+ int64_t tv_nsec;
+};
+
+struct wgallowedip
+{
+ uint16_t family;
+ union
+ {
+ struct in_addr ip4;
+ struct in6_addr ip6;
+ };
+ uint8_t cidr;
+ struct wgallowedip* next_allowedip;
+};
+
+enum
+{
+ WGPEER_REMOVE_ME = 1U << 0,
+ WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
+ 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
+};
+
+struct wgpeer
+{
+ uint32_t flags;
+
+ uint8_t public_key[WG_KEY_LEN];
+ uint8_t preshared_key[WG_KEY_LEN];
+
+ union
+ {
+ struct sockaddr addr;
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ } endpoint;
+
+ struct timespec64 last_handshake_time;
+ uint64_t rx_bytes, tx_bytes;
+ uint16_t persistent_keepalive_interval;
+
+ bool advanced_security;
+
+ struct wgallowedip *first_allowedip, *last_allowedip;
+ struct wgpeer* next_peer;
+};
+
+enum
+{
+ WGDEVICE_REPLACE_PEERS = 1U << 0,
+ WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
+ WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
+ WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
+ WGDEVICE_HAS_FWMARK = 1U << 4,
+ WGDEVICE_HAS_JC = 1U << 5,
+ WGDEVICE_HAS_JMIN = 1U << 6,
+ WGDEVICE_HAS_JMAX = 1U << 7,
+ WGDEVICE_HAS_S1 = 1U << 8,
+ WGDEVICE_HAS_S2 = 1U << 9,
+ WGDEVICE_HAS_H1 = 1U << 10,
+ WGDEVICE_HAS_H2 = 1U << 11,
+ WGDEVICE_HAS_H3 = 1U << 12,
+ WGDEVICE_HAS_H4 = 1U << 13,
+ WGDEVICE_HAS_I1 = 1U << 14,
+ WGDEVICE_HAS_I2 = 1U << 15,
+ WGDEVICE_HAS_I3 = 1U << 16,
+ WGDEVICE_HAS_I4 = 1U << 17,
+ WGDEVICE_HAS_I5 = 1U << 18,
+ WGDEVICE_HAS_J1 = 1U << 19,
+ WGDEVICE_HAS_J2 = 1U << 20,
+ WGDEVICE_HAS_J3 = 1U << 21,
+ WGDEVICE_HAS_ITIME = 1U << 22
+};
+
+struct wgdevice
+{
+ char name[IFNAMSIZ];
+ uint32_t ifindex;
+
+ uint32_t flags;
+
+ uint8_t public_key[WG_KEY_LEN];
+ uint8_t private_key[WG_KEY_LEN];
+
+ uint32_t fwmark;
+ uint16_t listen_port;
+
+ struct wgpeer *first_peer, *last_peer;
+
+ uint16_t junk_packet_count;
+ uint16_t junk_packet_min_size;
+ uint16_t junk_packet_max_size;
+ uint16_t init_packet_junk_size;
+ uint16_t response_packet_junk_size;
+ uint32_t init_packet_magic_header;
+ uint32_t response_packet_magic_header;
+ uint32_t underload_packet_magic_header;
+ uint32_t transport_packet_magic_header;
+ char* i1;
+ char* i2;
+ char* i3;
+ char* i4;
+ char* i5;
+ char* j1;
+ char* j2;
+ char* j3;
+ char* itime;
+};
+
+#define for_each_wgpeer(__dev, __peer) \
+ for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
+#define for_each_wgallowedip(__peer, __allowedip) \
+ for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); \
+ (__allowedip) = (__allowedip)->next_allowedip)
+
+static inline void free_wgdevice(struct wgdevice* dev)
+{
+ if (!dev)
+ return;
+ for (struct wgpeer *peer = dev->first_peer, *np = peer ? peer->next_peer : NULL; peer;
+ peer = np, np = peer ? peer->next_peer : NULL)
+ {
+ for (struct wgallowedip *allowedip = peer->first_allowedip,
+ *na = allowedip ? allowedip->next_allowedip : NULL;
+ allowedip;
+ allowedip = na, na = allowedip ? allowedip->next_allowedip : NULL)
+ free(allowedip);
+ free(peer);
+ }
+ free(dev);
}
#endif
diff --git a/src/ipc-linux.h b/src/ipc-linux.h
index c6d9847..a385f06 100644
--- a/src/ipc-linux.h
+++ b/src/ipc-linux.h
@@ -3,619 +3,787 @@
* Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved.
*/
-#include
-#include
-#include
-#include
-#include
+#include "containers.h"
+#include "encoding.h"
+#include "netlink.h"
#include
-#include
-#include
-#include
-#include
#include
#include
#include
#include
#include
#include
-#include "containers.h"
-#include "encoding.h"
-#include "netlink.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#define IPC_SUPPORTS_KERNEL_INTERFACE
#define SOCKET_BUFFER_SIZE (mnl_ideal_socket_buffer_size())
-struct interface {
- const char *name;
- bool is_wireguard;
+struct interface
+{
+ const char* name;
+ bool is_wireguard;
};
-static int parse_linkinfo(const struct nlattr *attr, void *data)
+static int parse_linkinfo(const struct nlattr* attr, void* data)
{
- struct interface *interface = data;
+ struct interface* interface = data;
- if (mnl_attr_get_type(attr) == IFLA_INFO_KIND && !strcmp(WG_GENL_NAME, mnl_attr_get_str(attr)))
- interface->is_wireguard = true;
- return MNL_CB_OK;
+ if (mnl_attr_get_type(attr) == IFLA_INFO_KIND &&
+ !strcmp(WG_GENL_NAME, mnl_attr_get_str(attr)))
+ interface->is_wireguard = true;
+ return MNL_CB_OK;
}
-static int parse_infomsg(const struct nlattr *attr, void *data)
+static int parse_infomsg(const struct nlattr* attr, void* data)
{
- struct interface *interface = data;
+ struct interface* interface = data;
- if (mnl_attr_get_type(attr) == IFLA_LINKINFO)
- return mnl_attr_parse_nested(attr, parse_linkinfo, data);
- else if (mnl_attr_get_type(attr) == IFLA_IFNAME)
- interface->name = mnl_attr_get_str(attr);
- return MNL_CB_OK;
+ if (mnl_attr_get_type(attr) == IFLA_LINKINFO)
+ return mnl_attr_parse_nested(attr, parse_linkinfo, data);
+ else if (mnl_attr_get_type(attr) == IFLA_IFNAME)
+ interface->name = mnl_attr_get_str(attr);
+ return MNL_CB_OK;
}
-static int read_devices_cb(const struct nlmsghdr *nlh, void *data)
+static int read_devices_cb(const struct nlmsghdr* nlh, void* data)
{
- struct string_list *list = data;
- struct interface interface = { 0 };
- int ret;
+ struct string_list* list = data;
+ struct interface interface = {0};
+ int ret;
- ret = mnl_attr_parse(nlh, sizeof(struct ifinfomsg), parse_infomsg, &interface);
- if (ret != MNL_CB_OK)
- return ret;
- if (interface.name && interface.is_wireguard)
- ret = string_list_add(list, interface.name);
- if (ret < 0)
- return ret;
- if (nlh->nlmsg_type != NLMSG_DONE)
- return MNL_CB_OK + 1;
- return MNL_CB_OK;
+ ret = mnl_attr_parse(nlh, sizeof(struct ifinfomsg), parse_infomsg, &interface);
+ if (ret != MNL_CB_OK)
+ return ret;
+ if (interface.name && interface.is_wireguard)
+ ret = string_list_add(list, interface.name);
+ if (ret < 0)
+ return ret;
+ if (nlh->nlmsg_type != NLMSG_DONE)
+ return MNL_CB_OK + 1;
+ return MNL_CB_OK;
}
-static int kernel_get_wireguard_interfaces(struct string_list *list)
+static int kernel_get_wireguard_interfaces(struct string_list* list)
{
- struct mnl_socket *nl = NULL;
- char *rtnl_buffer = NULL;
- size_t message_len;
- unsigned int portid, seq;
- ssize_t len;
- int ret = 0;
- struct nlmsghdr *nlh;
- struct ifinfomsg *ifm;
+ struct mnl_socket* nl = NULL;
+ char* rtnl_buffer = NULL;
+ size_t message_len;
+ unsigned int portid, seq;
+ ssize_t len;
+ int ret = 0;
+ struct nlmsghdr* nlh;
+ struct ifinfomsg* ifm;
- ret = -ENOMEM;
- rtnl_buffer = calloc(SOCKET_BUFFER_SIZE, 1);
- if (!rtnl_buffer)
- goto cleanup;
+ ret = -ENOMEM;
+ rtnl_buffer = calloc(SOCKET_BUFFER_SIZE, 1);
+ if (!rtnl_buffer)
+ goto cleanup;
- nl = mnl_socket_open(NETLINK_ROUTE);
- if (!nl) {
- ret = -errno;
- goto cleanup;
- }
+ nl = mnl_socket_open(NETLINK_ROUTE);
+ if (!nl)
+ {
+ ret = -errno;
+ goto cleanup;
+ }
- if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
- ret = -errno;
- goto cleanup;
- }
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
+ {
+ ret = -errno;
+ goto cleanup;
+ }
- seq = time(NULL);
- portid = mnl_socket_get_portid(nl);
- nlh = mnl_nlmsg_put_header(rtnl_buffer);
- nlh->nlmsg_type = RTM_GETLINK;
- nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
- nlh->nlmsg_seq = seq;
- ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
- ifm->ifi_family = AF_UNSPEC;
- message_len = nlh->nlmsg_len;
+ seq = time(NULL);
+ portid = mnl_socket_get_portid(nl);
+ nlh = mnl_nlmsg_put_header(rtnl_buffer);
+ nlh->nlmsg_type = RTM_GETLINK;
+ nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP;
+ nlh->nlmsg_seq = seq;
+ ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
+ ifm->ifi_family = AF_UNSPEC;
+ message_len = nlh->nlmsg_len;
- if (mnl_socket_sendto(nl, rtnl_buffer, message_len) < 0) {
- ret = -errno;
- goto cleanup;
- }
+ if (mnl_socket_sendto(nl, rtnl_buffer, message_len) < 0)
+ {
+ ret = -errno;
+ goto cleanup;
+ }
another:
- if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, SOCKET_BUFFER_SIZE)) < 0) {
- ret = -errno;
- goto cleanup;
- }
- if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, list)) < 0) {
- /* Netlink returns NLM_F_DUMP_INTR if the set of all tunnels changed
+ if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, SOCKET_BUFFER_SIZE)) < 0)
+ {
+ ret = -errno;
+ goto cleanup;
+ }
+ if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, list)) < 0)
+ {
+ /* Netlink returns NLM_F_DUMP_INTR if the set of all tunnels changed
* during the dump. That's unfortunate, but is pretty common on busy
* systems that are adding and removing tunnels all the time. Rather
* than retrying, potentially indefinitely, we just work with the
* partial results. */
- if (errno != EINTR) {
- ret = -errno;
- goto cleanup;
- }
- }
- if (len == MNL_CB_OK + 1)
- goto another;
- ret = 0;
+ if (errno != EINTR)
+ {
+ ret = -errno;
+ goto cleanup;
+ }
+ }
+ if (len == MNL_CB_OK + 1)
+ goto another;
+ ret = 0;
cleanup:
- free(rtnl_buffer);
- if (nl)
- mnl_socket_close(nl);
- return ret;
+ free(rtnl_buffer);
+ if (nl)
+ mnl_socket_close(nl);
+ return ret;
}
-static int kernel_set_device(struct wgdevice *dev)
+static int kernel_set_device(struct wgdevice* dev)
{
- int ret = 0;
- struct wgpeer *peer = NULL;
- struct wgallowedip *allowedip = NULL;
- struct nlattr *peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
- struct nlmsghdr *nlh;
- struct mnlg_socket *nlg;
+ int ret = 0;
+ struct wgpeer* peer = NULL;
+ struct wgallowedip* allowedip = NULL;
+ struct nlattr * peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
+ struct nlmsghdr* nlh;
+ struct mnlg_socket* nlg;
- nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
- if (!nlg)
- return -errno;
+ nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
+ if (!nlg)
+ return -errno;
again:
- nlh = mnlg_msg_prepare(nlg, WG_CMD_SET_DEVICE, NLM_F_REQUEST | NLM_F_ACK);
- mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, dev->name);
+ nlh = mnlg_msg_prepare(nlg, WG_CMD_SET_DEVICE, NLM_F_REQUEST | NLM_F_ACK);
+ mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, dev->name);
- if (!peer) {
- uint32_t flags = 0;
+ if (!peer)
+ {
+ uint32_t flags = 0;
- if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
- mnl_attr_put(nlh, WGDEVICE_A_PRIVATE_KEY, sizeof(dev->private_key), dev->private_key);
- if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
- mnl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, dev->listen_port);
- if (dev->flags & WGDEVICE_HAS_JC)
- mnl_attr_put_u16(nlh, WGDEVICE_A_JC, dev->junk_packet_count);
- if (dev->flags & WGDEVICE_HAS_JMIN)
- mnl_attr_put_u16(nlh, WGDEVICE_A_JMIN, dev->junk_packet_min_size);
- if (dev->flags & WGDEVICE_HAS_JMAX)
- mnl_attr_put_u16(nlh, WGDEVICE_A_JMAX, dev->junk_packet_max_size);
- if (dev->flags & WGDEVICE_HAS_S1)
- mnl_attr_put_u16(nlh, WGDEVICE_A_S1, dev->init_packet_junk_size);
- if (dev->flags & WGDEVICE_HAS_S2)
- mnl_attr_put_u16(nlh, WGDEVICE_A_S2, dev->response_packet_junk_size);
- if (dev->flags & WGDEVICE_HAS_H1)
- mnl_attr_put_u32(nlh, WGDEVICE_A_H1, dev->init_packet_magic_header);
- if (dev->flags & WGDEVICE_HAS_H2)
- mnl_attr_put_u32(nlh, WGDEVICE_A_H2, dev->response_packet_magic_header);
- if (dev->flags & WGDEVICE_HAS_H3)
- 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_FWMARK)
- mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
- if (dev->flags & WGDEVICE_REPLACE_PEERS)
- flags |= WGDEVICE_F_REPLACE_PEERS;
- if (flags)
- mnl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, flags);
- }
- if (!dev->first_peer)
- goto send;
- peers_nest = peer_nest = allowedips_nest = allowedip_nest = NULL;
- peers_nest = mnl_attr_nest_start(nlh, WGDEVICE_A_PEERS);
- for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer) {
- uint32_t flags = 0;
+ if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
+ mnl_attr_put(
+ nlh, WGDEVICE_A_PRIVATE_KEY, sizeof(dev->private_key), dev->private_key);
+ if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, dev->listen_port);
+ if (dev->flags & WGDEVICE_HAS_JC)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_JC, dev->junk_packet_count);
+ if (dev->flags & WGDEVICE_HAS_JMIN)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_JMIN, dev->junk_packet_min_size);
+ if (dev->flags & WGDEVICE_HAS_JMAX)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_JMAX, dev->junk_packet_max_size);
+ if (dev->flags & WGDEVICE_HAS_S1)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_S1, dev->init_packet_junk_size);
+ if (dev->flags & WGDEVICE_HAS_S2)
+ mnl_attr_put_u16(nlh, WGDEVICE_A_S2, dev->response_packet_junk_size);
+ if (dev->flags & WGDEVICE_HAS_H1)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_H1, dev->init_packet_magic_header);
+ if (dev->flags & WGDEVICE_HAS_H2)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_H2, dev->response_packet_magic_header);
+ if (dev->flags & WGDEVICE_HAS_H3)
+ 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_FWMARK)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
+ if (dev->flags & WGDEVICE_REPLACE_PEERS)
+ flags |= WGDEVICE_F_REPLACE_PEERS;
+ if (flags)
+ mnl_attr_put_u32(nlh, WGDEVICE_A_FLAGS, flags);
+ }
+ if (!dev->first_peer)
+ goto send;
+ peers_nest = peer_nest = allowedips_nest = allowedip_nest = NULL;
+ peers_nest = mnl_attr_nest_start(nlh, WGDEVICE_A_PEERS);
+ for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer)
+ {
+ uint32_t flags = 0;
- peer_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
- if (!peer_nest)
- goto toobig_peers;
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PUBLIC_KEY, sizeof(peer->public_key), peer->public_key))
- goto toobig_peers;
- if (peer->flags & WGPEER_REMOVE_ME)
- flags |= WGPEER_F_REMOVE_ME;
- if (!allowedip) {
- if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
- flags |= WGPEER_F_REPLACE_ALLOWEDIPS;
- if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PRESHARED_KEY, sizeof(peer->preshared_key), peer->preshared_key))
- goto toobig_peers;
- }
- if (peer->endpoint.addr.sa_family == AF_INET) {
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr4), &peer->endpoint.addr4))
- goto toobig_peers;
- } else if (peer->endpoint.addr.sa_family == AF_INET6) {
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr6), &peer->endpoint.addr6))
- goto toobig_peers;
- }
- if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
- if (!mnl_attr_put_u16_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval))
- goto toobig_peers;
- }
- }
- if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
- if (peer->advanced_security)
- mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
- flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
- }
- if (flags) {
- if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
- goto toobig_peers;
- }
- if (peer->first_allowedip) {
- if (!allowedip)
- allowedip = peer->first_allowedip;
- allowedips_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ALLOWEDIPS);
- if (!allowedips_nest)
- goto toobig_allowedips;
- for (; allowedip; allowedip = allowedip->next_allowedip) {
- allowedip_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
- if (!allowedip_nest)
- goto toobig_allowedips;
- if (!mnl_attr_put_u16_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FAMILY, allowedip->family))
- goto toobig_allowedips;
- if (allowedip->family == AF_INET) {
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip4), &allowedip->ip4))
- goto toobig_allowedips;
- } else if (allowedip->family == AF_INET6) {
- if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip6), &allowedip->ip6))
- goto toobig_allowedips;
- }
- if (!mnl_attr_put_u8_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_CIDR_MASK, allowedip->cidr))
- goto toobig_allowedips;
- mnl_attr_nest_end(nlh, allowedip_nest);
- allowedip_nest = NULL;
- }
- mnl_attr_nest_end(nlh, allowedips_nest);
- allowedips_nest = NULL;
- }
+ peer_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
+ if (!peer_nest)
+ goto toobig_peers;
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGPEER_A_PUBLIC_KEY,
+ sizeof(peer->public_key),
+ peer->public_key))
+ goto toobig_peers;
+ if (peer->flags & WGPEER_REMOVE_ME)
+ flags |= WGPEER_F_REMOVE_ME;
+ if (!allowedip)
+ {
+ if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
+ flags |= WGPEER_F_REPLACE_ALLOWEDIPS;
+ if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
+ {
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGPEER_A_PRESHARED_KEY,
+ sizeof(peer->preshared_key),
+ peer->preshared_key))
+ goto toobig_peers;
+ }
+ if (peer->endpoint.addr.sa_family == AF_INET)
+ {
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGPEER_A_ENDPOINT,
+ sizeof(peer->endpoint.addr4),
+ &peer->endpoint.addr4))
+ goto toobig_peers;
+ }
+ else if (peer->endpoint.addr.sa_family == AF_INET6)
+ {
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGPEER_A_ENDPOINT,
+ sizeof(peer->endpoint.addr6),
+ &peer->endpoint.addr6))
+ goto toobig_peers;
+ }
+ if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
+ {
+ if (!mnl_attr_put_u16_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
+ peer->persistent_keepalive_interval))
+ goto toobig_peers;
+ }
+ }
+ if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY)
+ {
+ if (peer->advanced_security)
+ mnl_attr_put_check(
+ nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
+ flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
+ }
+ if (flags)
+ {
+ if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
+ goto toobig_peers;
+ }
+ if (peer->first_allowedip)
+ {
+ if (!allowedip)
+ allowedip = peer->first_allowedip;
+ allowedips_nest =
+ mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ALLOWEDIPS);
+ if (!allowedips_nest)
+ goto toobig_allowedips;
+ for (; allowedip; allowedip = allowedip->next_allowedip)
+ {
+ allowedip_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
+ if (!allowedip_nest)
+ goto toobig_allowedips;
+ if (!mnl_attr_put_u16_check(
+ nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FAMILY, allowedip->family))
+ goto toobig_allowedips;
+ if (allowedip->family == AF_INET)
+ {
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGALLOWEDIP_A_IPADDR,
+ sizeof(allowedip->ip4),
+ &allowedip->ip4))
+ goto toobig_allowedips;
+ }
+ else if (allowedip->family == AF_INET6)
+ {
+ if (!mnl_attr_put_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGALLOWEDIP_A_IPADDR,
+ sizeof(allowedip->ip6),
+ &allowedip->ip6))
+ goto toobig_allowedips;
+ }
+ if (!mnl_attr_put_u8_check(
+ nlh,
+ SOCKET_BUFFER_SIZE,
+ WGALLOWEDIP_A_CIDR_MASK,
+ allowedip->cidr))
+ goto toobig_allowedips;
+ mnl_attr_nest_end(nlh, allowedip_nest);
+ allowedip_nest = NULL;
+ }
+ mnl_attr_nest_end(nlh, allowedips_nest);
+ allowedips_nest = NULL;
+ }
- mnl_attr_nest_end(nlh, peer_nest);
- peer_nest = NULL;
- }
- mnl_attr_nest_end(nlh, peers_nest);
- peers_nest = NULL;
- goto send;
+ mnl_attr_nest_end(nlh, peer_nest);
+ peer_nest = NULL;
+ }
+ mnl_attr_nest_end(nlh, peers_nest);
+ peers_nest = NULL;
+ goto send;
toobig_allowedips:
- if (allowedip_nest)
- mnl_attr_nest_cancel(nlh, allowedip_nest);
- if (allowedips_nest)
- mnl_attr_nest_end(nlh, allowedips_nest);
- mnl_attr_nest_end(nlh, peer_nest);
- mnl_attr_nest_end(nlh, peers_nest);
- goto send;
+ if (allowedip_nest)
+ mnl_attr_nest_cancel(nlh, allowedip_nest);
+ if (allowedips_nest)
+ mnl_attr_nest_end(nlh, allowedips_nest);
+ mnl_attr_nest_end(nlh, peer_nest);
+ mnl_attr_nest_end(nlh, peers_nest);
+ goto send;
toobig_peers:
- if (peer_nest)
- mnl_attr_nest_cancel(nlh, peer_nest);
- mnl_attr_nest_end(nlh, peers_nest);
- goto send;
+ if (peer_nest)
+ mnl_attr_nest_cancel(nlh, peer_nest);
+ mnl_attr_nest_end(nlh, peers_nest);
+ goto send;
send:
- if (mnlg_socket_send(nlg, nlh) < 0) {
- ret = -errno;
- goto out;
- }
- errno = 0;
- if (mnlg_socket_recv_run(nlg, NULL, NULL) < 0) {
- ret = errno ? -errno : -EINVAL;
- goto out;
- }
- if (peer)
- goto again;
+ if (mnlg_socket_send(nlg, nlh) < 0)
+ {
+ ret = -errno;
+ goto out;
+ }
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, NULL, NULL) < 0)
+ {
+ ret = errno ? -errno : -EINVAL;
+ goto out;
+ }
+ if (peer)
+ goto again;
out:
- mnlg_socket_close(nlg);
- errno = -ret;
- return ret;
+ mnlg_socket_close(nlg);
+ errno = -ret;
+ return ret;
}
-static int parse_allowedip(const struct nlattr *attr, void *data)
+static int parse_allowedip(const struct nlattr* attr, void* data)
{
- struct wgallowedip *allowedip = data;
+ struct wgallowedip* allowedip = data;
- switch (mnl_attr_get_type(attr)) {
- case WGALLOWEDIP_A_UNSPEC:
- break;
- case WGALLOWEDIP_A_FAMILY:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16))
- allowedip->family = mnl_attr_get_u16(attr);
- break;
- case WGALLOWEDIP_A_IPADDR:
- if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip4))
- memcpy(&allowedip->ip4, mnl_attr_get_payload(attr), sizeof(allowedip->ip4));
- else if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip6))
- memcpy(&allowedip->ip6, mnl_attr_get_payload(attr), sizeof(allowedip->ip6));
- break;
- case WGALLOWEDIP_A_CIDR_MASK:
- if (!mnl_attr_validate(attr, MNL_TYPE_U8))
- allowedip->cidr = mnl_attr_get_u8(attr);
- break;
- }
+ switch (mnl_attr_get_type(attr))
+ {
+ case WGALLOWEDIP_A_UNSPEC:
+ break;
+ case WGALLOWEDIP_A_FAMILY:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ allowedip->family = mnl_attr_get_u16(attr);
+ break;
+ case WGALLOWEDIP_A_IPADDR:
+ if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip4))
+ memcpy(&allowedip->ip4, mnl_attr_get_payload(attr), sizeof(allowedip->ip4));
+ else if (mnl_attr_get_payload_len(attr) == sizeof(allowedip->ip6))
+ memcpy(&allowedip->ip6, mnl_attr_get_payload(attr), sizeof(allowedip->ip6));
+ break;
+ case WGALLOWEDIP_A_CIDR_MASK:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U8))
+ allowedip->cidr = mnl_attr_get_u8(attr);
+ break;
+ }
- return MNL_CB_OK;
+ return MNL_CB_OK;
}
-static int parse_allowedips(const struct nlattr *attr, void *data)
+static int parse_allowedips(const struct nlattr* attr, void* data)
{
- struct wgpeer *peer = data;
- struct wgallowedip *new_allowedip = calloc(1, sizeof(*new_allowedip));
- int ret;
+ struct wgpeer* peer = data;
+ struct wgallowedip* new_allowedip = calloc(1, sizeof(*new_allowedip));
+ int ret;
- if (!new_allowedip) {
- perror("calloc");
- return MNL_CB_ERROR;
- }
- if (!peer->first_allowedip)
- peer->first_allowedip = peer->last_allowedip = new_allowedip;
- else {
- peer->last_allowedip->next_allowedip = new_allowedip;
- peer->last_allowedip = new_allowedip;
- }
- ret = mnl_attr_parse_nested(attr, parse_allowedip, new_allowedip);
- if (!ret)
- return ret;
- if (!((new_allowedip->family == AF_INET && new_allowedip->cidr <= 32) || (new_allowedip->family == AF_INET6 && new_allowedip->cidr <= 128)))
- return MNL_CB_ERROR;
- return MNL_CB_OK;
+ if (!new_allowedip)
+ {
+ perror("calloc");
+ return MNL_CB_ERROR;
+ }
+ if (!peer->first_allowedip)
+ peer->first_allowedip = peer->last_allowedip = new_allowedip;
+ else
+ {
+ peer->last_allowedip->next_allowedip = new_allowedip;
+ peer->last_allowedip = new_allowedip;
+ }
+ ret = mnl_attr_parse_nested(attr, parse_allowedip, new_allowedip);
+ if (!ret)
+ return ret;
+ if (!((new_allowedip->family == AF_INET && new_allowedip->cidr <= 32) ||
+ (new_allowedip->family == AF_INET6 && new_allowedip->cidr <= 128)))
+ return MNL_CB_ERROR;
+ return MNL_CB_OK;
}
-static int parse_peer(const struct nlattr *attr, void *data)
+static int parse_peer(const struct nlattr* attr, void* data)
{
- struct wgpeer *peer = data;
+ struct wgpeer* peer = data;
- switch (mnl_attr_get_type(attr)) {
- case WGPEER_A_UNSPEC:
- break;
- case WGPEER_A_PUBLIC_KEY:
- if (mnl_attr_get_payload_len(attr) == sizeof(peer->public_key)) {
- memcpy(peer->public_key, mnl_attr_get_payload(attr), sizeof(peer->public_key));
- peer->flags |= WGPEER_HAS_PUBLIC_KEY;
- }
- break;
- case WGPEER_A_PRESHARED_KEY:
- if (mnl_attr_get_payload_len(attr) == sizeof(peer->preshared_key)) {
- memcpy(peer->preshared_key, mnl_attr_get_payload(attr), sizeof(peer->preshared_key));
- if (!key_is_zero(peer->preshared_key))
- peer->flags |= WGPEER_HAS_PRESHARED_KEY;
- }
- break;
- case WGPEER_A_ENDPOINT: {
- struct sockaddr *addr;
+ switch (mnl_attr_get_type(attr))
+ {
+ case WGPEER_A_UNSPEC:
+ break;
+ case WGPEER_A_PUBLIC_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->public_key))
+ {
+ memcpy(
+ peer->public_key, mnl_attr_get_payload(attr), sizeof(peer->public_key));
+ peer->flags |= WGPEER_HAS_PUBLIC_KEY;
+ }
+ break;
+ case WGPEER_A_PRESHARED_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->preshared_key))
+ {
+ memcpy(
+ peer->preshared_key,
+ mnl_attr_get_payload(attr),
+ sizeof(peer->preshared_key));
+ if (!key_is_zero(peer->preshared_key))
+ peer->flags |= WGPEER_HAS_PRESHARED_KEY;
+ }
+ break;
+ case WGPEER_A_ENDPOINT: {
+ struct sockaddr* addr;
- if (mnl_attr_get_payload_len(attr) < sizeof(*addr))
- break;
- addr = mnl_attr_get_payload(attr);
- if (addr->sa_family == AF_INET && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr4))
- memcpy(&peer->endpoint.addr4, addr, sizeof(peer->endpoint.addr4));
- else if (addr->sa_family == AF_INET6 && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr6))
- memcpy(&peer->endpoint.addr6, addr, sizeof(peer->endpoint.addr6));
- break;
- }
- case WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16))
- peer->persistent_keepalive_interval = mnl_attr_get_u16(attr);
- break;
- case WGPEER_A_LAST_HANDSHAKE_TIME:
- if (mnl_attr_get_payload_len(attr) == sizeof(peer->last_handshake_time))
- memcpy(&peer->last_handshake_time, mnl_attr_get_payload(attr), sizeof(peer->last_handshake_time));
- break;
- case WGPEER_A_RX_BYTES:
- if (!mnl_attr_validate(attr, MNL_TYPE_U64))
- peer->rx_bytes = mnl_attr_get_u64(attr);
- break;
- case WGPEER_A_TX_BYTES:
- if (!mnl_attr_validate(attr, MNL_TYPE_U64))
- peer->tx_bytes = mnl_attr_get_u64(attr);
- break;
- case WGPEER_A_FLAGS:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
- uint32_t flags = mnl_attr_get_u32(attr);
+ if (mnl_attr_get_payload_len(attr) < sizeof(*addr))
+ break;
+ addr = mnl_attr_get_payload(attr);
+ if (addr->sa_family == AF_INET &&
+ mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr4))
+ memcpy(&peer->endpoint.addr4, addr, sizeof(peer->endpoint.addr4));
+ else if (
+ addr->sa_family == AF_INET6 &&
+ mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr6))
+ memcpy(&peer->endpoint.addr6, addr, sizeof(peer->endpoint.addr6));
+ break;
+ }
+ case WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ peer->persistent_keepalive_interval = mnl_attr_get_u16(attr);
+ break;
+ case WGPEER_A_LAST_HANDSHAKE_TIME:
+ if (mnl_attr_get_payload_len(attr) == sizeof(peer->last_handshake_time))
+ memcpy(
+ &peer->last_handshake_time,
+ mnl_attr_get_payload(attr),
+ sizeof(peer->last_handshake_time));
+ break;
+ case WGPEER_A_RX_BYTES:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U64))
+ peer->rx_bytes = mnl_attr_get_u64(attr);
+ break;
+ case WGPEER_A_TX_BYTES:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U64))
+ peer->tx_bytes = mnl_attr_get_u64(attr);
+ break;
+ case WGPEER_A_FLAGS:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ {
+ uint32_t flags = mnl_attr_get_u32(attr);
- if (flags & WGPEER_F_HAS_ADVANCED_SECURITY && !(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
- peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
- peer->advanced_security = false;
- }
- }
- break;
- case WGPEER_A_ADVANCED_SECURITY:
- if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) {
- peer->advanced_security = true;
+ if (flags & WGPEER_F_HAS_ADVANCED_SECURITY &&
+ !(peer->flags & WGPEER_HAS_ADVANCED_SECURITY))
+ {
+ peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
+ peer->advanced_security = false;
+ }
+ }
+ break;
+ case WGPEER_A_ADVANCED_SECURITY:
+ if (!mnl_attr_validate(attr, MNL_TYPE_FLAG))
+ {
+ peer->advanced_security = true;
- if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
- peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
- }
- }
- break;
- case WGPEER_A_ALLOWEDIPS:
- return mnl_attr_parse_nested(attr, parse_allowedips, peer);
- }
+ if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY))
+ {
+ peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
+ }
+ }
+ break;
+ case WGPEER_A_ALLOWEDIPS:
+ return mnl_attr_parse_nested(attr, parse_allowedips, peer);
+ }
- return MNL_CB_OK;
+ return MNL_CB_OK;
}
-static int parse_peers(const struct nlattr *attr, void *data)
+static int parse_peers(const struct nlattr* attr, void* data)
{
- struct wgdevice *device = data;
- struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
- int ret;
+ struct wgdevice* device = data;
+ struct wgpeer* new_peer = calloc(1, sizeof(*new_peer));
+ int ret;
- if (!new_peer) {
- perror("calloc");
- return MNL_CB_ERROR;
- }
- if (!device->first_peer)
- device->first_peer = device->last_peer = new_peer;
- else {
- device->last_peer->next_peer = new_peer;
- device->last_peer = new_peer;
- }
- ret = mnl_attr_parse_nested(attr, parse_peer, new_peer);
- if (!ret)
- return ret;
- if (!(new_peer->flags & WGPEER_HAS_PUBLIC_KEY))
- return MNL_CB_ERROR;
- return MNL_CB_OK;
+ if (!new_peer)
+ {
+ perror("calloc");
+ return MNL_CB_ERROR;
+ }
+ if (!device->first_peer)
+ device->first_peer = device->last_peer = new_peer;
+ else
+ {
+ device->last_peer->next_peer = new_peer;
+ device->last_peer = new_peer;
+ }
+ ret = mnl_attr_parse_nested(attr, parse_peer, new_peer);
+ if (!ret)
+ return ret;
+ if (!(new_peer->flags & WGPEER_HAS_PUBLIC_KEY))
+ return MNL_CB_ERROR;
+ return MNL_CB_OK;
}
-static int parse_device(const struct nlattr *attr, void *data)
+static int parse_device(const struct nlattr* attr, void* data)
{
- struct wgdevice *device = data;
+ struct wgdevice* device = data;
- switch (mnl_attr_get_type(attr)) {
- case WGDEVICE_A_UNSPEC:
- break;
- case WGDEVICE_A_IFINDEX:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32))
- device->ifindex = mnl_attr_get_u32(attr);
- break;
- case WGDEVICE_A_IFNAME:
- if (!mnl_attr_validate(attr, MNL_TYPE_STRING)) {
- strncpy(device->name, mnl_attr_get_str(attr), sizeof(device->name) - 1);
- device->name[sizeof(device->name) - 1] = '\0';
- }
- break;
- case WGDEVICE_A_PRIVATE_KEY:
- if (mnl_attr_get_payload_len(attr) == sizeof(device->private_key)) {
- memcpy(device->private_key, mnl_attr_get_payload(attr), sizeof(device->private_key));
- device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
- }
- break;
- case WGDEVICE_A_PUBLIC_KEY:
- if (mnl_attr_get_payload_len(attr) == sizeof(device->public_key)) {
- memcpy(device->public_key, mnl_attr_get_payload(attr), sizeof(device->public_key));
- device->flags |= WGDEVICE_HAS_PUBLIC_KEY;
- }
- break;
- case WGDEVICE_A_LISTEN_PORT:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16))
- device->listen_port = mnl_attr_get_u16(attr);
- break;
- case WGDEVICE_A_FWMARK:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32))
- device->fwmark = mnl_attr_get_u32(attr);
- break;
- case WGDEVICE_A_PEERS:
- return mnl_attr_parse_nested(attr, parse_peers, device);
- case WGDEVICE_A_JC:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
- device->junk_packet_count = mnl_attr_get_u16(attr);
- device->flags |= WGDEVICE_HAS_JC;
- }
- break;
- case WGDEVICE_A_JMIN:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
- device->junk_packet_min_size = mnl_attr_get_u16(attr);
- device->flags |= WGDEVICE_HAS_JMIN;
- }
- break;
- case WGDEVICE_A_JMAX:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
- device->junk_packet_max_size = mnl_attr_get_u16(attr);
- device->flags |= WGDEVICE_HAS_JMAX;
- }
- break;
- case WGDEVICE_A_S1:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
- device->init_packet_junk_size = mnl_attr_get_u16(attr);
- device->flags |= WGDEVICE_HAS_S1;
- }
- break;
- case WGDEVICE_A_S2:
- if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
- device->response_packet_junk_size = mnl_attr_get_u16(attr);
- device->flags |= WGDEVICE_HAS_S2;
- }
- break;
- case WGDEVICE_A_H1:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
- device->init_packet_magic_header = mnl_attr_get_u32(attr);
- device->flags |= WGDEVICE_HAS_H1;
- }
- break;
- case WGDEVICE_A_H2:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
- device->response_packet_magic_header = mnl_attr_get_u32(attr);
- device->flags |= WGDEVICE_HAS_H2;
- }
- break;
- case WGDEVICE_A_H3:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
- device->underload_packet_magic_header = mnl_attr_get_u32(attr);
- device->flags |= WGDEVICE_HAS_H3;
- }
- break;
- case WGDEVICE_A_H4:
- if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
- device->transport_packet_magic_header = mnl_attr_get_u32(attr);
- device->flags |= WGDEVICE_HAS_H4;
- }
- break;
- }
+ switch (mnl_attr_get_type(attr))
+ {
+ case WGDEVICE_A_UNSPEC:
+ break;
+ case WGDEVICE_A_IFINDEX:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ device->ifindex = mnl_attr_get_u32(attr);
+ break;
+ case WGDEVICE_A_IFNAME:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
+ {
+ strncpy(device->name, mnl_attr_get_str(attr), sizeof(device->name) - 1);
+ device->name[sizeof(device->name) - 1] = '\0';
+ }
+ break;
+ case WGDEVICE_A_PRIVATE_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(device->private_key))
+ {
+ memcpy(
+ device->private_key,
+ mnl_attr_get_payload(attr),
+ sizeof(device->private_key));
+ device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
+ }
+ break;
+ case WGDEVICE_A_PUBLIC_KEY:
+ if (mnl_attr_get_payload_len(attr) == sizeof(device->public_key))
+ {
+ memcpy(
+ device->public_key,
+ mnl_attr_get_payload(attr),
+ sizeof(device->public_key));
+ device->flags |= WGDEVICE_HAS_PUBLIC_KEY;
+ }
+ break;
+ case WGDEVICE_A_LISTEN_PORT:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ device->listen_port = mnl_attr_get_u16(attr);
+ break;
+ case WGDEVICE_A_FWMARK:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ device->fwmark = mnl_attr_get_u32(attr);
+ break;
+ case WGDEVICE_A_PEERS:
+ return mnl_attr_parse_nested(attr, parse_peers, device);
+ case WGDEVICE_A_JC:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ {
+ device->junk_packet_count = mnl_attr_get_u16(attr);
+ device->flags |= WGDEVICE_HAS_JC;
+ }
+ break;
+ case WGDEVICE_A_JMIN:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ {
+ device->junk_packet_min_size = mnl_attr_get_u16(attr);
+ device->flags |= WGDEVICE_HAS_JMIN;
+ }
+ break;
+ case WGDEVICE_A_JMAX:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ {
+ device->junk_packet_max_size = mnl_attr_get_u16(attr);
+ device->flags |= WGDEVICE_HAS_JMAX;
+ }
+ break;
+ case WGDEVICE_A_S1:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ {
+ device->init_packet_junk_size = mnl_attr_get_u16(attr);
+ device->flags |= WGDEVICE_HAS_S1;
+ }
+ break;
+ case WGDEVICE_A_S2:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U16))
+ {
+ device->response_packet_junk_size = mnl_attr_get_u16(attr);
+ device->flags |= WGDEVICE_HAS_S2;
+ }
+ break;
+ case WGDEVICE_A_H1:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ {
+ device->init_packet_magic_header = mnl_attr_get_u32(attr);
+ device->flags |= WGDEVICE_HAS_H1;
+ }
+ break;
+ case WGDEVICE_A_H2:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ {
+ device->response_packet_magic_header = mnl_attr_get_u32(attr);
+ device->flags |= WGDEVICE_HAS_H2;
+ }
+ break;
+ case WGDEVICE_A_H3:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ {
+ device->underload_packet_magic_header = mnl_attr_get_u32(attr);
+ device->flags |= WGDEVICE_HAS_H3;
+ }
+ break;
+ case WGDEVICE_A_H4:
+ if (!mnl_attr_validate(attr, MNL_TYPE_U32))
+ {
+ device->transport_packet_magic_header = mnl_attr_get_u32(attr);
+ device->flags |= WGDEVICE_HAS_H4;
+ }
- return MNL_CB_OK;
+ case WGDEVICE_A_I1:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->i1 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_I1;
+}
+ case WGDEVICE_A_I2:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->i2 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_I2;
+}
+ case WGDEVICE_A_I3:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->i3 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_I3;
+}
+ case WGDEVICE_A_I4:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->i4 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_I4;
+}
+ case WGDEVICE_A_I5:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->i5 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_I5;
+ }
+ case WGDEVICE_A_J1:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->j1 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_J1;
+ }
+ case WGDEVICE_A_J2:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->j2 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_J2;
+ }
+ case WGDEVICE_A_J3:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->j3 = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_J3;
+ }
+ case WGDEVICE_A_ITIME:
+ if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
+ device->itime = strdup(mnl_attr_get_str(attr));
+ device->flags |= WGDEVICE_HAS_ITIME;
+ }
+ break;
+ }
+
+ return MNL_CB_OK;
}
-static int read_device_cb(const struct nlmsghdr *nlh, void *data)
+static int read_device_cb(const struct nlmsghdr* nlh, void* data)
{
- return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_device, data);
+ return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_device, data);
}
-static void coalesce_peers(struct wgdevice *device)
+static void coalesce_peers(struct wgdevice* device)
{
- struct wgpeer *old_next_peer, *peer = device->first_peer;
+ struct wgpeer *old_next_peer, *peer = device->first_peer;
- while (peer && peer->next_peer) {
- if (memcmp(peer->public_key, peer->next_peer->public_key, sizeof(peer->public_key))) {
- peer = peer->next_peer;
- continue;
- }
- if (!peer->first_allowedip) {
- peer->first_allowedip = peer->next_peer->first_allowedip;
- peer->last_allowedip = peer->next_peer->last_allowedip;
- } else {
- peer->last_allowedip->next_allowedip = peer->next_peer->first_allowedip;
- peer->last_allowedip = peer->next_peer->last_allowedip;
- }
- old_next_peer = peer->next_peer;
- peer->next_peer = old_next_peer->next_peer;
- free(old_next_peer);
- }
+ while (peer && peer->next_peer)
+ {
+ if (memcmp(
+ peer->public_key, peer->next_peer->public_key, sizeof(peer->public_key)))
+ {
+ peer = peer->next_peer;
+ continue;
+ }
+ if (!peer->first_allowedip)
+ {
+ peer->first_allowedip = peer->next_peer->first_allowedip;
+ peer->last_allowedip = peer->next_peer->last_allowedip;
+ }
+ else
+ {
+ peer->last_allowedip->next_allowedip = peer->next_peer->first_allowedip;
+ peer->last_allowedip = peer->next_peer->last_allowedip;
+ }
+ old_next_peer = peer->next_peer;
+ peer->next_peer = old_next_peer->next_peer;
+ free(old_next_peer);
+ }
}
-static int kernel_get_device(struct wgdevice **device, const char *iface)
+static int kernel_get_device(struct wgdevice** device, const char* iface)
{
- int ret;
- struct nlmsghdr *nlh;
- struct mnlg_socket *nlg;
+ int ret;
+ struct nlmsghdr* nlh;
+ struct mnlg_socket* nlg;
- /* libmnl doesn't check the buffer size, so enforce that before using. */
- if (strlen(iface) >= IFNAMSIZ) {
- errno = ENAMETOOLONG;
- return -ENAMETOOLONG;
- }
+ /* libmnl doesn't check the buffer size, so enforce that before using. */
+ if (strlen(iface) >= IFNAMSIZ)
+ {
+ errno = ENAMETOOLONG;
+ return -ENAMETOOLONG;
+ }
try_again:
- ret = 0;
- *device = calloc(1, sizeof(**device));
- if (!*device)
- return -errno;
+ ret = 0;
+ *device = calloc(1, sizeof(**device));
+ if (!*device)
+ return -errno;
- nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
- if (!nlg) {
- free_wgdevice(*device);
- *device = NULL;
- return -errno;
- }
+ nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
+ if (!nlg)
+ {
+ free_wgdevice(*device);
+ *device = NULL;
+ return -errno;
+ }
- nlh = mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
- mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, iface);
- if (mnlg_socket_send(nlg, nlh) < 0) {
- ret = -errno;
- goto out;
- }
- errno = 0;
- if (mnlg_socket_recv_run(nlg, read_device_cb, *device) < 0) {
- ret = errno ? -errno : -EINVAL;
- goto out;
- }
- coalesce_peers(*device);
+ nlh =
+ mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
+ mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, iface);
+ if (mnlg_socket_send(nlg, nlh) < 0)
+ {
+ ret = -errno;
+ goto out;
+ }
+ errno = 0;
+ if (mnlg_socket_recv_run(nlg, read_device_cb, *device) < 0)
+ {
+ ret = errno ? -errno : -EINVAL;
+ goto out;
+ }
+ coalesce_peers(*device);
out:
- if (nlg)
- mnlg_socket_close(nlg);
- if (ret) {
- free_wgdevice(*device);
- if (ret == -EINTR)
- goto try_again;
- *device = NULL;
- }
- errno = -ret;
- return ret;
+ if (nlg)
+ mnlg_socket_close(nlg);
+ if (ret)
+ {
+ free_wgdevice(*device);
+ if (ret == -EINTR)
+ goto try_again;
+ *device = NULL;
+ }
+ errno = -ret;
+ return ret;
}
diff --git a/src/showconf.c b/src/showconf.c
index 424b2be..473416c 100644
--- a/src/showconf.c
+++ b/src/showconf.c
@@ -65,6 +65,25 @@ int showconf_main(int argc, const char *argv[])
if (device->flags & WGDEVICE_HAS_H4)
printf("H4 = %u\n", device->transport_packet_magic_header);
+ if (device->flags & WGDEVICE_HAS_I1)
+ printf("I1 = %s\n", device->i1);
+ if (device->flags & WGDEVICE_HAS_I2)
+ printf("I2 = %s\n", device->i2);
+ if (device->flags & WGDEVICE_HAS_I3)
+ printf("I3 = %s\n", device->i3);
+ if (device->flags & WGDEVICE_HAS_I4)
+ printf("I4 = %s\n", device->i4);
+ if (device->flags & WGDEVICE_HAS_I5)
+ printf("I5 = %s\n", device->i5);
+ if (device->flags & WGDEVICE_HAS_J1)
+ printf("J1 = %s\n", device->j1);
+ if (device->flags & WGDEVICE_HAS_J2)
+ printf("J2 = %s\n", device->j2);
+ if (device->flags & WGDEVICE_HAS_J3)
+ printf("J3 = %s\n", device->j3);
+ if (device->flags & WGDEVICE_HAS_ITIME)
+ printf("Itime = %s\n", device->itime);
+
printf("\n");
for_each_wgpeer(device, peer) {
key_to_base64(base64, peer->public_key);
diff --git a/src/uapi/linux/linux/wireguard.h b/src/uapi/linux/linux/wireguard.h
index 8d38c90..c4849bb 100644
--- a/src/uapi/linux/linux/wireguard.h
+++ b/src/uapi/linux/linux/wireguard.h
@@ -191,6 +191,15 @@ enum wgdevice_attribute {
WGDEVICE_A_H2,
WGDEVICE_A_H3,
WGDEVICE_A_H4,
+ WGDEVICE_A_I1,
+ WGDEVICE_A_I2,
+ WGDEVICE_A_I3,
+ WGDEVICE_A_I4,
+ WGDEVICE_A_I5,
+ WGDEVICE_A_J1,
+ WGDEVICE_A_J2,
+ WGDEVICE_A_J3,
+ WGDEVICE_A_ITIME,
WGDEVICE_A_PEER,
__WGDEVICE_A_LAST
};