mirror of
https://github.com/amnezia-vpn/amneziawg-tools.git
synced 2025-08-01 17:12:50 +02:00
fix: formatting
This commit is contained in:
parent
5d3c2a6096
commit
66de01f211
10 changed files with 3170 additions and 3696 deletions
220
src/containers.h
220
src/containers.h
|
@ -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
|
||||
|
|
1007
src/ipc-freebsd.h
1007
src/ipc-freebsd.h
File diff suppressed because it is too large
Load diff
1368
src/ipc-linux.h
1368
src/ipc-linux.h
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
|
804
src/ipc-uapi.h
804
src/ipc-uapi.h
|
@ -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
|
||||
|
|
1264
src/ipc-windows.h
1264
src/ipc-windows.h
File diff suppressed because it is too large
Load diff
1119
src/netlink.h
1119
src/netlink.h
File diff suppressed because it is too large
Load diff
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
|
|
2
src/wg.c
2
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"))) {
|
||||
|
|
Loading…
Add table
Reference in a new issue