From 66de01f21196befe6676cdd09c637224ff7f8851 Mon Sep 17 00:00:00 2001 From: Mark Puha Date: Sat, 14 Jun 2025 15:02:32 +0200 Subject: [PATCH] fix: formatting --- src/containers.h | 220 +++--- src/ipc-freebsd.h | 1007 ++++++++++++------------- src/ipc-linux.h | 1368 ++++++++++++++++------------------ src/ipc-openbsd.h | 791 ++++++++++---------- src/ipc-uapi.h | 804 +++++++++----------- src/ipc-windows.h | 1264 ++++++++++++++----------------- src/netlink.h | 1119 +++++++++++++-------------- src/uapi/openbsd/net/if_wg.h | 129 ++-- src/uapi/windows/wireguard.h | 162 ++-- src/wg.c | 2 +- 10 files changed, 3170 insertions(+), 3696 deletions(-) diff --git a/src/containers.h b/src/containers.h index 376230e..9035c1a 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__) @@ -28,143 +28,127 @@ #endif /* Cross platform __kernel_timespec */ -struct timespec64 -{ - int64_t tv_sec; - int64_t tv_nsec; +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; +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, - WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6 +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, + WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6 }; -struct wgpeer -{ - uint32_t flags; +struct wgpeer { + uint32_t flags; - uint8_t public_key[WG_KEY_LEN]; - uint8_t preshared_key[WG_KEY_LEN]; + 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; + 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; + struct timespec64 last_handshake_time; + uint64_t rx_bytes, tx_bytes; + uint16_t persistent_keepalive_interval; - bool advanced_security; - bool special_handshake; + bool advanced_security; + bool special_handshake; - struct wgallowedip *first_allowedip, *last_allowedip; - struct wgpeer* next_peer; + 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 +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; +struct wgdevice { + char name[IFNAMSIZ]; + uint32_t ifindex; - uint32_t flags; + uint32_t flags; - uint8_t public_key[WG_KEY_LEN]; - uint8_t private_key[WG_KEY_LEN]; + uint8_t public_key[WG_KEY_LEN]; + uint8_t private_key[WG_KEY_LEN]; - uint32_t fwmark; - uint16_t listen_port; + uint32_t fwmark; + uint16_t listen_port; - struct wgpeer *first_peer, *last_peer; + 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; - uint32_t itime; + 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; + uint32_t 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) +#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) +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); + 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-freebsd.h b/src/ipc-freebsd.h index 7fe3b12..f07b5dd 100644 --- a/src/ipc-freebsd.h +++ b/src/ipc-freebsd.h @@ -5,485 +5,436 @@ */ #include -#include #include #include +#include #define IPC_SUPPORTS_KERNEL_INTERFACE static int get_dgram_socket(void) { - static int sock = -1; - if (sock < 0) - sock = socket(AF_INET, SOCK_DGRAM, 0); - return sock; + static int sock = -1; + if (sock < 0) + sock = socket(AF_INET, SOCK_DGRAM, 0); + return sock; } -static int kernel_get_wireguard_interfaces(struct string_list* list) +static int kernel_get_wireguard_interfaces(struct string_list *list) { - struct ifgroupreq ifgr = {.ifgr_name = "wg"}; - struct ifg_req* ifg; - int s = get_dgram_socket(), ret = 0; + struct ifgroupreq ifgr = { .ifgr_name = "wg" }; + struct ifg_req *ifg; + int s = get_dgram_socket(), ret = 0; - if (s < 0) - return -errno; + if (s < 0) + return -errno; - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) - return errno == ENOENT ? 0 : -errno; + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) + return errno == ENOENT ? 0 : -errno; - ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); - if (!ifgr.ifgr_groups) - return -errno; - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) - { - ret = -errno; - goto out; - } + ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); + if (!ifgr.ifgr_groups) + return -errno; + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) { + ret = -errno; + goto out; + } - for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) - { - if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) - goto out; - ifgr.ifgr_len -= sizeof(struct ifg_req); - } + for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) { + if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) + goto out; + ifgr.ifgr_len -= sizeof(struct ifg_req); + } out: - free(ifgr.ifgr_groups); - return ret; + free(ifgr.ifgr_groups); + return ret; } -static int kernel_get_device(struct wgdevice** device, const char* ifname) +static int kernel_get_device(struct wgdevice **device, const char *ifname) { - struct wg_data_io wgd = {0}; - nvlist_t* nvl_device = NULL; - const nvlist_t* const* nvl_peers; - struct wgdevice* dev = NULL; - size_t size, peer_count, i; - uint64_t number; - const void* binary; - int ret = 0, s; + struct wg_data_io wgd = { 0 }; + nvlist_t *nvl_device = NULL; + const nvlist_t *const *nvl_peers; + struct wgdevice *dev = NULL; + size_t size, peer_count, i; + uint64_t number; + const void *binary; + int ret = 0, s; - *device = NULL; - s = get_dgram_socket(); - if (s < 0) - goto err; + *device = NULL; + s = get_dgram_socket(); + if (s < 0) + goto err; - strlcpy(wgd.wgd_name, ifname, sizeof(wgd.wgd_name)); - if (ioctl(s, SIOCGWG, &wgd) < 0) - goto err; + strlcpy(wgd.wgd_name, ifname, sizeof(wgd.wgd_name)); + if (ioctl(s, SIOCGWG, &wgd) < 0) + goto err; - wgd.wgd_data = malloc(wgd.wgd_size); - if (!wgd.wgd_data) - goto err; - if (ioctl(s, SIOCGWG, &wgd) < 0) - goto err; + wgd.wgd_data = malloc(wgd.wgd_size); + if (!wgd.wgd_data) + goto err; + if (ioctl(s, SIOCGWG, &wgd) < 0) + goto err; - dev = calloc(1, sizeof(*dev)); - if (!dev) - goto err; - strlcpy(dev->name, ifname, sizeof(dev->name)); - nvl_device = nvlist_unpack(wgd.wgd_data, wgd.wgd_size, 0); - if (!nvl_device) - goto err; + dev = calloc(1, sizeof(*dev)); + if (!dev) + goto err; + strlcpy(dev->name, ifname, sizeof(dev->name)); + nvl_device = nvlist_unpack(wgd.wgd_data, wgd.wgd_size, 0); + if (!nvl_device) + goto err; - if (nvlist_exists_number(nvl_device, "listen-port")) - { - number = nvlist_get_number(nvl_device, "listen-port"); - if (number <= UINT16_MAX) - { - dev->listen_port = number; - dev->flags |= WGDEVICE_HAS_LISTEN_PORT; - } - } - if (nvlist_exists_number(nvl_device, "jc")) - { - number = nvlist_get_number(nvl_device, "jc"); - if (number <= UINT16_MAX) - { - dev->junk_packet_count = number; - dev->flags |= WGDEVICE_HAS_JC; - } - } - if (nvlist_exists_number(nvl_device, "jmin")) - { - number = nvlist_get_number(nvl_device, "jmin"); - if (number <= UINT16_MAX) - { - dev->junk_packet_min_size = number; - dev->flags |= WGDEVICE_HAS_JMIN; - } - } - if (nvlist_exists_number(nvl_device, "jmax")) - { - number = nvlist_get_number(nvl_device, "jmax"); - if (number <= UINT16_MAX) - { - dev->junk_packet_max_size = number; - dev->flags |= WGDEVICE_HAS_JMAX; - } - } - if (nvlist_exists_number(nvl_device, "s1")) - { - number = nvlist_get_number(nvl_device, "s1"); - if (number <= UINT16_MAX) - { - dev->init_packet_junk_size = number; - dev->flags |= WGDEVICE_HAS_S1; - } - } - if (nvlist_exists_number(nvl_device, "s2")) - { - number = nvlist_get_number(nvl_device, "s2"); - if (number <= UINT16_MAX) - { - dev->response_packet_junk_size = number; - dev->flags |= WGDEVICE_HAS_S2; - } - } - if (nvlist_exists_number(nvl_device, "h1")) - { - number = nvlist_get_number(nvl_device, "h1"); - if (number <= UINT32_MAX) - { - dev->init_packet_magic_header = number; - dev->flags |= WGDEVICE_HAS_H1; - } - } - if (nvlist_exists_number(nvl_device, "h2")) - { - number = nvlist_get_number(nvl_device, "h2"); - if (number <= UINT32_MAX) - { - dev->response_packet_magic_header = number; - dev->flags |= WGDEVICE_HAS_H2; - } - } - if (nvlist_exists_number(nvl_device, "h3")) - { - number = nvlist_get_number(nvl_device, "h3"); - if (number <= UINT32_MAX) - { - dev->underload_packet_magic_header = number; - dev->flags |= WGDEVICE_HAS_H3; - } - } - if (nvlist_exists_number(nvl_device, "h4")) - { - number = nvlist_get_number(nvl_device, "h4"); - if (number <= UINT32_MAX) - { - dev->transport_packet_magic_header = number; - dev->flags |= WGDEVICE_HAS_H4; - } - } - if (nvlist_exists_binary(nvl_device, "i1")) - { - binary = nvlist_get_binary(nvl_device, "i1", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->i1 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_I1; - } - } - if (nvlist_exists_binary(nvl_device, "i2")) - { - binary = nvlist_get_binary(nvl_device, "i2", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->i2 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_I2; - } - } - if (nvlist_exists_binary(nvl_device, "i3")) - { - binary = nvlist_get_binary(nvl_device, "i3", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->i3 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_I3; - } - } - if (nvlist_exists_binary(nvl_device, "i4")) - { - binary = nvlist_get_binary(nvl_device, "i4", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->i4 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_I4; - } - } - if (nvlist_exists_binary(nvl_device, "i5")) - { - binary = nvlist_get_binary(nvl_device, "i5", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->i5 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_I5; - } - } - if (nvlist_exists_binary(nvl_device, "j1")) - { - binary = nvlist_get_binary(nvl_device, "j1", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->j1 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_J1; - } - } - if (nvlist_exists_binary(nvl_device, "j2")) - { - binary = nvlist_get_binary(nvl_device, "j2", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->j2 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_J2; - } - } - if (nvlist_exists_binary(nvl_device, "j3")) - { - binary = nvlist_get_binary(nvl_device, "j3", &size); - if (binary && size < MAX_AWG_JUNK_LEN) - { - dev->j3 = strdup((const char*)binary); - dev->flags |= WGDEVICE_HAS_J3; - } - } - if (nvlist_exists_binary(nvl_device, "itime")) - { - number = nvlist_get_number(nvl_device, "itime"); - if (number <= UINT32_MAX) - { - dev->itime = number; - dev->flags |= WGDEVICE_HAS_ITIME; - } - } + if (nvlist_exists_number(nvl_device, "listen-port")) { + number = nvlist_get_number(nvl_device, "listen-port"); + if (number <= UINT16_MAX) { + dev->listen_port = number; + dev->flags |= WGDEVICE_HAS_LISTEN_PORT; + } + } + if (nvlist_exists_number(nvl_device, "jc")) { + number = nvlist_get_number(nvl_device, "jc"); + if (number <= UINT16_MAX){ + dev->junk_packet_count = number; + dev->flags |= WGDEVICE_HAS_JC; + } + } + if (nvlist_exists_number(nvl_device, "jmin")) { + number = nvlist_get_number(nvl_device, "jmin"); + if (number <= UINT16_MAX){ + dev->junk_packet_min_size = number; + dev->flags |= WGDEVICE_HAS_JMIN; + } + } + if (nvlist_exists_number(nvl_device, "jmax")) { + number = nvlist_get_number(nvl_device, "jmax"); + if (number <= UINT16_MAX){ + dev->junk_packet_max_size = number; + dev->flags |= WGDEVICE_HAS_JMAX; + } + } + if (nvlist_exists_number(nvl_device, "s1")) { + number = nvlist_get_number(nvl_device, "s1"); + if (number <= UINT16_MAX){ + dev->init_packet_junk_size = number; + dev->flags |= WGDEVICE_HAS_S1; + } + } + if (nvlist_exists_number(nvl_device, "s2")) { + number = nvlist_get_number(nvl_device, "s2"); + if (number <= UINT16_MAX){ + dev->response_packet_junk_size = number; + dev->flags |= WGDEVICE_HAS_S2; + } + } + if (nvlist_exists_number(nvl_device, "h1")) { + number = nvlist_get_number(nvl_device, "h1"); + if (number <= UINT32_MAX){ + dev->init_packet_magic_header = number; + dev->flags |= WGDEVICE_HAS_H1; + } + } + if (nvlist_exists_number(nvl_device, "h2")) { + number = nvlist_get_number(nvl_device, "h2"); + if (number <= UINT32_MAX){ + dev->response_packet_magic_header = number; + dev->flags |= WGDEVICE_HAS_H2; + } + } + if (nvlist_exists_number(nvl_device, "h3")) { + number = nvlist_get_number(nvl_device, "h3"); + if (number <= UINT32_MAX){ + dev->underload_packet_magic_header = number; + dev->flags |= WGDEVICE_HAS_H3; + } + } + if (nvlist_exists_number(nvl_device, "h4")) { + number = nvlist_get_number(nvl_device, "h4"); + if (number <= UINT32_MAX){ + dev->transport_packet_magic_header = number; + dev->flags |= WGDEVICE_HAS_H4; + } + } + if (nvlist_exists_binary(nvl_device, "i1")) + { + binary = nvlist_get_binary(nvl_device, "i1", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->i1 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_I1; + } + } + if (nvlist_exists_binary(nvl_device, "i2")) + { + binary = nvlist_get_binary(nvl_device, "i2", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->i2 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_I2; + } + } + if (nvlist_exists_binary(nvl_device, "i3")) + { + binary = nvlist_get_binary(nvl_device, "i3", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->i3 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_I3; + } + } + if (nvlist_exists_binary(nvl_device, "i4")) + { + binary = nvlist_get_binary(nvl_device, "i4", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->i4 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_I4; + } + } + if (nvlist_exists_binary(nvl_device, "i5")) + { + binary = nvlist_get_binary(nvl_device, "i5", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->i5 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_I5; + } + } + if (nvlist_exists_binary(nvl_device, "j1")) + { + binary = nvlist_get_binary(nvl_device, "j1", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->j1 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_J1; + } + } + if (nvlist_exists_binary(nvl_device, "j2")) + { + binary = nvlist_get_binary(nvl_device, "j2", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->j2 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_J2; + } + } + if (nvlist_exists_binary(nvl_device, "j3")) + { + binary = nvlist_get_binary(nvl_device, "j3", &size); + if (binary && size < MAX_AWG_JUNK_LEN) + { + dev->j3 = strdup((const char*)binary); + dev->flags |= WGDEVICE_HAS_J3; + } + } + if (nvlist_exists_binary(nvl_device, "itime")) + { + number = nvlist_get_number(nvl_device, "itime"); + if (number <= UINT32_MAX) + { + dev->itime = number; + dev->flags |= WGDEVICE_HAS_ITIME; + } + } - if (nvlist_exists_number(nvl_device, "user-cookie")) - { - number = nvlist_get_number(nvl_device, "user-cookie"); - if (number <= UINT32_MAX) - { - dev->fwmark = number; - dev->flags |= WGDEVICE_HAS_FWMARK; - } - } - if (nvlist_exists_binary(nvl_device, "public-key")) - { - binary = nvlist_get_binary(nvl_device, "public-key", &size); - if (binary && size == sizeof(dev->public_key)) - { - memcpy(dev->public_key, binary, sizeof(dev->public_key)); - dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; - } - } - if (nvlist_exists_binary(nvl_device, "private-key")) - { - binary = nvlist_get_binary(nvl_device, "private-key", &size); - if (binary && size == sizeof(dev->private_key)) - { - memcpy(dev->private_key, binary, sizeof(dev->private_key)); - dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; - } - } - if (!nvlist_exists_nvlist_array(nvl_device, "peers")) - goto skip_peers; - nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count); - if (!nvl_peers) - goto skip_peers; - for (i = 0; i < peer_count; ++i) - { - struct wgpeer* peer; - struct wgallowedip* aip = NULL; - const nvlist_t* const* nvl_aips; - size_t aip_count, j; + if (nvlist_exists_number(nvl_device, "user-cookie")) { + number = nvlist_get_number(nvl_device, "user-cookie"); + if (number <= UINT32_MAX) { + dev->fwmark = number; + dev->flags |= WGDEVICE_HAS_FWMARK; + } + } + if (nvlist_exists_binary(nvl_device, "public-key")) { + binary = nvlist_get_binary(nvl_device, "public-key", &size); + if (binary && size == sizeof(dev->public_key)) { + memcpy(dev->public_key, binary, sizeof(dev->public_key)); + dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; + } + } + if (nvlist_exists_binary(nvl_device, "private-key")) { + binary = nvlist_get_binary(nvl_device, "private-key", &size); + if (binary && size == sizeof(dev->private_key)) { + memcpy(dev->private_key, binary, sizeof(dev->private_key)); + dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; + } + } + if (!nvlist_exists_nvlist_array(nvl_device, "peers")) + goto skip_peers; + nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count); + if (!nvl_peers) + goto skip_peers; + for (i = 0; i < peer_count; ++i) { + struct wgpeer *peer; + struct wgallowedip *aip = NULL; + const nvlist_t *const *nvl_aips; + size_t aip_count, j; - peer = calloc(1, sizeof(*peer)); - if (!peer) - goto err_peer; - if (nvlist_exists_binary(nvl_peers[i], "public-key")) - { - binary = nvlist_get_binary(nvl_peers[i], "public-key", &size); - if (binary && size == sizeof(peer->public_key)) - { - memcpy(peer->public_key, binary, sizeof(peer->public_key)); - peer->flags |= WGPEER_HAS_PUBLIC_KEY; - } - } - if (nvlist_exists_binary(nvl_peers[i], "preshared-key")) - { - binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size); - if (binary && size == sizeof(peer->preshared_key)) - { - memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key)); - if (!key_is_zero(peer->preshared_key)) - peer->flags |= WGPEER_HAS_PRESHARED_KEY; - } - } - if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval")) - { - number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval"); - if (number <= UINT16_MAX) - { - peer->persistent_keepalive_interval = number; - peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; - } - } - if (nvlist_exists_binary(nvl_peers[i], "endpoint")) - { - const struct sockaddr* endpoint = - nvlist_get_binary(nvl_peers[i], "endpoint", &size); - if (endpoint && size <= sizeof(peer->endpoint) && - size >= sizeof(peer->endpoint.addr) && - (endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6)) - memcpy(&peer->endpoint.addr, endpoint, size); - } - if (nvlist_exists_number(nvl_peers[i], "rx-bytes")) - peer->rx_bytes = nvlist_get_number(nvl_peers[i], "rx-bytes"); - if (nvlist_exists_number(nvl_peers[i], "tx-bytes")) - peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes"); - if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time")) - { - binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size); - if (binary && size == sizeof(peer->last_handshake_time)) - memcpy( - &peer->last_handshake_time, - binary, - sizeof(peer->last_handshake_time)); - } + peer = calloc(1, sizeof(*peer)); + if (!peer) + goto err_peer; + if (nvlist_exists_binary(nvl_peers[i], "public-key")) { + binary = nvlist_get_binary(nvl_peers[i], "public-key", &size); + if (binary && size == sizeof(peer->public_key)) { + memcpy(peer->public_key, binary, sizeof(peer->public_key)); + peer->flags |= WGPEER_HAS_PUBLIC_KEY; + } + } + if (nvlist_exists_binary(nvl_peers[i], "preshared-key")) { + binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size); + if (binary && size == sizeof(peer->preshared_key)) { + memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key)); + if (!key_is_zero(peer->preshared_key)) + peer->flags |= WGPEER_HAS_PRESHARED_KEY; + } + } + if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval")) { + number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval"); + if (number <= UINT16_MAX) { + peer->persistent_keepalive_interval = number; + peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; + } + } + if (nvlist_exists_binary(nvl_peers[i], "endpoint")) { + const struct sockaddr *endpoint = nvlist_get_binary(nvl_peers[i], "endpoint", &size); + if (endpoint && size <= sizeof(peer->endpoint) && size >= sizeof(peer->endpoint.addr) && + (endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6)) + memcpy(&peer->endpoint.addr, endpoint, size); + } + if (nvlist_exists_number(nvl_peers[i], "rx-bytes")) + peer->rx_bytes = nvlist_get_number(nvl_peers[i], "rx-bytes"); + if (nvlist_exists_number(nvl_peers[i], "tx-bytes")) + peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes"); + if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time")) { + binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size); + if (binary && size == sizeof(peer->last_handshake_time)) + memcpy(&peer->last_handshake_time, binary, sizeof(peer->last_handshake_time)); + } - if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips")) - goto skip_allowed_ips; - nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count); - if (!aip_count || !nvl_aips) - goto skip_allowed_ips; - for (j = 0; j < aip_count; ++j) - { - if (!nvlist_exists_number(nvl_aips[j], "cidr")) - continue; - if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && - !nvlist_exists_binary(nvl_aips[j], "ipv6")) - continue; - aip = calloc(1, sizeof(*aip)); - if (!aip) - goto err_allowed_ips; - number = nvlist_get_number(nvl_aips[j], "cidr"); - if (nvlist_exists_binary(nvl_aips[j], "ipv4")) - { - binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size); - if (!binary || number > 32) - { - ret = EINVAL; - goto err_allowed_ips; - } - aip->family = AF_INET; - aip->cidr = number; - memcpy(&aip->ip4, binary, sizeof(aip->ip4)); - } - else - { - assert(nvlist_exists_binary(nvl_aips[j], "ipv6")); - binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size); - if (!binary || number > 128) - { - ret = EINVAL; - goto err_allowed_ips; - } - aip->family = AF_INET6; - aip->cidr = number; - memcpy(&aip->ip6, binary, sizeof(aip->ip6)); - } + if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips")) + goto skip_allowed_ips; + nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count); + if (!aip_count || !nvl_aips) + goto skip_allowed_ips; + for (j = 0; j < aip_count; ++j) { + if (!nvlist_exists_number(nvl_aips[j], "cidr")) + continue; + if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && !nvlist_exists_binary(nvl_aips[j], "ipv6")) + continue; + aip = calloc(1, sizeof(*aip)); + if (!aip) + goto err_allowed_ips; + number = nvlist_get_number(nvl_aips[j], "cidr"); + if (nvlist_exists_binary(nvl_aips[j], "ipv4")) { + binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size); + if (!binary || number > 32) { + ret = EINVAL; + goto err_allowed_ips; + } + aip->family = AF_INET; + aip->cidr = number; + memcpy(&aip->ip4, binary, sizeof(aip->ip4)); + } else { + assert(nvlist_exists_binary(nvl_aips[j], "ipv6")); + binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size); + if (!binary || number > 128) { + ret = EINVAL; + goto err_allowed_ips; + } + aip->family = AF_INET6; + aip->cidr = number; + memcpy(&aip->ip6, binary, sizeof(aip->ip6)); + } - if (!peer->first_allowedip) - peer->first_allowedip = aip; - else - peer->last_allowedip->next_allowedip = aip; - peer->last_allowedip = aip; - aip = NULL; - continue; + if (!peer->first_allowedip) + peer->first_allowedip = aip; + else + peer->last_allowedip->next_allowedip = aip; + peer->last_allowedip = aip; + aip = NULL; + continue; - err_allowed_ips: - if (!ret) - ret = -errno; - free(aip); - goto err_peer; - } + err_allowed_ips: + if (!ret) + ret = -errno; + free(aip); + goto err_peer; + } - /* Nothing leaked, hopefully -- ownership transferred or aip freed. */ - assert(aip == NULL); - skip_allowed_ips: - if (!dev->first_peer) - dev->first_peer = peer; - else - dev->last_peer->next_peer = peer; - dev->last_peer = peer; - continue; + /* Nothing leaked, hopefully -- ownership transferred or aip freed. */ + assert(aip == NULL); + skip_allowed_ips: + if (!dev->first_peer) + dev->first_peer = peer; + else + dev->last_peer->next_peer = peer; + dev->last_peer = peer; + continue; - err_peer: - if (!ret) - ret = -errno; - free(peer); - goto err; - } + err_peer: + if (!ret) + ret = -errno; + free(peer); + goto err; + } skip_peers: - free(wgd.wgd_data); - nvlist_destroy(nvl_device); - *device = dev; - return 0; + free(wgd.wgd_data); + nvlist_destroy(nvl_device); + *device = dev; + return 0; err: - if (!ret) - ret = -errno; - free(wgd.wgd_data); - nvlist_destroy(nvl_device); - free(dev); - return ret; + if (!ret) + ret = -errno; + free(wgd.wgd_data); + nvlist_destroy(nvl_device); + free(dev); + return ret; } -static int kernel_set_device(struct wgdevice* dev) + +static int kernel_set_device(struct wgdevice *dev) { - struct wg_data_io wgd = {0}; - nvlist_t * nvl_device = NULL, **nvl_peers = NULL; - size_t peer_count = 0, i = 0; - struct wgpeer* peer; - int ret = 0, s; + struct wg_data_io wgd = { 0 }; + nvlist_t *nvl_device = NULL, **nvl_peers = NULL; + size_t peer_count = 0, i = 0; + struct wgpeer *peer; + int ret = 0, s; - strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name)); + strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name)); - nvl_device = nvlist_create(0); - if (!nvl_device) - goto err; + nvl_device = nvlist_create(0); + if (!nvl_device) + goto err; - for_each_wgpeer(dev, peer)++ peer_count; - if (peer_count) - { - nvl_peers = calloc(peer_count, sizeof(*nvl_peers)); - if (!nvl_peers) - goto err; - } - if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) - nvlist_add_binary( - nvl_device, "private-key", dev->private_key, sizeof(dev->private_key)); - if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) - nvlist_add_number(nvl_device, "listen-port", dev->listen_port); - if (dev->flags & WGDEVICE_HAS_JC) - nvlist_add_number(nvl_device, "jc", dev->junk_packet_count); - if (dev->flags & WGDEVICE_HAS_JMIN) - nvlist_add_number(nvl_device, "jmin", dev->junk_packet_min_size); - if (dev->flags & WGDEVICE_HAS_JMAX) - nvlist_add_number(nvl_device, "jmax", dev->junk_packet_max_size); - if (dev->flags & WGDEVICE_HAS_S1) - nvlist_add_number(nvl_device, "s1", dev->init_packet_junk_size); - if (dev->flags & WGDEVICE_HAS_S2) - nvlist_add_number(nvl_device, "s2", dev->response_packet_junk_size); - if (dev->flags & WGDEVICE_HAS_H1) - nvlist_add_number(nvl_device, "h1", dev->init_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H2) - nvlist_add_number(nvl_device, "h2", dev->response_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H3) - nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H4) - nvlist_add_number(nvl_device, "h4", dev->transport_packet_magic_header); + for_each_wgpeer(dev, peer) + ++peer_count; + if (peer_count) { + nvl_peers = calloc(peer_count, sizeof(*nvl_peers)); + if (!nvl_peers) + goto err; + } + if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) + nvlist_add_binary(nvl_device, "private-key", dev->private_key, sizeof(dev->private_key)); + if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) + nvlist_add_number(nvl_device, "listen-port", dev->listen_port); + if (dev->flags & WGDEVICE_HAS_JC) + nvlist_add_number(nvl_device, "jc", dev->junk_packet_count); + if (dev->flags & WGDEVICE_HAS_JMIN) + nvlist_add_number(nvl_device, "jmin", dev->junk_packet_min_size); + if (dev->flags & WGDEVICE_HAS_JMAX) + nvlist_add_number(nvl_device, "jmax", dev->junk_packet_max_size); + if (dev->flags & WGDEVICE_HAS_S1) + nvlist_add_number(nvl_device, "s1", dev->init_packet_junk_size); + if (dev->flags & WGDEVICE_HAS_S2) + nvlist_add_number(nvl_device, "s2", dev->response_packet_junk_size); + if (dev->flags & WGDEVICE_HAS_H1) + nvlist_add_number(nvl_device, "h1", dev->init_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H2) + nvlist_add_number(nvl_device, "h2", dev->response_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H3) + nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H4) + nvlist_add_number(nvl_device, "h4", dev->transport_packet_magic_header); if (dev->flags & WGDEVICE_HAS_I1) nvlist_add_binary(nvl_device, "i1", dev->i1, strlen(dev->i1) + 1); if (dev->flags & WGDEVICE_HAS_I2) @@ -502,109 +453,89 @@ static int kernel_set_device(struct wgdevice* dev) nvlist_add_binary(nvl_device, "j3", dev->j3, strlen(dev->j3) + 1); if (dev->flags & WGDEVICE_HAS_ITIME) nvlist_add_number(nvl_device, "itime", dev->itime); + if (dev->flags & WGDEVICE_HAS_FWMARK) + nvlist_add_number(nvl_device, "user-cookie", dev->fwmark); + if (dev->flags & WGDEVICE_REPLACE_PEERS) + nvlist_add_bool(nvl_device, "replace-peers", true); - if (dev->flags & WGDEVICE_HAS_FWMARK) - nvlist_add_number(nvl_device, "user-cookie", dev->fwmark); - if (dev->flags & WGDEVICE_REPLACE_PEERS) - nvlist_add_bool(nvl_device, "replace-peers", true); + for_each_wgpeer(dev, peer) { + size_t aip_count = 0, j = 0; + nvlist_t **nvl_aips = NULL; + struct wgallowedip *aip; - for_each_wgpeer(dev, peer) - { - size_t aip_count = 0, j = 0; - nvlist_t** nvl_aips = NULL; - struct wgallowedip* aip; + nvl_peers[i] = nvlist_create(0); + if (!nvl_peers[i]) + goto err_peer; + for_each_wgallowedip(peer, aip) + ++aip_count; + if (aip_count) { + nvl_aips = calloc(aip_count, sizeof(*nvl_aips)); + if (!nvl_aips) + goto err_peer; + } + nvlist_add_binary(nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key)); + if (peer->flags & WGPEER_HAS_PRESHARED_KEY) + nvlist_add_binary(nvl_peers[i], "preshared-key", peer->preshared_key, sizeof(peer->preshared_key)); + if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) + nvlist_add_number(nvl_peers[i], "persistent-keepalive-interval", peer->persistent_keepalive_interval); + if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) + nvlist_add_binary(nvl_peers[i], "endpoint", &peer->endpoint.addr, peer->endpoint.addr.sa_len); + if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) + nvlist_add_bool(nvl_peers[i], "replace-allowedips", true); + if (peer->flags & WGPEER_REMOVE_ME) + nvlist_add_bool(nvl_peers[i], "remove", true); + for_each_wgallowedip(peer, aip) { + nvl_aips[j] = nvlist_create(0); + if (!nvl_aips[j]) + goto err_peer; + nvlist_add_number(nvl_aips[j], "cidr", aip->cidr); + if (aip->family == AF_INET) + nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4)); + else if (aip->family == AF_INET6) + nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6)); + ++j; + } + if (j) { + nvlist_add_nvlist_array(nvl_peers[i], "allowed-ips", (const nvlist_t *const *)nvl_aips, j); + for (j = 0; j < aip_count; ++j) + nvlist_destroy(nvl_aips[j]); + free(nvl_aips); + } + ++i; + continue; - nvl_peers[i] = nvlist_create(0); - if (!nvl_peers[i]) - goto err_peer; - for_each_wgallowedip(peer, aip)++ aip_count; - if (aip_count) - { - nvl_aips = calloc(aip_count, sizeof(*nvl_aips)); - if (!nvl_aips) - goto err_peer; - } - nvlist_add_binary( - nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key)); - if (peer->flags & WGPEER_HAS_PRESHARED_KEY) - nvlist_add_binary( - nvl_peers[i], - "preshared-key", - peer->preshared_key, - sizeof(peer->preshared_key)); - if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) - nvlist_add_number( - nvl_peers[i], - "persistent-keepalive-interval", - peer->persistent_keepalive_interval); - if (peer->endpoint.addr.sa_family == AF_INET || - peer->endpoint.addr.sa_family == AF_INET6) - nvlist_add_binary( - nvl_peers[i], - "endpoint", - &peer->endpoint.addr, - peer->endpoint.addr.sa_len); - if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - nvlist_add_bool(nvl_peers[i], "replace-allowedips", true); - if (peer->flags & WGPEER_REMOVE_ME) - nvlist_add_bool(nvl_peers[i], "remove", true); - for_each_wgallowedip(peer, aip) - { - nvl_aips[j] = nvlist_create(0); - if (!nvl_aips[j]) - goto err_peer; - nvlist_add_number(nvl_aips[j], "cidr", aip->cidr); - if (aip->family == AF_INET) - nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4)); - else if (aip->family == AF_INET6) - nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6)); - ++j; - } - if (j) - { - nvlist_add_nvlist_array( - nvl_peers[i], "allowed-ips", (const nvlist_t* const*)nvl_aips, j); - for (j = 0; j < aip_count; ++j) - nvlist_destroy(nvl_aips[j]); - free(nvl_aips); - } - ++i; - continue; - - err_peer: - ret = -errno; - for (j = 0; j < aip_count && nvl_aips; ++j) - nvlist_destroy(nvl_aips[j]); - free(nvl_aips); - nvlist_destroy(nvl_peers[i]); - nvl_peers[i] = NULL; - goto err; - } - if (i) - { - nvlist_add_nvlist_array( - nvl_device, "peers", (const nvlist_t* const*)nvl_peers, i); - for (i = 0; i < peer_count; ++i) - nvlist_destroy(nvl_peers[i]); - free(nvl_peers); - nvl_peers = NULL; - } - wgd.wgd_data = nvlist_pack(nvl_device, &wgd.wgd_size); - nvlist_destroy(nvl_device); - nvl_device = NULL; - if (!wgd.wgd_data) - goto err; - s = get_dgram_socket(); - if (s < 0) - return -errno; - return ioctl(s, SIOCSWG, &wgd); + err_peer: + ret = -errno; + for (j = 0; j < aip_count && nvl_aips; ++j) + nvlist_destroy(nvl_aips[j]); + free(nvl_aips); + nvlist_destroy(nvl_peers[i]); + nvl_peers[i] = NULL; + goto err; + } + if (i) { + nvlist_add_nvlist_array(nvl_device, "peers", (const nvlist_t *const *)nvl_peers, i); + for (i = 0; i < peer_count; ++i) + nvlist_destroy(nvl_peers[i]); + free(nvl_peers); + nvl_peers = NULL; + } + wgd.wgd_data = nvlist_pack(nvl_device, &wgd.wgd_size); + nvlist_destroy(nvl_device); + nvl_device = NULL; + if (!wgd.wgd_data) + goto err; + s = get_dgram_socket(); + if (s < 0) + return -errno; + return ioctl(s, SIOCSWG, &wgd); err: - if (!ret) - ret = -errno; - for (i = 0; i < peer_count && nvl_peers; ++i) - nvlist_destroy(nvl_peers[i]); - free(nvl_peers); - nvlist_destroy(nvl_device); - return ret; + if (!ret) + ret = -errno; + for (i = 0; i < peer_count && nvl_peers; ++i) + nvlist_destroy(nvl_peers[i]); + free(nvl_peers); + nvlist_destroy(nvl_device); + return ret; } diff --git a/src/ipc-linux.h b/src/ipc-linux.h index d228c67..ffc95ca 100644 --- a/src/ipc-linux.h +++ b/src/ipc-linux.h @@ -3,849 +3,725 @@ * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. */ -#include "containers.h" -#include "encoding.h" -#include "netlink.h" -#include "uapi/linux/linux/wireguard.h" +#include +#include +#include +#include +#include #include +#include +#include +#include +#include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "containers.h" +#include "encoding.h" +#include "netlink.h" #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_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_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_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) + 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_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 (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)) + 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 (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)) - 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; - } - 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: - 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; + } + 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: + 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_SPECIAL_HANDSHAKE: - if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) - { - peer->special_handshake = true; + if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) { + peer->flags |= WGPEER_HAS_ADVANCED_SECURITY; + } + } + 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); - } + 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); + } - 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; - 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; - } - break; - 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; - } - break; - 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; - } - break; - 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; - } - break; - 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; - } - break; - 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; - } - break; - 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; - } - break; - 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; - } - break; - case WGDEVICE_A_ITIME: - if (!mnl_attr_validate(attr, MNL_TYPE_STRING)) - { - device->itime = mnl_attr_get_u32(attr); - device->flags |= WGDEVICE_HAS_ITIME; - } - 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + 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; + } + break; + case WGDEVICE_A_ITIME: + if (!mnl_attr_validate(attr, MNL_TYPE_STRING)) + { + device->itime = mnl_attr_get_u32(attr); + device->flags |= WGDEVICE_HAS_ITIME; + } + break; + } - return MNL_CB_OK; + 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/ipc-openbsd.h b/src/ipc-openbsd.h index 6a8e80a..c0f1e7b 100644 --- a/src/ipc-openbsd.h +++ b/src/ipc-openbsd.h @@ -3,521 +3,478 @@ * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. */ -#include "containers.h" #include -#include -#include -#include #include #include #include +#include #include #include #include #include -#include +#include +#include +#include +#include "containers.h" #define IPC_SUPPORTS_KERNEL_INTERFACE static int get_dgram_socket(void) { - static int sock = -1; - if (sock < 0) - sock = socket(AF_INET, SOCK_DGRAM, 0); - return sock; + static int sock = -1; + if (sock < 0) + sock = socket(AF_INET, SOCK_DGRAM, 0); + return sock; } -static int kernel_get_wireguard_interfaces(struct string_list* list) +static int kernel_get_wireguard_interfaces(struct string_list *list) { - struct ifgroupreq ifgr = {.ifgr_name = "wg"}; - struct ifg_req* ifg; - int s = get_dgram_socket(), ret = 0; + struct ifgroupreq ifgr = { .ifgr_name = "wg" }; + struct ifg_req *ifg; + int s = get_dgram_socket(), ret = 0; - if (s < 0) - return -errno; + if (s < 0) + return -errno; - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) - return errno == ENOENT ? 0 : -errno; + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) + return errno == ENOENT ? 0 : -errno; - ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); - if (!ifgr.ifgr_groups) - return -errno; - if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) - { - ret = -errno; - goto out; - } + ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); + if (!ifgr.ifgr_groups) + return -errno; + if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) { + ret = -errno; + goto out; + } - for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) - { - if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) - goto out; - ifgr.ifgr_len -= sizeof(struct ifg_req); - } + for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) { + if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) + goto out; + ifgr.ifgr_len -= sizeof(struct ifg_req); + } out: - free(ifgr.ifgr_groups); - return ret; + free(ifgr.ifgr_groups); + return ret; } -static int kernel_get_device(struct wgdevice** device, const char* iface) +static int kernel_get_device(struct wgdevice **device, const char *iface) { - struct wg_data_io wgdata = {.wgd_size = 0}; - struct wg_interface_io* wg_iface; - struct wg_peer_io* wg_peer; - struct wg_aip_io* wg_aip; - struct wgdevice* dev; - struct wgpeer* peer; - struct wgallowedip* aip; - int s = get_dgram_socket(), ret; + struct wg_data_io wgdata = { .wgd_size = 0 }; + struct wg_interface_io *wg_iface; + struct wg_peer_io *wg_peer; + struct wg_aip_io *wg_aip; + struct wgdevice *dev; + struct wgpeer *peer; + struct wgallowedip *aip; + int s = get_dgram_socket(), ret; - if (s < 0) - return -errno; + if (s < 0) + return -errno; - *device = NULL; - strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name)); - for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) - { - if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0) - goto out; - if (last_size >= wgdata.wgd_size) - break; - wgdata.wgd_interface = realloc(wgdata.wgd_interface, wgdata.wgd_size); - if (!wgdata.wgd_interface) - goto out; - } + *device = NULL; + strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name)); + for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) { + if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0) + goto out; + if (last_size >= wgdata.wgd_size) + break; + wgdata.wgd_interface = realloc(wgdata.wgd_interface, wgdata.wgd_size); + if (!wgdata.wgd_interface) + goto out; + } - wg_iface = wgdata.wgd_interface; - dev = calloc(1, sizeof(*dev)); - if (!dev) - goto out; - strlcpy(dev->name, iface, sizeof(dev->name)); + wg_iface = wgdata.wgd_interface; + dev = calloc(1, sizeof(*dev)); + if (!dev) + goto out; + strlcpy(dev->name, iface, sizeof(dev->name)); - if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE) - { - dev->fwmark = wg_iface->i_rtable; - dev->flags |= WGDEVICE_HAS_FWMARK; - } + if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE) { + dev->fwmark = wg_iface->i_rtable; + dev->flags |= WGDEVICE_HAS_FWMARK; + } - if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT) - { - dev->listen_port = wg_iface->i_port; - dev->flags |= WGDEVICE_HAS_LISTEN_PORT; - } + if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT) { + dev->listen_port = wg_iface->i_port; + dev->flags |= WGDEVICE_HAS_LISTEN_PORT; + } - if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC) - { - memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key)); - dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; - } + if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC) { + memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key)); + dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; + } - if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE) - { - memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key)); - dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; - } + if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE) { + memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key)); + dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC) - { - dev->junk_packet_count = wg_iface->i_junk_packet_count; - dev->flags |= WGDEVICE_HAS_JC; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC) { + dev->junk_packet_count = wg_iface->i_junk_packet_count; + dev->flags |= WGDEVICE_HAS_JC; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN) - { - dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size; - dev->flags |= WGDEVICE_HAS_JMIN; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN) { + dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size; + dev->flags |= WGDEVICE_HAS_JMIN; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX) - { - dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size; - dev->flags |= WGDEVICE_HAS_JMAX; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX) { + dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size; + dev->flags |= WGDEVICE_HAS_JMAX; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1) - { - dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size; - dev->flags |= WGDEVICE_HAS_S1; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1) { + dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size; + dev->flags |= WGDEVICE_HAS_S1; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2) - { - dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size; - dev->flags |= WGDEVICE_HAS_S2; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2) { + dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size; + dev->flags |= WGDEVICE_HAS_S2; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1) - { - dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header; - dev->flags |= WGDEVICE_HAS_H1; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1) { + dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header; + dev->flags |= WGDEVICE_HAS_H1; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2) - { - dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header; - dev->flags |= WGDEVICE_HAS_H2; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2) { + dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header; + dev->flags |= WGDEVICE_HAS_H2; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3) - { - dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header; - dev->flags |= WGDEVICE_HAS_H3; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3) { + dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header; + dev->flags |= WGDEVICE_HAS_H3; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4) - { - dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header; - dev->flags |= WGDEVICE_HAS_H4; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4) { + dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header; + dev->flags |= WGDEVICE_HAS_H4; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I1) - { - wg_iface->i_i1 = strdup(dev->i1); - wg_iface->i_flags |= WGDEVICE_HAS_I1; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I1) + { + wg_iface->i_i1 = strdup(dev->i1); + wg_iface->i_flags |= WGDEVICE_HAS_I1; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I2) - { - wg_iface->i_i2 = strdup(dev->i2); - wg_iface->i_flags |= WGDEVICE_HAS_I2; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I2) + { + wg_iface->i_i2 = strdup(dev->i2); + wg_iface->i_flags |= WGDEVICE_HAS_I2; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I3) - { - wg_iface->i_i3 = strdup(dev->i3); - wg_iface->i_flags |= WGDEVICE_HAS_I3; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I3) + { + wg_iface->i_i3 = strdup(dev->i3); + wg_iface->i_flags |= WGDEVICE_HAS_I3; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I4) - { - wg_iface->i_i4 = strdup(dev->i4); - wg_iface->i_flags |= WGDEVICE_HAS_I4; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I4) + { + wg_iface->i_i4 = strdup(dev->i4); + wg_iface->i_flags |= WGDEVICE_HAS_I4; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I5) - { - wg_iface->i_i5 = strdup(dev->i5); - wg_iface->i_flags |= WGDEVICE_HAS_I5; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I5) + { + wg_iface->i_i5 = strdup(dev->i5); + wg_iface->i_flags |= WGDEVICE_HAS_I5; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J1) - { - wg_iface->i_j1 = strdup(dev->j1); - wg_iface->i_flags |= WGDEVICE_HAS_J1; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J1) + { + wg_iface->i_j1 = strdup(dev->j1); + wg_iface->i_flags |= WGDEVICE_HAS_J1; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J2) - { - wg_iface->i_j2 = strdup(dev->j2); - wg_iface->i_flags |= WGDEVICE_HAS_J2; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J2) + { + wg_iface->i_j2 = strdup(dev->j2); + wg_iface->i_flags |= WGDEVICE_HAS_J2; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J3) - { - wg_iface->i_j3 = strdup(dev->j3); - wg_iface->i_flags |= WGDEVICE_HAS_J3; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J3) + { + wg_iface->i_j3 = strdup(dev->j3); + wg_iface->i_flags |= WGDEVICE_HAS_J3; + } - if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_ITIME) - { - wg_iface->i_itime = dev->itime; - wg_iface->i_flags |= WGDEVICE_HAS_ITIME; - } + if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_ITIME) + { + wg_iface->i_itime = dev->itime; + wg_iface->i_flags |= WGDEVICE_HAS_ITIME; + } - wg_peer = &wg_iface->i_peers[0]; - for (size_t i = 0; i < wg_iface->i_peers_count; ++i) - { - peer = calloc(1, sizeof(*peer)); - if (!peer) - goto out; + wg_peer = &wg_iface->i_peers[0]; + for (size_t i = 0; i < wg_iface->i_peers_count; ++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->p_flags & WG_PEER_HAS_PUBLIC) - { - memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key)); - peer->flags |= WGPEER_HAS_PUBLIC_KEY; - } + if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC) { + memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key)); + peer->flags |= WGPEER_HAS_PUBLIC_KEY; + } - if (wg_peer->p_flags & WG_PEER_HAS_PSK) - { - memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key)); - if (!key_is_zero(peer->preshared_key)) - peer->flags |= WGPEER_HAS_PRESHARED_KEY; - } + if (wg_peer->p_flags & WG_PEER_HAS_PSK) { + memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key)); + if (!key_is_zero(peer->preshared_key)) + peer->flags |= WGPEER_HAS_PRESHARED_KEY; + } - if (wg_peer->p_flags & WG_PEER_HAS_PKA) - { - peer->persistent_keepalive_interval = wg_peer->p_pka; - peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; - } + if (wg_peer->p_flags & WG_PEER_HAS_PKA) { + peer->persistent_keepalive_interval = wg_peer->p_pka; + peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; + } - if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT && - wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr)) - memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len); + if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT && wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr)) + memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len); - peer->rx_bytes = wg_peer->p_rxbytes; - peer->tx_bytes = wg_peer->p_txbytes; + peer->rx_bytes = wg_peer->p_rxbytes; + peer->tx_bytes = wg_peer->p_txbytes; - peer->last_handshake_time.tv_sec = wg_peer->p_last_handshake.tv_sec; - peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec; + peer->last_handshake_time.tv_sec = wg_peer->p_last_handshake.tv_sec; + peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec; - wg_aip = &wg_peer->p_aips[0]; - for (size_t j = 0; j < wg_peer->p_aips_count; ++j) - { - aip = calloc(1, sizeof(*aip)); - if (!aip) - goto out; + wg_aip = &wg_peer->p_aips[0]; + for (size_t j = 0; j < wg_peer->p_aips_count; ++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->a_af; - if (wg_aip->a_af == AF_INET) - { - memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4)); - aip->cidr = wg_aip->a_cidr; - } - else if (wg_aip->a_af == AF_INET6) - { - memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6)); - aip->cidr = wg_aip->a_cidr; - } - ++wg_aip; - } - wg_peer = (struct wg_peer_io*)wg_aip; - } - *device = dev; - errno = 0; + aip->family = wg_aip->a_af; + if (wg_aip->a_af == AF_INET) { + memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4)); + aip->cidr = wg_aip->a_cidr; + } else if (wg_aip->a_af == AF_INET6) { + memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6)); + aip->cidr = wg_aip->a_cidr; + } + ++wg_aip; + } + wg_peer = (struct wg_peer_io *)wg_aip; + } + *device = dev; + errno = 0; out: - ret = -errno; - free(wgdata.wgd_interface); - return ret; + ret = -errno; + free(wgdata.wgd_interface); + return ret; } -static int kernel_set_device(struct wgdevice* dev) +static int kernel_set_device(struct wgdevice *dev) { - struct wg_data_io wgdata = {.wgd_size = sizeof(struct wg_interface_io)}; - struct wg_interface_io* wg_iface; - struct wg_peer_io* wg_peer; - struct wg_aip_io* wg_aip; - struct wgpeer* peer; - struct wgallowedip* aip; - int s = get_dgram_socket(), ret; - size_t peer_count, aip_count; + struct wg_data_io wgdata = { .wgd_size = sizeof(struct wg_interface_io) }; + struct wg_interface_io *wg_iface; + struct wg_peer_io *wg_peer; + struct wg_aip_io *wg_aip; + struct wgpeer *peer; + struct wgallowedip *aip; + int s = get_dgram_socket(), ret; + size_t peer_count, aip_count; - if (s < 0) - return -errno; + if (s < 0) + return -errno; - for_each_wgpeer(dev, peer) - { - wgdata.wgd_size += sizeof(struct wg_peer_io); - for_each_wgallowedip(peer, aip) wgdata.wgd_size += sizeof(struct wg_aip_io); - } - wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size); - if (!wgdata.wgd_interface) - return -errno; - strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name)); + for_each_wgpeer(dev, peer) { + wgdata.wgd_size += sizeof(struct wg_peer_io); + for_each_wgallowedip(peer, aip) + wgdata.wgd_size += sizeof(struct wg_aip_io); + } + wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size); + if (!wgdata.wgd_interface) + return -errno; + strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name)); - if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) - { - memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private)); - wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE; - } + if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { + memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private)); + wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE; + } - if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) - { - wg_iface->i_port = dev->listen_port; - wg_iface->i_flags |= WG_INTERFACE_HAS_PORT; - } + if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) { + wg_iface->i_port = dev->listen_port; + wg_iface->i_flags |= WG_INTERFACE_HAS_PORT; + } - if (dev->flags & WGDEVICE_HAS_FWMARK) - { - wg_iface->i_rtable = dev->fwmark; - wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE; - } + if (dev->flags & WGDEVICE_HAS_FWMARK) { + wg_iface->i_rtable = dev->fwmark; + wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE; + } - if (dev->flags & WGDEVICE_REPLACE_PEERS) - wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS; + if (dev->flags & WGDEVICE_REPLACE_PEERS) + wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS; - if (dev->flags & WGDEVICE_HAS_JC) - { - wg_iface->i_junk_packet_count = dev->junk_packet_count; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC; - } - if (dev->flags & WGDEVICE_HAS_JMIN) - { - wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN; - } + if (dev->flags & WGDEVICE_HAS_JC) { + wg_iface->i_junk_packet_count = dev->junk_packet_count; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC; + } - if (dev->flags & WGDEVICE_HAS_JMAX) - { - wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX; - } + if (dev->flags & WGDEVICE_HAS_JMIN) { + wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN; + } - if (dev->flags & WGDEVICE_HAS_S1) - { - wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1; - } + if (dev->flags & WGDEVICE_HAS_JMAX) { + wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX; + } - if (dev->flags & WGDEVICE_HAS_S2) - { - wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2; - } + if (dev->flags & WGDEVICE_HAS_S1) { + wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1; + } - if (dev->flags & WGDEVICE_HAS_H1) - { - wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1; - } + if (dev->flags & WGDEVICE_HAS_S2) { + wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2; + } - if (dev->flags & WGDEVICE_HAS_H2) - { - wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2; - } + if (dev->flags & WGDEVICE_HAS_H1) { + wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1; + } - if (dev->flags & WGDEVICE_HAS_H3) - { - wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3; - } + if (dev->flags & WGDEVICE_HAS_H2) { + wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2; + } - if (dev->flags & WGDEVICE_HAS_H4) - { - wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H4; - } + if (dev->flags & WGDEVICE_HAS_H3) { + wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3; + } - if (dev->flags & WGDEVICE_HAS_I1) - { - wg_iface->i_i1 = strdup(dev->i1); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I1; - } + if (dev->flags & WGDEVICE_HAS_H4) { + wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H4; + } - if (dev->flags & WGDEVICE_HAS_I2) - { - wg_iface->i_i2 = strdup(dev->i2); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I2; - } + if (dev->flags & WGDEVICE_HAS_I1) + { + wg_iface->i_i1 = strdup(dev->i1); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I1; + } - if (dev->flags & WGDEVICE_HAS_I3) - { - wg_iface->i_i3 = strdup(dev->i3); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I3; - } + if (dev->flags & WGDEVICE_HAS_I2) + { + wg_iface->i_i2 = strdup(dev->i2); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I2; + } - if (dev->flags & WGDEVICE_HAS_I4) - { - wg_iface->i_i4 = strdup(dev->i4); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I4; - } + if (dev->flags & WGDEVICE_HAS_I3) + { + wg_iface->i_i3 = strdup(dev->i3); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I3; + } - if (dev->flags & WGDEVICE_HAS_I5) - { - wg_iface->i_i5 = strdup(dev->i5); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I5; - } + if (dev->flags & WGDEVICE_HAS_I4) + { + wg_iface->i_i4 = strdup(dev->i4); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I4; + } - if (dev->flags & WGDEVICE_HAS_J1) - { - wg_iface->i_j1 = strdup(dev->j1); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J1; - } + if (dev->flags & WGDEVICE_HAS_I5) + { + wg_iface->i_i5 = strdup(dev->i5); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I5; + } - if (dev->flags & WGDEVICE_HAS_J2) - { - wg_iface->i_j2 = strdup(dev->j2); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J2; - } + if (dev->flags & WGDEVICE_HAS_J1) + { + wg_iface->i_j1 = strdup(dev->j1); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J1; + } - if (dev->flags & WGDEVICE_HAS_J3) - { - wg_iface->i_j3 = strdup(dev->j3); - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J3; - } + if (dev->flags & WGDEVICE_HAS_J2) + { + wg_iface->i_j2 = strdup(dev->j2); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J2; + } - if (dev->flags & WGDEVICE_HAS_ITIME) - { - wg_iface->i_itime = dev->itime; - wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_ITIME; - } + if (dev->flags & WGDEVICE_HAS_J3) + { + wg_iface->i_j3 = strdup(dev->j3); + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J3; + } - peer_count = 0; - wg_peer = &wg_iface->i_peers[0]; - for_each_wgpeer(dev, peer) - { - wg_peer->p_flags = WG_PEER_HAS_PUBLIC; - memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public)); + if (dev->flags & WGDEVICE_HAS_ITIME) + { + wg_iface->i_itime = dev->itime; + wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_ITIME; + } - if (peer->flags & WGPEER_HAS_PRESHARED_KEY) - { - memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk)); - wg_peer->p_flags |= WG_PEER_HAS_PSK; - } + peer_count = 0; + wg_peer = &wg_iface->i_peers[0]; + for_each_wgpeer(dev, peer) { + wg_peer->p_flags = WG_PEER_HAS_PUBLIC; + memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public)); - if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) - { - wg_peer->p_pka = peer->persistent_keepalive_interval; - wg_peer->p_flags |= WG_PEER_HAS_PKA; - } + if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { + memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk)); + wg_peer->p_flags |= WG_PEER_HAS_PSK; + } - if ((peer->endpoint.addr.sa_family == AF_INET || - peer->endpoint.addr.sa_family == AF_INET6) && - peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint)) - { - memcpy( - &wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len); - wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT; - } + if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) { + wg_peer->p_pka = peer->persistent_keepalive_interval; + wg_peer->p_flags |= WG_PEER_HAS_PKA; + } - if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - wg_peer->p_flags |= WG_PEER_REPLACE_AIPS; + if ((peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) && + peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint)) { + memcpy(&wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len); + wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT; + } - if (peer->flags & WGPEER_REMOVE_ME) - wg_peer->p_flags |= WG_PEER_REMOVE; + if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) + wg_peer->p_flags |= WG_PEER_REPLACE_AIPS; - aip_count = 0; - wg_aip = &wg_peer->p_aips[0]; - for_each_wgallowedip(peer, aip) - { - wg_aip->a_af = aip->family; - wg_aip->a_cidr = aip->cidr; + if (peer->flags & WGPEER_REMOVE_ME) + wg_peer->p_flags |= WG_PEER_REMOVE; - if (aip->family == AF_INET) - memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(wg_aip->a_ipv4)); - else if (aip->family == AF_INET6) - memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(wg_aip->a_ipv6)); - else - continue; - ++aip_count; - ++wg_aip; - } - wg_peer->p_aips_count = aip_count; - ++peer_count; - wg_peer = (struct wg_peer_io*)wg_aip; - } - wg_iface->i_peers_count = peer_count; + aip_count = 0; + wg_aip = &wg_peer->p_aips[0]; + for_each_wgallowedip(peer, aip) { + wg_aip->a_af = aip->family; + wg_aip->a_cidr = aip->cidr; - if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) < 0) - goto out; - errno = 0; + if (aip->family == AF_INET) + memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(wg_aip->a_ipv4)); + else if (aip->family == AF_INET6) + memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(wg_aip->a_ipv6)); + else + continue; + ++aip_count; + ++wg_aip; + } + wg_peer->p_aips_count = aip_count; + ++peer_count; + wg_peer = (struct wg_peer_io *)wg_aip; + } + wg_iface->i_peers_count = peer_count; + + if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) < 0) + goto out; + errno = 0; out: - ret = -errno; - free(wgdata.wgd_interface); - return ret; + ret = -errno; + free(wgdata.wgd_interface); + return ret; } diff --git a/src/ipc-uapi.h b/src/ipc-uapi.h index 563243f..2060c51 100644 --- a/src/ipc-uapi.h +++ b/src/ipc-uapi.h @@ -3,10 +3,6 @@ * Copyright (C) 2015-2020 Jason A. Donenfeld . All Rights Reserved. */ -#include "containers.h" -#include "ctype.h" -#include "curve25519.h" -#include "encoding.h" #include #include #include @@ -18,6 +14,10 @@ #include #include #include +#include "containers.h" +#include "curve25519.h" +#include "encoding.h" +#include "ctype.h" #ifdef _WIN32 #include "ipc-uapi-windows.h" @@ -25,467 +25,381 @@ #include "ipc-uapi-unix.h" #endif -static int userspace_set_device(struct wgdevice* dev) +static int userspace_set_device(struct wgdevice *dev) { - char hex[WG_KEY_LEN_HEX], ip[INET6_ADDRSTRLEN], host[4096 + 1], service[512 + 1]; - struct wgpeer* peer; - struct wgallowedip* allowedip; - FILE* f; - int ret, set_errno = -EPROTO; - socklen_t addr_len; - size_t line_buffer_len = 0, line_len; - char * key = NULL, *value; + char hex[WG_KEY_LEN_HEX], ip[INET6_ADDRSTRLEN], host[4096 + 1], service[512 + 1]; + struct wgpeer *peer; + struct wgallowedip *allowedip; + FILE *f; + int ret, set_errno = -EPROTO; + socklen_t addr_len; + size_t line_buffer_len = 0, line_len; + char *key = NULL, *value; - f = userspace_interface_file(dev->name); - if (!f) - return -errno; - fprintf(f, "set=1\n"); + f = userspace_interface_file(dev->name); + if (!f) + return -errno; + fprintf(f, "set=1\n"); - if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) - { - key_to_hex(hex, dev->private_key); - fprintf(f, "private_key=%s\n", hex); - } - if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) - fprintf(f, "listen_port=%u\n", dev->listen_port); - if (dev->flags & WGDEVICE_HAS_FWMARK) - fprintf(f, "fwmark=%u\n", dev->fwmark); - if (dev->flags & WGDEVICE_REPLACE_PEERS) - fprintf(f, "replace_peers=true\n"); - if (dev->flags & WGDEVICE_HAS_JC) - fprintf(f, "jc=%u\n", dev->junk_packet_count); - if (dev->flags & WGDEVICE_HAS_JMIN) - fprintf(f, "jmin=%u\n", dev->junk_packet_min_size); - if (dev->flags & WGDEVICE_HAS_JMAX) - fprintf(f, "jmax=%u\n", dev->junk_packet_max_size); - if (dev->flags & WGDEVICE_HAS_S1) - fprintf(f, "s1=%u\n", dev->init_packet_junk_size); - if (dev->flags & WGDEVICE_HAS_S2) - fprintf(f, "s2=%u\n", dev->response_packet_junk_size); - if (dev->flags & WGDEVICE_HAS_H1) - fprintf(f, "h1=%u\n", dev->init_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H2) - fprintf(f, "h2=%u\n", dev->response_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H3) - fprintf(f, "h3=%u\n", dev->underload_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_H4) - fprintf(f, "h4=%u\n", dev->transport_packet_magic_header); - if (dev->flags & WGDEVICE_HAS_I1) - fprintf(f, "i1=%s\n", dev->i1); - if (dev->flags & WGDEVICE_HAS_I2) - fprintf(f, "i2=%s\n", dev->i2); - if (dev->flags & WGDEVICE_HAS_I3) - fprintf(f, "i3=%s\n", dev->i3); - if (dev->flags & WGDEVICE_HAS_I4) - fprintf(f, "i4=%s\n", dev->i4); - if (dev->flags & WGDEVICE_HAS_I5) - fprintf(f, "i5=%s\n", dev->i5); - if (dev->flags & WGDEVICE_HAS_J1) - fprintf(f, "j1=%s\n", dev->j1); - if (dev->flags & WGDEVICE_HAS_J2) - fprintf(f, "j2=%s\n", dev->j2); - if (dev->flags & WGDEVICE_HAS_J3) - fprintf(f, "j3=%s\n", dev->j3); - if (dev->flags & WGDEVICE_HAS_ITIME) - fprintf(f, "itime=%u\n", dev->itime); + if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { + key_to_hex(hex, dev->private_key); + fprintf(f, "private_key=%s\n", hex); + } + if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) + fprintf(f, "listen_port=%u\n", dev->listen_port); + if (dev->flags & WGDEVICE_HAS_FWMARK) + fprintf(f, "fwmark=%u\n", dev->fwmark); + if (dev->flags & WGDEVICE_REPLACE_PEERS) + fprintf(f, "replace_peers=true\n"); + if (dev->flags & WGDEVICE_HAS_JC) + fprintf(f, "jc=%u\n", dev->junk_packet_count); + if (dev->flags & WGDEVICE_HAS_JMIN) + fprintf(f, "jmin=%u\n", dev->junk_packet_min_size); + if (dev->flags & WGDEVICE_HAS_JMAX) + fprintf(f, "jmax=%u\n", dev->junk_packet_max_size); + if (dev->flags & WGDEVICE_HAS_S1) + fprintf(f, "s1=%u\n", dev->init_packet_junk_size); + if (dev->flags & WGDEVICE_HAS_S2) + fprintf(f, "s2=%u\n", dev->response_packet_junk_size); + if (dev->flags & WGDEVICE_HAS_H1) + fprintf(f, "h1=%u\n", dev->init_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H2) + fprintf(f, "h2=%u\n", dev->response_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H3) + fprintf(f, "h3=%u\n", dev->underload_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_H4) + fprintf(f, "h4=%u\n", dev->transport_packet_magic_header); - printf("i1: %s\n", dev->i1); + if (dev->flags & WGDEVICE_HAS_I1) + fprintf(f, "i1=%s\n", dev->i1); + if (dev->flags & WGDEVICE_HAS_I2) + fprintf(f, "i2=%s\n", dev->i2); + if (dev->flags & WGDEVICE_HAS_I3) + fprintf(f, "i3=%s\n", dev->i3); + if (dev->flags & WGDEVICE_HAS_I4) + fprintf(f, "i4=%s\n", dev->i4); + if (dev->flags & WGDEVICE_HAS_I5) + fprintf(f, "i5=%s\n", dev->i5); + if (dev->flags & WGDEVICE_HAS_J1) + fprintf(f, "j1=%s\n", dev->j1); + if (dev->flags & WGDEVICE_HAS_J2) + fprintf(f, "j2=%s\n", dev->j2); + if (dev->flags & WGDEVICE_HAS_J3) + fprintf(f, "j3=%s\n", dev->j3); + if (dev->flags & WGDEVICE_HAS_ITIME) + fprintf(f, "itime=%u\n", dev->itime); - for_each_wgpeer(dev, peer) - { - key_to_hex(hex, peer->public_key); - fprintf(f, "public_key=%s\n", hex); - if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) - { - 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"); - continue; - } - if (peer->flags & WGPEER_HAS_PRESHARED_KEY) - { - key_to_hex(hex, peer->preshared_key); - fprintf(f, "preshared_key=%s\n", hex); - } - if (peer->endpoint.addr.sa_family == AF_INET || - peer->endpoint.addr.sa_family == AF_INET6) - { - addr_len = 0; - if (peer->endpoint.addr.sa_family == AF_INET) - addr_len = sizeof(struct sockaddr_in); - else if (peer->endpoint.addr.sa_family == AF_INET6) - addr_len = sizeof(struct sockaddr_in6); - if (!getnameinfo( - &peer->endpoint.addr, - addr_len, - host, - sizeof(host), - service, - sizeof(service), - NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) - { - if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':')) - fprintf(f, "endpoint=[%s]:%s\n", host, service); - else - fprintf(f, "endpoint=%s:%s\n", host, service); - } - } - if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) - fprintf( - f, - "persistent_keepalive_interval=%u\n", - peer->persistent_keepalive_interval); - if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - fprintf(f, "replace_allowed_ips=true\n"); - for_each_wgallowedip(peer, allowedip) - { - if (allowedip->family == AF_INET) - { - if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN)) - continue; - } - else if (allowedip->family == AF_INET6) - { - if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN)) - continue; - } - else - continue; - fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr); - } - } - fprintf(f, "\n"); - fflush(f); + for_each_wgpeer(dev, peer) { + key_to_hex(hex, peer->public_key); + fprintf(f, "public_key=%s\n", hex); + if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) { + 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"); + continue; + } + if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { + key_to_hex(hex, peer->preshared_key); + fprintf(f, "preshared_key=%s\n", hex); + } + if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) { + addr_len = 0; + if (peer->endpoint.addr.sa_family == AF_INET) + addr_len = sizeof(struct sockaddr_in); + else if (peer->endpoint.addr.sa_family == AF_INET6) + addr_len = sizeof(struct sockaddr_in6); + if (!getnameinfo(&peer->endpoint.addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) { + if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':')) + fprintf(f, "endpoint=[%s]:%s\n", host, service); + else + fprintf(f, "endpoint=%s:%s\n", host, service); + } + } + if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) + fprintf(f, "persistent_keepalive_interval=%u\n", peer->persistent_keepalive_interval); + if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) + fprintf(f, "replace_allowed_ips=true\n"); + for_each_wgallowedip(peer, allowedip) { + if (allowedip->family == AF_INET) { + if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN)) + continue; + } else if (allowedip->family == AF_INET6) { + if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN)) + continue; + } else + continue; + fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr); + } + } + fprintf(f, "\n"); + fflush(f); - while (getline(&key, &line_buffer_len, f) > 0) - { - line_len = strlen(key); - ret = set_errno; - if (line_len == 1 && key[0] == '\n') - goto out; - value = strchr(key, '='); - if (!value || line_len == 0 || key[line_len - 1] != '\n') - break; - *value++ = key[--line_len] = '\0'; + while (getline(&key, &line_buffer_len, f) > 0) { + line_len = strlen(key); + ret = set_errno; + if (line_len == 1 && key[0] == '\n') + goto out; + value = strchr(key, '='); + if (!value || line_len == 0 || key[line_len - 1] != '\n') + break; + *value++ = key[--line_len] = '\0'; - if (!strcmp(key, "errno")) - { - long long num; - char* end; - if (value[0] != '-' && !char_is_digit(value[0])) - break; - num = strtoll(value, &end, 10); - if (*end || num > INT_MAX || num < INT_MIN) - break; - set_errno = num; - } - } - ret = errno ? -errno : -EPROTO; + if (!strcmp(key, "errno")) { + long long num; + char *end; + if (value[0] != '-' && !char_is_digit(value[0])) + break; + num = strtoll(value, &end, 10); + if (*end || num > INT_MAX || num < INT_MIN) + break; + set_errno = num; + } + } + ret = errno ? -errno : -EPROTO; out: - free(key); - fclose(f); - errno = -ret; - return ret; + free(key); + fclose(f); + errno = -ret; + return ret; } -#define NUM(max) \ - ({ \ - unsigned long long num; \ - char* end; \ - if (!char_is_digit(value[0])) \ - break; \ - num = strtoull(value, &end, 10); \ - if (*end || num > max) \ - break; \ - num; \ - }) +#define NUM(max) ({ \ + unsigned long long num; \ + char *end; \ + if (!char_is_digit(value[0])) \ + break; \ + num = strtoull(value, &end, 10); \ + if (*end || num > max) \ + break; \ + num; \ +}) -static int userspace_get_device(struct wgdevice** out, const char* iface) +static int userspace_get_device(struct wgdevice **out, const char *iface) { - struct wgdevice* dev; - struct wgpeer* peer = NULL; - struct wgallowedip* allowedip = NULL; - size_t line_buffer_len = 0, line_len; - char * key = NULL, *value; - FILE* f; - int ret = -EPROTO; + struct wgdevice *dev; + struct wgpeer *peer = NULL; + struct wgallowedip *allowedip = NULL; + size_t line_buffer_len = 0, line_len; + char *key = NULL, *value; + FILE *f; + int ret = -EPROTO; - *out = dev = calloc(1, sizeof(*dev)); - if (!dev) - return -errno; + *out = dev = calloc(1, sizeof(*dev)); + if (!dev) + return -errno; - f = userspace_interface_file(iface); - if (!f) - { - ret = -errno; - free(dev); - *out = NULL; - return ret; - } + f = userspace_interface_file(iface); + if (!f) { + ret = -errno; + free(dev); + *out = NULL; + return ret; + } - fprintf(f, "get=1\n\n"); - fflush(f); + fprintf(f, "get=1\n\n"); + fflush(f); - strncpy(dev->name, iface, IFNAMSIZ - 1); - dev->name[IFNAMSIZ - 1] = '\0'; + strncpy(dev->name, iface, IFNAMSIZ - 1); + dev->name[IFNAMSIZ - 1] = '\0'; - while (getline(&key, &line_buffer_len, f) > 0) - { - line_len = strlen(key); - if (line_len == 1 && key[0] == '\n') - goto err; - value = strchr(key, '='); - if (!value || line_len == 0 || key[line_len - 1] != '\n') - break; - *value++ = key[--line_len] = '\0'; + while (getline(&key, &line_buffer_len, f) > 0) { + line_len = strlen(key); + if (line_len == 1 && key[0] == '\n') + goto err; + value = strchr(key, '='); + if (!value || line_len == 0 || key[line_len - 1] != '\n') + break; + *value++ = key[--line_len] = '\0'; - if (!peer && !strcmp(key, "private_key")) - { - if (!key_from_hex(dev->private_key, value)) - break; - curve25519_generate_public(dev->public_key, dev->private_key); - dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY; - } - else if (!peer && !strcmp(key, "listen_port")) - { - dev->listen_port = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_LISTEN_PORT; - } - else if (!peer && !strcmp(key, "fwmark")) - { - dev->fwmark = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_FWMARK; - } - else if (!peer && !strcmp(key, "jc")) - { - dev->junk_packet_count = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_JC; - } - else if (!peer && !strcmp(key, "jmin")) - { - dev->junk_packet_min_size = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_JMIN; - } - else if (!peer && !strcmp(key, "jmax")) - { - dev->junk_packet_max_size = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_JMAX; - } - else if (!peer && !strcmp(key, "s1")) - { - dev->init_packet_junk_size = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_S1; - } - else if (!peer && !strcmp(key, "s2")) - { - dev->response_packet_junk_size = NUM(0xffffU); - dev->flags |= WGDEVICE_HAS_S2; - } - else if (!peer && !strcmp(key, "h1")) - { - dev->init_packet_magic_header = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_H1; - } - else if (!peer && !strcmp(key, "h2")) - { - dev->response_packet_magic_header = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_H2; - } - else if (!peer && !strcmp(key, "h3")) - { - dev->underload_packet_magic_header = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_H3; - } - else if (!peer && !strcmp(key, "h4")) - { - dev->transport_packet_magic_header = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_H4; - } - else if (!peer && !strcmp(key, "i1")) - { - dev->i1 = strdup(value); - dev->flags |= WGDEVICE_HAS_I1; - } - else if (!peer && !strcmp(key, "i2")) - { - dev->i2 = strdup(value); - dev->flags |= WGDEVICE_HAS_I2; - } - else if (!peer && !strcmp(key, "i3")) - { - dev->i3 = strdup(value); - dev->flags |= WGDEVICE_HAS_I3; - } - else if (!peer && !strcmp(key, "i4")) - { - dev->i4 = strdup(value); - dev->flags |= WGDEVICE_HAS_I4; - } - else if (!peer && !strcmp(key, "i5")) - { - dev->i5 = strdup(value); - dev->flags |= WGDEVICE_HAS_I5; - } - else if (!peer && !strcmp(key, "j1")) - { - dev->j1 = strdup(value); - dev->flags |= WGDEVICE_HAS_J1; - } - else if (!peer && !strcmp(key, "j2")) - { - dev->j2 = strdup(value); - dev->flags |= WGDEVICE_HAS_J2; - } - else if (!peer && !strcmp(key, "j3")) - { - dev->j3 = strdup(value); - dev->flags |= WGDEVICE_HAS_J3; - } - else if (!peer && !strcmp(key, "itime")) - { - dev->itime = NUM(0xffffffffU); - dev->flags |= WGDEVICE_HAS_ITIME; - } - else if (!strcmp(key, "public_key")) - { - struct wgpeer* new_peer = calloc(1, sizeof(*new_peer)); + if (!peer && !strcmp(key, "private_key")) { + if (!key_from_hex(dev->private_key, value)) + break; + curve25519_generate_public(dev->public_key, dev->private_key); + dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY; + } else if (!peer && !strcmp(key, "listen_port")) { + dev->listen_port = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_LISTEN_PORT; + } else if (!peer && !strcmp(key, "fwmark")) { + dev->fwmark = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_FWMARK; + } else if(!peer && !strcmp(key, "jc")) { + dev->junk_packet_count = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_JC; + } else if(!peer && !strcmp(key, "jmin")) { + dev->junk_packet_min_size = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_JMIN; + } else if(!peer && !strcmp(key, "jmax")) { + dev->junk_packet_max_size = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_JMAX; + } else if(!peer && !strcmp(key, "s1")) { + dev->init_packet_junk_size = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_S1; + } else if(!peer && !strcmp(key, "s2")) { + dev->response_packet_junk_size = NUM(0xffffU); + dev->flags |= WGDEVICE_HAS_S2; + } else if(!peer && !strcmp(key, "h1")) { + dev->init_packet_magic_header = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_H1; + } else if(!peer && !strcmp(key, "h2")) { + dev->response_packet_magic_header = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_H2; + } else if(!peer && !strcmp(key, "h3")) { + dev->underload_packet_magic_header = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_H3; + } else if(!peer && !strcmp(key, "h4")) { + dev->transport_packet_magic_header = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_H4; + } else if (!peer && !strcmp(key, "i1")) { + dev->i1 = strdup(value); + dev->flags |= WGDEVICE_HAS_I1; + } + else if (!peer && !strcmp(key, "i2")) { + dev->i2 = strdup(value); + dev->flags |= WGDEVICE_HAS_I2; + } + else if (!peer && !strcmp(key, "i3")) { + dev->i3 = strdup(value); + dev->flags |= WGDEVICE_HAS_I3; + } + else if (!peer && !strcmp(key, "i4")) { + dev->i4 = strdup(value); + dev->flags |= WGDEVICE_HAS_I4; + } + else if (!peer && !strcmp(key, "i5")) { + dev->i5 = strdup(value); + dev->flags |= WGDEVICE_HAS_I5; + } + else if (!peer && !strcmp(key, "j1")) { + dev->j1 = strdup(value); + dev->flags |= WGDEVICE_HAS_J1; + } + else if (!peer && !strcmp(key, "j2")) { + dev->j2 = strdup(value); + dev->flags |= WGDEVICE_HAS_J2; + } + else if (!peer && !strcmp(key, "j3")) { + dev->j3 = strdup(value); + dev->flags |= WGDEVICE_HAS_J3; + } + else if (!peer && !strcmp(key, "itime")) { + dev->itime = NUM(0xffffffffU); + dev->flags |= WGDEVICE_HAS_ITIME; + } else if (!strcmp(key, "public_key")) { + struct wgpeer *new_peer = calloc(1, sizeof(*new_peer)); - if (!new_peer) - { - ret = -ENOMEM; - goto err; - } - allowedip = NULL; - if (peer) - peer->next_peer = new_peer; - else - dev->first_peer = new_peer; - peer = new_peer; - if (!key_from_hex(peer->public_key, value)) - break; - peer->flags |= WGPEER_HAS_PUBLIC_KEY; - } - else if (peer && !strcmp(key, "preshared_key")) - { - if (!key_from_hex(peer->preshared_key, value)) - break; - if (!key_is_zero(peer->preshared_key)) - peer->flags |= WGPEER_HAS_PRESHARED_KEY; - } - else if (peer && !strcmp(key, "endpoint")) - { - char * begin, *end; - struct addrinfo* resolved; - struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_DGRAM, - .ai_protocol = IPPROTO_UDP}; - if (!strlen(value)) - break; - if (value[0] == '[') - { - begin = &value[1]; - end = strchr(value, ']'); - if (!end) - break; - *end++ = '\0'; - if (*end++ != ':' || !*end) - break; - } - else - { - begin = value; - end = strrchr(value, ':'); - if (!end || !*(end + 1)) - break; - *end++ = '\0'; - } - if (getaddrinfo(begin, end, &hints, &resolved) != 0) - { - ret = ENETUNREACH; - goto err; - } - if ((resolved->ai_family == AF_INET && - resolved->ai_addrlen == sizeof(struct sockaddr_in)) || - (resolved->ai_family == AF_INET6 && - resolved->ai_addrlen == sizeof(struct sockaddr_in6))) - memcpy(&peer->endpoint.addr, resolved->ai_addr, resolved->ai_addrlen); - else - { - freeaddrinfo(resolved); - break; - } - freeaddrinfo(resolved); - } - else if (peer && !strcmp(key, "persistent_keepalive_interval")) - { - peer->persistent_keepalive_interval = NUM(0xffffU); - peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; - } - else if (peer && !strcmp(key, "allowed_ip")) - { - struct wgallowedip* new_allowedip; - char * end, *mask = value, *ip = strsep(&mask, "/"); + if (!new_peer) { + ret = -ENOMEM; + goto err; + } + allowedip = NULL; + if (peer) + peer->next_peer = new_peer; + else + dev->first_peer = new_peer; + peer = new_peer; + if (!key_from_hex(peer->public_key, value)) + break; + peer->flags |= WGPEER_HAS_PUBLIC_KEY; + } else if (peer && !strcmp(key, "preshared_key")) { + if (!key_from_hex(peer->preshared_key, value)) + break; + if (!key_is_zero(peer->preshared_key)) + peer->flags |= WGPEER_HAS_PRESHARED_KEY; + } else if (peer && !strcmp(key, "endpoint")) { + char *begin, *end; + struct addrinfo *resolved; + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_DGRAM, + .ai_protocol = IPPROTO_UDP + }; + if (!strlen(value)) + break; + if (value[0] == '[') { + begin = &value[1]; + end = strchr(value, ']'); + if (!end) + break; + *end++ = '\0'; + if (*end++ != ':' || !*end) + break; + } else { + begin = value; + end = strrchr(value, ':'); + if (!end || !*(end + 1)) + break; + *end++ = '\0'; + } + if (getaddrinfo(begin, end, &hints, &resolved) != 0) { + ret = ENETUNREACH; + goto err; + } + if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) || + (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6))) + memcpy(&peer->endpoint.addr, resolved->ai_addr, resolved->ai_addrlen); + else { + freeaddrinfo(resolved); + break; + } + freeaddrinfo(resolved); + } else if (peer && !strcmp(key, "persistent_keepalive_interval")) { + peer->persistent_keepalive_interval = NUM(0xffffU); + peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; + } else if (peer && !strcmp(key, "allowed_ip")) { + struct wgallowedip *new_allowedip; + char *end, *mask = value, *ip = strsep(&mask, "/"); - if (!mask || !char_is_digit(mask[0])) - break; - new_allowedip = calloc(1, sizeof(*new_allowedip)); - if (!new_allowedip) - { - ret = -ENOMEM; - goto err; - } - if (allowedip) - allowedip->next_allowedip = new_allowedip; - else - peer->first_allowedip = new_allowedip; - allowedip = new_allowedip; - allowedip->family = AF_UNSPEC; - if (strchr(ip, ':')) - { - if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1) - allowedip->family = AF_INET6; - } - else - { - if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1) - allowedip->family = AF_INET; - } - allowedip->cidr = strtoul(mask, &end, 10); - if (*end || allowedip->family == AF_UNSPEC || - (allowedip->family == AF_INET6 && allowedip->cidr > 128) || - (allowedip->family == AF_INET && allowedip->cidr > 32)) - break; - } - else if (peer && !strcmp(key, "last_handshake_time_sec")) - peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL); - else if (peer && !strcmp(key, "last_handshake_time_nsec")) - peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL); - else if (peer && !strcmp(key, "rx_bytes")) - peer->rx_bytes = NUM(0xffffffffffffffffULL); - else if (peer && !strcmp(key, "tx_bytes")) - peer->tx_bytes = NUM(0xffffffffffffffffULL); - else if (!strcmp(key, "errno")) - ret = -NUM(0x7fffffffU); - } - ret = -EPROTO; + if (!mask || !char_is_digit(mask[0])) + break; + new_allowedip = calloc(1, sizeof(*new_allowedip)); + if (!new_allowedip) { + ret = -ENOMEM; + goto err; + } + if (allowedip) + allowedip->next_allowedip = new_allowedip; + else + peer->first_allowedip = new_allowedip; + allowedip = new_allowedip; + allowedip->family = AF_UNSPEC; + if (strchr(ip, ':')) { + if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1) + allowedip->family = AF_INET6; + } else { + if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1) + allowedip->family = AF_INET; + } + allowedip->cidr = strtoul(mask, &end, 10); + if (*end || allowedip->family == AF_UNSPEC || (allowedip->family == AF_INET6 && allowedip->cidr > 128) || (allowedip->family == AF_INET && allowedip->cidr > 32)) + break; + } else if (peer && !strcmp(key, "last_handshake_time_sec")) + peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL); + else if (peer && !strcmp(key, "last_handshake_time_nsec")) + peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL); + else if (peer && !strcmp(key, "rx_bytes")) + peer->rx_bytes = NUM(0xffffffffffffffffULL); + else if (peer && !strcmp(key, "tx_bytes")) + peer->tx_bytes = NUM(0xffffffffffffffffULL); + else if (!strcmp(key, "errno")) + ret = -NUM(0x7fffffffU); + } + ret = -EPROTO; err: - free(key); - if (ret) - { - free_wgdevice(dev); - *out = NULL; - } - fclose(f); - errno = -ret; - return ret; + free(key); + if (ret) { + free_wgdevice(dev); + *out = NULL; + } + fclose(f); + errno = -ret; + return ret; + } #undef NUM diff --git a/src/ipc-windows.h b/src/ipc-windows.h index b269f1b..99d9a48 100644 --- a/src/ipc-windows.h +++ b/src/ipc-windows.h @@ -4,774 +4,652 @@ */ #include "containers.h" -#include -#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_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; - } + 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 & WG_DEVICE_HAS_I1) - { - const size_t i1_size = strlen(dev->i1) + 1; - wg_iface->I1 = (UCHAR*)malloc(i1_size); - 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) + 1; - wg_iface->I2 = (UCHAR*)malloc(i2_size); - 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) + 1; - wg_iface->I3 = (UCHAR*)malloc(i3_size); - 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) + 1; - wg_iface->I4 = (UCHAR*)malloc(i4_size); - 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) + 1; - wg_iface->I5 = (UCHAR*)malloc(i5_size); - 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) + 1; - wg_iface->J1 = (UCHAR*)malloc(j1_size); - 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) + 1; - wg_iface->J2 = (UCHAR*)malloc(j2_size); - 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) + 1; - wg_iface->J3 = (UCHAR*)malloc(j3_size); - 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; - } + if (dev->flags & WGDEVICE_HAS_H4) { + wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header; + wg_iface->Flags |= WG_IOCTL_INTERFACE_H4; + } - 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 (dev->flags & WG_DEVICE_HAS_I1) + { + const size_t i1_size = strlen(dev->i1) + 1; + wg_iface->I1 = (UCHAR*)malloc(i1_size); + 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) + 1; + wg_iface->I2 = (UCHAR*)malloc(i2_size); + 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) + 1; + wg_iface->I3 = (UCHAR*)malloc(i3_size); + 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) + 1; + wg_iface->I4 = (UCHAR*)malloc(i4_size); + 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) + 1; + wg_iface->I5 = (UCHAR*)malloc(i5_size); + 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) + 1; + wg_iface->J1 = (UCHAR*)malloc(j1_size); + 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) + 1; + wg_iface->J2 = (UCHAR*)malloc(j2_size); + 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) + 1; + wg_iface->J3 = (UCHAR*)malloc(j3_size); + 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; + } - 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; - } + 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_PERSISTENT_KEEPALIVE_INTERVAL) - { - wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval; - wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE; - } + 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->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_HAS_PERSISTENT_KEEPALIVE_INTERVAL) { + wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval; + wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE; + } - if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS; + 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_REMOVE_ME) - wg_peer->Flags |= WG_IOCTL_PEER_REMOVE; + if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) + wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS; - 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 (peer->flags & WGPEER_REMOVE_ME) + wg_peer->Flags |= WG_IOCTL_PEER_REMOVE; - 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; + 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 (!DeviceIoControl( - handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) - { - errno = EACCES; - goto out; - } - errno = 0; + 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; 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 08f1382..f9729ee 100644 --- a/src/netlink.h +++ b/src/netlink.h @@ -6,853 +6,792 @@ /* 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 +#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) { return len + MNL_NLMSG_HDRLEN; } - -static struct nlmsghdr* mnl_nlmsg_put_header(void* buf) +static size_t mnl_nlmsg_size(size_t len) { - int len = MNL_ALIGN(sizeof(struct nlmsghdr)); - struct nlmsghdr* nlh = buf; - - memset(buf, 0, len); - nlh->nlmsg_len = len; - return nlh; + return len + MNL_NLMSG_HDRLEN; } -static void* mnl_nlmsg_put_extra_header(struct nlmsghdr* nlh, size_t size) +static struct nlmsghdr *mnl_nlmsg_put_header(void *buf) { - char* ptr = (char*)nlh + nlh->nlmsg_len; - size_t len = MNL_ALIGN(size); - nlh->nlmsg_len += len; - memset(ptr, 0, len); - return ptr; + int len = MNL_ALIGN(sizeof(struct nlmsghdr)); + struct nlmsghdr *nlh = buf; + + memset(buf, 0, len); + nlh->nlmsg_len = len; + return nlh; } -static void* mnl_nlmsg_get_payload(const struct nlmsghdr* nlh) +static void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size) { - return (void*)nlh + MNL_NLMSG_HDRLEN; + 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_get_payload_offset(const struct nlmsghdr* nlh, size_t offset) +static void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh) { - return (void*)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); + return (void *)nlh + MNL_NLMSG_HDRLEN; } -static bool mnl_nlmsg_ok(const struct nlmsghdr* nlh, int len) +static void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset) { - return len >= (int)sizeof(struct nlmsghdr) && - nlh->nlmsg_len >= sizeof(struct nlmsghdr) && (int)nlh->nlmsg_len <= len; + return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); } -static struct nlmsghdr* mnl_nlmsg_next(const struct nlmsghdr* nlh, int* len) +static bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len) { - *len -= MNL_ALIGN(nlh->nlmsg_len); - return (struct nlmsghdr*)((void*)nlh + MNL_ALIGN(nlh->nlmsg_len)); + return len >= (int)sizeof(struct nlmsghdr) && + nlh->nlmsg_len >= sizeof(struct nlmsghdr) && + (int)nlh->nlmsg_len <= len; } -static void* mnl_nlmsg_get_payload_tail(const struct nlmsghdr* nlh) +static struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len) { - return (void*)nlh + MNL_ALIGN(nlh->nlmsg_len); + *len -= MNL_ALIGN(nlh->nlmsg_len); + return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len)); } -static bool mnl_nlmsg_seq_ok(const struct nlmsghdr* nlh, unsigned int seq) +static void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh) { - return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; + return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len); } -static bool mnl_nlmsg_portid_ok(const struct nlmsghdr* nlh, unsigned int portid) +static bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq) { - return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; + return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; } -static uint16_t mnl_attr_get_type(const struct nlattr* attr) +static bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid) { - return attr->nla_type & NLA_TYPE_MASK; + return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; } -static uint16_t mnl_attr_get_payload_len(const struct nlattr* attr) +static uint16_t mnl_attr_get_type(const struct nlattr *attr) { - return attr->nla_len - MNL_ATTR_HDRLEN; + return attr->nla_type & NLA_TYPE_MASK; } -static void* mnl_attr_get_payload(const struct nlattr* attr) +static uint16_t mnl_attr_get_payload_len(const struct nlattr *attr) { - return (void*)attr + MNL_ATTR_HDRLEN; + return attr->nla_len - MNL_ATTR_HDRLEN; } -static bool mnl_attr_ok(const struct nlattr* attr, int len) +static void *mnl_attr_get_payload(const struct nlattr *attr) { - return len >= (int)sizeof(struct nlattr) && attr->nla_len >= sizeof(struct nlattr) && - (int)attr->nla_len <= len; + return (void *)attr + MNL_ATTR_HDRLEN; } -static struct nlattr* mnl_attr_next(const struct nlattr* attr) +static bool mnl_attr_ok(const struct nlattr *attr, int len) { - return (struct nlattr*)((void*)attr + MNL_ALIGN(attr->nla_len)); + return len >= (int)sizeof(struct nlattr) && + attr->nla_len >= sizeof(struct nlattr) && + (int)attr->nla_len <= len; } -static int mnl_attr_type_valid(const struct nlattr* attr, uint16_t max) +static struct nlattr *mnl_attr_next(const struct nlattr *attr) { - if (mnl_attr_get_type(attr) > max) - { - errno = EOPNOTSUPP; - return -1; - } - return 1; + return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len)); } -static int __mnl_attr_validate( - const struct nlattr* attr, - enum mnl_attr_data_type type, - size_t exp_len) +static int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max) { - uint16_t attr_len = mnl_attr_get_payload_len(attr); - const char* attr_data = mnl_attr_get_payload(attr); + if (mnl_attr_get_type(attr) > max) { + errno = EOPNOTSUPP; + return -1; + } + return 1; +} - 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: +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 == 0) - break; + 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 < MNL_ATTR_HDRLEN) - { - errno = ERANGE; - return -1; - } - break; - default: + if (attr_len == 0) + break; - break; - } - if (exp_len && attr_len > exp_len) - { - errno = ERANGE; - return -1; - } - return 0; + 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; } 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) { return __mnl_socket_open(bus, 0); } - -static int mnl_socket_bind(struct mnl_socket* nl, unsigned int groups, pid_t pid) +static struct mnl_socket *mnl_socket_open(int bus) { - 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; + return __mnl_socket_open(bus, 0); } -static ssize_t mnl_socket_sendto(const struct mnl_socket* nl, const void* buf, size_t len) +static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid) { - static const struct sockaddr_nl snl = {.nl_family = AF_NETLINK}; - return sendto(nl->fd, buf, len, 0, (struct sockaddr*)&snl, sizeof(snl)); + 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 ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_t bufsiz) +static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, + size_t len) { - 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 const struct sockaddr_nl snl = { + .nl_family = AF_NETLINK + }; + return sendto(nl->fd, buf, len, 0, + (struct sockaddr *) &snl, sizeof(snl)); } -static int mnl_socket_close(struct mnl_socket* nl) +static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, + size_t bufsiz) { - int ret = close(nl->fd); - free(nl); - return ret; + 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; } /* 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/uapi/openbsd/net/if_wg.h b/src/uapi/openbsd/net/if_wg.h index 9bc3b91..8e29da5 100644 --- a/src/uapi/openbsd/net/if_wg.h +++ b/src/uapi/openbsd/net/if_wg.h @@ -7,12 +7,13 @@ #ifndef __IF_WG_H__ #define __IF_WG_H__ -#include #include +#include #include #include + /* * This is the public interface to the WireGuard network interface. * @@ -24,56 +25,52 @@ #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_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) @@ -94,25 +91,24 @@ struct wg_peer_io #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; @@ -125,11 +121,10 @@ struct wg_interface_io 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 1b99427..1b41517 100644 --- a/src/uapi/windows/wireguard.h +++ b/src/uapi/windows/wireguard.h @@ -6,113 +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_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_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; - UCHAR* I1; - UCHAR* I2; - UCHAR* I3; - UCHAR* I4; - UCHAR* I5; - UCHAR* J1; - UCHAR* J2; - UCHAR* J3; - ULONG Itime; + 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 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 DEVPKEY_WG_NAME \ - (DEVPROPKEY){ \ - {0x65726957, 0x7547, 0x7261, {0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79}}, \ - DEVPROPID_FIRST_USABLE + 1} #endif diff --git a/src/wg.c b/src/wg.c index 6480970..0431fce 100644 --- a/src/wg.c +++ b/src/wg.c @@ -42,7 +42,7 @@ int main(int argc, const char *argv[]) PROG_NAME = argv[0]; if (argc == 2 && (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version") || !strcmp(argv[1], "version"))) { - printf("wireguard-tools v%s - https://git.zx2c4.com/wireguard-tools/\n", WIREGUARD_TOOLS_VERSION); + printf("amneziawg-tools v%s - https://amnezia.org\n", WIREGUARD_TOOLS_VERSION); return 0; } if (argc == 2 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help") || !strcmp(argv[1], "help"))) {