fix: formatting

This commit is contained in:
Mark Puha 2025-06-14 15:02:32 +02:00
parent 5d3c2a6096
commit 66de01f211
10 changed files with 3170 additions and 3696 deletions

View file

@ -6,13 +6,13 @@
#ifndef CONTAINERS_H
#define CONTAINERS_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <time.h>
#if defined(__linux__)
#include <linux/wireguard.h>
#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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -3,521 +3,478 @@
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#include "containers.h"
#include <errno.h>
#include <net/if.h>
#include <net/if_wg.h>
#include <netinet/in.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/types.h>
#include <time.h>
#include <net/if.h>
#include <net/if_wg.h>
#include <netinet/in.h>
#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;
}

View file

@ -3,10 +3,6 @@
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/
#include "containers.h"
#include "ctype.h"
#include "curve25519.h"
#include "encoding.h"
#include <arpa/inet.h>
#include <errno.h>
#include <limits.h>
@ -18,6 +14,10 @@
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -7,12 +7,13 @@
#ifndef __IF_WG_H__
#define __IF_WG_H__
#include <sys/errno.h>
#include <sys/limits.h>
#include <sys/errno.h>
#include <net/if.h>
#include <netinet/in.h>
/*
* 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__ */

View file

@ -6,113 +6,113 @@
#ifndef _WIREGUARD_NT_H
#define _WIREGUARD_NT_H
#include <in6addr.h>
#include <inaddr.h>
#include <ntdef.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#include <inaddr.h>
#include <in6addr.h>
#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

View file

@ -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"))) {