mirror of
https://github.com/amnezia-vpn/amneziawg-tools.git
synced 2025-08-02 09:32:51 +02:00
fix: formatting
This commit is contained in:
parent
5d3c2a6096
commit
66de01f211
10 changed files with 3170 additions and 3696 deletions
|
@ -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,26 +28,22 @@
|
|||
#endif
|
||||
|
||||
/* Cross platform __kernel_timespec */
|
||||
struct timespec64
|
||||
{
|
||||
struct timespec64 {
|
||||
int64_t tv_sec;
|
||||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
struct wgallowedip
|
||||
{
|
||||
struct wgallowedip {
|
||||
uint16_t family;
|
||||
union
|
||||
{
|
||||
union {
|
||||
struct in_addr ip4;
|
||||
struct in6_addr ip6;
|
||||
};
|
||||
uint8_t cidr;
|
||||
struct wgallowedip* next_allowedip;
|
||||
struct wgallowedip *next_allowedip;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
WGPEER_REMOVE_ME = 1U << 0,
|
||||
WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
|
||||
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
|
||||
|
@ -57,15 +53,13 @@ enum
|
|||
WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6
|
||||
};
|
||||
|
||||
struct wgpeer
|
||||
{
|
||||
struct wgpeer {
|
||||
uint32_t flags;
|
||||
|
||||
uint8_t public_key[WG_KEY_LEN];
|
||||
uint8_t preshared_key[WG_KEY_LEN];
|
||||
|
||||
union
|
||||
{
|
||||
union {
|
||||
struct sockaddr addr;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
|
@ -79,11 +73,10 @@ struct wgpeer
|
|||
bool special_handshake;
|
||||
|
||||
struct wgallowedip *first_allowedip, *last_allowedip;
|
||||
struct wgpeer* next_peer;
|
||||
struct wgpeer *next_peer;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
WGDEVICE_REPLACE_PEERS = 1U << 0,
|
||||
WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
|
||||
WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
|
||||
|
@ -109,8 +102,7 @@ enum
|
|||
WGDEVICE_HAS_ITIME = 1U << 22
|
||||
};
|
||||
|
||||
struct wgdevice
|
||||
{
|
||||
struct wgdevice {
|
||||
char name[IFNAMSIZ];
|
||||
uint32_t ifindex;
|
||||
|
||||
|
@ -144,23 +136,15 @@ struct wgdevice
|
|||
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)
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <dev/wg/if_wg.h>
|
||||
#include <sys/nv.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <dev/wg/if_wg.h>
|
||||
|
||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||
|
||||
|
@ -19,10 +19,10 @@ static int get_dgram_socket(void)
|
|||
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;
|
||||
struct ifgroupreq ifgr = { .ifgr_name = "wg" };
|
||||
struct ifg_req *ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
|
||||
if (s < 0)
|
||||
|
@ -34,14 +34,12 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
{
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
|
||||
{
|
||||
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);
|
||||
|
@ -52,15 +50,15 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
||||
static int kernel_get_device(struct wgdevice **device, const char *ifname)
|
||||
{
|
||||
struct wg_data_io wgd = {0};
|
||||
nvlist_t* nvl_device = NULL;
|
||||
const nvlist_t* const* nvl_peers;
|
||||
struct wgdevice* dev = NULL;
|
||||
struct wg_data_io wgd = { 0 };
|
||||
nvlist_t *nvl_device = NULL;
|
||||
const nvlist_t *const *nvl_peers;
|
||||
struct wgdevice *dev = NULL;
|
||||
size_t size, peer_count, i;
|
||||
uint64_t number;
|
||||
const void* binary;
|
||||
const void *binary;
|
||||
int ret = 0, s;
|
||||
|
||||
*device = NULL;
|
||||
|
@ -86,92 +84,72 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
|||
if (!nvl_device)
|
||||
goto err;
|
||||
|
||||
if (nvlist_exists_number(nvl_device, "listen-port"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "listen-port")) {
|
||||
number = nvlist_get_number(nvl_device, "listen-port");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX) {
|
||||
dev->listen_port = number;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jc"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "jc")) {
|
||||
number = nvlist_get_number(nvl_device, "jc");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_count = number;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmin"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "jmin")) {
|
||||
number = nvlist_get_number(nvl_device, "jmin");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_min_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmax"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "jmax")) {
|
||||
number = nvlist_get_number(nvl_device, "jmax");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_max_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s1"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "s1")) {
|
||||
number = nvlist_get_number(nvl_device, "s1");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX){
|
||||
dev->init_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s2"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "s2")) {
|
||||
number = nvlist_get_number(nvl_device, "s2");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX){
|
||||
dev->response_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h1"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "h1")) {
|
||||
number = nvlist_get_number(nvl_device, "h1");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
if (number <= UINT32_MAX){
|
||||
dev->init_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h2"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "h2")) {
|
||||
number = nvlist_get_number(nvl_device, "h2");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
if (number <= UINT32_MAX){
|
||||
dev->response_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h3"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "h3")) {
|
||||
number = nvlist_get_number(nvl_device, "h3");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
if (number <= UINT32_MAX){
|
||||
dev->underload_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h4"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "h4")) {
|
||||
number = nvlist_get_number(nvl_device, "h4");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
if (number <= UINT32_MAX){
|
||||
dev->transport_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
@ -258,29 +236,23 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
|||
}
|
||||
}
|
||||
|
||||
if (nvlist_exists_number(nvl_device, "user-cookie"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_device, "user-cookie")) {
|
||||
number = nvlist_get_number(nvl_device, "user-cookie");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
if (number <= UINT32_MAX) {
|
||||
dev->fwmark = number;
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "public-key"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_device, "public-key")) {
|
||||
binary = nvlist_get_binary(nvl_device, "public-key", &size);
|
||||
if (binary && size == sizeof(dev->public_key))
|
||||
{
|
||||
if (binary && size == sizeof(dev->public_key)) {
|
||||
memcpy(dev->public_key, binary, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "private-key"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_device, "private-key")) {
|
||||
binary = nvlist_get_binary(nvl_device, "private-key", &size);
|
||||
if (binary && size == sizeof(dev->private_key))
|
||||
{
|
||||
if (binary && size == sizeof(dev->private_key)) {
|
||||
memcpy(dev->private_key, binary, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
|
@ -290,50 +262,40 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
|||
nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count);
|
||||
if (!nvl_peers)
|
||||
goto skip_peers;
|
||||
for (i = 0; i < peer_count; ++i)
|
||||
{
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip = NULL;
|
||||
const nvlist_t* const* nvl_aips;
|
||||
for (i = 0; i < peer_count; ++i) {
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip = NULL;
|
||||
const nvlist_t *const *nvl_aips;
|
||||
size_t aip_count, j;
|
||||
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto err_peer;
|
||||
if (nvlist_exists_binary(nvl_peers[i], "public-key"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_peers[i], "public-key")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "public-key", &size);
|
||||
if (binary && size == sizeof(peer->public_key))
|
||||
{
|
||||
if (binary && size == sizeof(peer->public_key)) {
|
||||
memcpy(peer->public_key, binary, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "preshared-key"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_peers[i], "preshared-key")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size);
|
||||
if (binary && size == sizeof(peer->preshared_key))
|
||||
{
|
||||
if (binary && size == sizeof(peer->preshared_key)) {
|
||||
memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval"))
|
||||
{
|
||||
if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval")) {
|
||||
number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
if (number <= UINT16_MAX) {
|
||||
peer->persistent_keepalive_interval = number;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "endpoint"))
|
||||
{
|
||||
const struct sockaddr* endpoint =
|
||||
nvlist_get_binary(nvl_peers[i], "endpoint", &size);
|
||||
if (endpoint && size <= sizeof(peer->endpoint) &&
|
||||
size >= sizeof(peer->endpoint.addr) &&
|
||||
if (nvlist_exists_binary(nvl_peers[i], "endpoint")) {
|
||||
const struct sockaddr *endpoint = nvlist_get_binary(nvl_peers[i], "endpoint", &size);
|
||||
if (endpoint && size <= sizeof(peer->endpoint) && size >= sizeof(peer->endpoint.addr) &&
|
||||
(endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6))
|
||||
memcpy(&peer->endpoint.addr, endpoint, size);
|
||||
}
|
||||
|
@ -341,14 +303,10 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
|||
peer->rx_bytes = nvlist_get_number(nvl_peers[i], "rx-bytes");
|
||||
if (nvlist_exists_number(nvl_peers[i], "tx-bytes"))
|
||||
peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes");
|
||||
if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size);
|
||||
if (binary && size == sizeof(peer->last_handshake_time))
|
||||
memcpy(
|
||||
&peer->last_handshake_time,
|
||||
binary,
|
||||
sizeof(peer->last_handshake_time));
|
||||
memcpy(&peer->last_handshake_time, binary, sizeof(peer->last_handshake_time));
|
||||
}
|
||||
|
||||
if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips"))
|
||||
|
@ -356,35 +314,28 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
|||
nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count);
|
||||
if (!aip_count || !nvl_aips)
|
||||
goto skip_allowed_ips;
|
||||
for (j = 0; j < aip_count; ++j)
|
||||
{
|
||||
for (j = 0; j < aip_count; ++j) {
|
||||
if (!nvlist_exists_number(nvl_aips[j], "cidr"))
|
||||
continue;
|
||||
if (!nvlist_exists_binary(nvl_aips[j], "ipv4") &&
|
||||
!nvlist_exists_binary(nvl_aips[j], "ipv6"))
|
||||
if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && !nvlist_exists_binary(nvl_aips[j], "ipv6"))
|
||||
continue;
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto err_allowed_ips;
|
||||
number = nvlist_get_number(nvl_aips[j], "cidr");
|
||||
if (nvlist_exists_binary(nvl_aips[j], "ipv4"))
|
||||
{
|
||||
if (nvlist_exists_binary(nvl_aips[j], "ipv4")) {
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size);
|
||||
if (!binary || number > 32)
|
||||
{
|
||||
if (!binary || number > 32) {
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
aip->family = AF_INET;
|
||||
aip->cidr = number;
|
||||
memcpy(&aip->ip4, binary, sizeof(aip->ip4));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
assert(nvlist_exists_binary(nvl_aips[j], "ipv6"));
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size);
|
||||
if (!binary || number > 128)
|
||||
{
|
||||
if (!binary || number > 128) {
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
|
@ -440,12 +391,13 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_set_device(struct wgdevice* dev)
|
||||
|
||||
static int kernel_set_device(struct wgdevice *dev)
|
||||
{
|
||||
struct wg_data_io wgd = {0};
|
||||
nvlist_t * nvl_device = NULL, **nvl_peers = NULL;
|
||||
struct wg_data_io wgd = { 0 };
|
||||
nvlist_t *nvl_device = NULL, **nvl_peers = NULL;
|
||||
size_t peer_count = 0, i = 0;
|
||||
struct wgpeer* peer;
|
||||
struct wgpeer *peer;
|
||||
int ret = 0, s;
|
||||
|
||||
strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name));
|
||||
|
@ -454,16 +406,15 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
if (!nvl_device)
|
||||
goto err;
|
||||
|
||||
for_each_wgpeer(dev, peer)++ peer_count;
|
||||
if (peer_count)
|
||||
{
|
||||
for_each_wgpeer(dev, peer)
|
||||
++peer_count;
|
||||
if (peer_count) {
|
||||
nvl_peers = calloc(peer_count, sizeof(*nvl_peers));
|
||||
if (!nvl_peers)
|
||||
goto err;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
nvlist_add_binary(
|
||||
nvl_device, "private-key", dev->private_key, sizeof(dev->private_key));
|
||||
nvlist_add_binary(nvl_device, "private-key", dev->private_key, sizeof(dev->private_key));
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
nvlist_add_number(nvl_device, "listen-port", dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
|
@ -502,54 +453,38 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
nvlist_add_binary(nvl_device, "j3", dev->j3, strlen(dev->j3) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
nvlist_add_number(nvl_device, "itime", dev->itime);
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
nvlist_add_number(nvl_device, "user-cookie", dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
nvlist_add_bool(nvl_device, "replace-peers", true);
|
||||
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
for_each_wgpeer(dev, peer) {
|
||||
size_t aip_count = 0, j = 0;
|
||||
nvlist_t** nvl_aips = NULL;
|
||||
struct wgallowedip* aip;
|
||||
nvlist_t **nvl_aips = NULL;
|
||||
struct wgallowedip *aip;
|
||||
|
||||
nvl_peers[i] = nvlist_create(0);
|
||||
if (!nvl_peers[i])
|
||||
goto err_peer;
|
||||
for_each_wgallowedip(peer, aip)++ aip_count;
|
||||
if (aip_count)
|
||||
{
|
||||
for_each_wgallowedip(peer, aip)
|
||||
++aip_count;
|
||||
if (aip_count) {
|
||||
nvl_aips = calloc(aip_count, sizeof(*nvl_aips));
|
||||
if (!nvl_aips)
|
||||
goto err_peer;
|
||||
}
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key));
|
||||
nvlist_add_binary(nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key));
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i],
|
||||
"preshared-key",
|
||||
peer->preshared_key,
|
||||
sizeof(peer->preshared_key));
|
||||
nvlist_add_binary(nvl_peers[i], "preshared-key", peer->preshared_key, sizeof(peer->preshared_key));
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
nvlist_add_number(
|
||||
nvl_peers[i],
|
||||
"persistent-keepalive-interval",
|
||||
peer->persistent_keepalive_interval);
|
||||
if (peer->endpoint.addr.sa_family == AF_INET ||
|
||||
peer->endpoint.addr.sa_family == AF_INET6)
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i],
|
||||
"endpoint",
|
||||
&peer->endpoint.addr,
|
||||
peer->endpoint.addr.sa_len);
|
||||
nvlist_add_number(nvl_peers[i], "persistent-keepalive-interval", peer->persistent_keepalive_interval);
|
||||
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
|
||||
nvlist_add_binary(nvl_peers[i], "endpoint", &peer->endpoint.addr, peer->endpoint.addr.sa_len);
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
nvlist_add_bool(nvl_peers[i], "replace-allowedips", true);
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
nvlist_add_bool(nvl_peers[i], "remove", true);
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
nvl_aips[j] = nvlist_create(0);
|
||||
if (!nvl_aips[j])
|
||||
goto err_peer;
|
||||
|
@ -560,10 +495,8 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6));
|
||||
++j;
|
||||
}
|
||||
if (j)
|
||||
{
|
||||
nvlist_add_nvlist_array(
|
||||
nvl_peers[i], "allowed-ips", (const nvlist_t* const*)nvl_aips, j);
|
||||
if (j) {
|
||||
nvlist_add_nvlist_array(nvl_peers[i], "allowed-ips", (const nvlist_t *const *)nvl_aips, j);
|
||||
for (j = 0; j < aip_count; ++j)
|
||||
nvlist_destroy(nvl_aips[j]);
|
||||
free(nvl_aips);
|
||||
|
@ -580,10 +513,8 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
nvl_peers[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
if (i)
|
||||
{
|
||||
nvlist_add_nvlist_array(
|
||||
nvl_device, "peers", (const nvlist_t* const*)nvl_peers, i);
|
||||
if (i) {
|
||||
nvlist_add_nvlist_array(nvl_device, "peers", (const nvlist_t *const *)nvl_peers, i);
|
||||
for (i = 0; i < peer_count; ++i)
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
free(nvl_peers);
|
||||
|
|
384
src/ipc-linux.h
384
src/ipc-linux.h
|
@ -3,50 +3,47 @@
|
|||
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "containers.h"
|
||||
#include "encoding.h"
|
||||
#include "netlink.h"
|
||||
#include "uapi/linux/linux/wireguard.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/wireguard.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include "containers.h"
|
||||
#include "encoding.h"
|
||||
#include "netlink.h"
|
||||
|
||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||
|
||||
#define SOCKET_BUFFER_SIZE (mnl_ideal_socket_buffer_size())
|
||||
|
||||
struct interface
|
||||
{
|
||||
const char* name;
|
||||
struct interface {
|
||||
const char *name;
|
||||
bool is_wireguard;
|
||||
};
|
||||
|
||||
static int parse_linkinfo(const struct nlattr* attr, void* data)
|
||||
static int parse_linkinfo(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct interface* interface = data;
|
||||
struct interface *interface = data;
|
||||
|
||||
if (mnl_attr_get_type(attr) == IFLA_INFO_KIND &&
|
||||
!strcmp(WG_GENL_NAME, mnl_attr_get_str(attr)))
|
||||
if (mnl_attr_get_type(attr) == IFLA_INFO_KIND && !strcmp(WG_GENL_NAME, mnl_attr_get_str(attr)))
|
||||
interface->is_wireguard = true;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int parse_infomsg(const struct nlattr* attr, void* data)
|
||||
static int parse_infomsg(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct interface* interface = data;
|
||||
struct interface *interface = data;
|
||||
|
||||
if (mnl_attr_get_type(attr) == IFLA_LINKINFO)
|
||||
return mnl_attr_parse_nested(attr, parse_linkinfo, data);
|
||||
|
@ -55,10 +52,10 @@ static int parse_infomsg(const struct nlattr* attr, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int read_devices_cb(const struct nlmsghdr* nlh, void* data)
|
||||
static int read_devices_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
struct string_list* list = data;
|
||||
struct interface interface = {0};
|
||||
struct string_list *list = data;
|
||||
struct interface interface = { 0 };
|
||||
int ret;
|
||||
|
||||
ret = mnl_attr_parse(nlh, sizeof(struct ifinfomsg), parse_infomsg, &interface);
|
||||
|
@ -73,16 +70,16 @@ static int read_devices_cb(const struct nlmsghdr* nlh, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int kernel_get_wireguard_interfaces(struct string_list* list)
|
||||
static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||
{
|
||||
struct mnl_socket* nl = NULL;
|
||||
char* rtnl_buffer = NULL;
|
||||
struct mnl_socket *nl = NULL;
|
||||
char *rtnl_buffer = NULL;
|
||||
size_t message_len;
|
||||
unsigned int portid, seq;
|
||||
ssize_t len;
|
||||
int ret = 0;
|
||||
struct nlmsghdr* nlh;
|
||||
struct ifinfomsg* ifm;
|
||||
struct nlmsghdr *nlh;
|
||||
struct ifinfomsg *ifm;
|
||||
|
||||
ret = -ENOMEM;
|
||||
rtnl_buffer = calloc(SOCKET_BUFFER_SIZE, 1);
|
||||
|
@ -90,14 +87,12 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
goto cleanup;
|
||||
|
||||
nl = mnl_socket_open(NETLINK_ROUTE);
|
||||
if (!nl)
|
||||
{
|
||||
if (!nl) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -112,27 +107,23 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
ifm->ifi_family = AF_UNSPEC;
|
||||
message_len = nlh->nlmsg_len;
|
||||
|
||||
if (mnl_socket_sendto(nl, rtnl_buffer, message_len) < 0)
|
||||
{
|
||||
if (mnl_socket_sendto(nl, rtnl_buffer, message_len) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
another:
|
||||
if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, SOCKET_BUFFER_SIZE)) < 0)
|
||||
{
|
||||
if ((len = mnl_socket_recvfrom(nl, rtnl_buffer, SOCKET_BUFFER_SIZE)) < 0) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, list)) < 0)
|
||||
{
|
||||
if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, list)) < 0) {
|
||||
/* Netlink returns NLM_F_DUMP_INTR if the set of all tunnels changed
|
||||
* during the dump. That's unfortunate, but is pretty common on busy
|
||||
* systems that are adding and removing tunnels all the time. Rather
|
||||
* than retrying, potentially indefinitely, we just work with the
|
||||
* partial results. */
|
||||
if (errno != EINTR)
|
||||
{
|
||||
if (errno != EINTR) {
|
||||
ret = -errno;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -148,14 +139,14 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_set_device(struct wgdevice* dev)
|
||||
static int kernel_set_device(struct wgdevice *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct wgpeer* peer = NULL;
|
||||
struct wgallowedip* allowedip = NULL;
|
||||
struct nlattr * peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
|
||||
struct nlmsghdr* nlh;
|
||||
struct mnlg_socket* nlg;
|
||||
struct wgpeer *peer = NULL;
|
||||
struct wgallowedip *allowedip = NULL;
|
||||
struct nlattr *peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
|
||||
struct nlmsghdr *nlh;
|
||||
struct mnlg_socket *nlg;
|
||||
|
||||
nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
|
||||
if (!nlg)
|
||||
|
@ -165,13 +156,11 @@ again:
|
|||
nlh = mnlg_msg_prepare(nlg, WG_CMD_SET_DEVICE, NLM_F_REQUEST | NLM_F_ACK);
|
||||
mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, dev->name);
|
||||
|
||||
if (!peer)
|
||||
{
|
||||
if (!peer) {
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
mnl_attr_put(
|
||||
nlh, WGDEVICE_A_PRIVATE_KEY, sizeof(dev->private_key), dev->private_key);
|
||||
mnl_attr_put(nlh, WGDEVICE_A_PRIVATE_KEY, sizeof(dev->private_key), dev->private_key);
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
mnl_attr_put_u16(nlh, WGDEVICE_A_LISTEN_PORT, dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
|
@ -210,7 +199,6 @@ again:
|
|||
mnl_attr_put_strz(nlh, WGDEVICE_A_J3, dev->j3);
|
||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
mnl_attr_put_u32(nlh, WGDEVICE_A_ITIME, dev->itime);
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
|
@ -222,71 +210,38 @@ again:
|
|||
goto send;
|
||||
peers_nest = peer_nest = allowedips_nest = allowedip_nest = NULL;
|
||||
peers_nest = mnl_attr_nest_start(nlh, WGDEVICE_A_PEERS);
|
||||
for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer)
|
||||
{
|
||||
for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer) {
|
||||
uint32_t flags = 0;
|
||||
|
||||
peer_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
|
||||
if (!peer_nest)
|
||||
goto toobig_peers;
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGPEER_A_PUBLIC_KEY,
|
||||
sizeof(peer->public_key),
|
||||
peer->public_key))
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PUBLIC_KEY, sizeof(peer->public_key), peer->public_key))
|
||||
goto toobig_peers;
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
flags |= WGPEER_F_REMOVE_ME;
|
||||
if (!allowedip)
|
||||
{
|
||||
if (!allowedip) {
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
flags |= WGPEER_F_REPLACE_ALLOWEDIPS;
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGPEER_A_PRESHARED_KEY,
|
||||
sizeof(peer->preshared_key),
|
||||
peer->preshared_key))
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PRESHARED_KEY, sizeof(peer->preshared_key), peer->preshared_key))
|
||||
goto toobig_peers;
|
||||
}
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
{
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGPEER_A_ENDPOINT,
|
||||
sizeof(peer->endpoint.addr4),
|
||||
&peer->endpoint.addr4))
|
||||
if (peer->endpoint.addr.sa_family == AF_INET) {
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr4), &peer->endpoint.addr4))
|
||||
goto toobig_peers;
|
||||
} else if (peer->endpoint.addr.sa_family == AF_INET6) {
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ENDPOINT, sizeof(peer->endpoint.addr6), &peer->endpoint.addr6))
|
||||
goto toobig_peers;
|
||||
}
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
{
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGPEER_A_ENDPOINT,
|
||||
sizeof(peer->endpoint.addr6),
|
||||
&peer->endpoint.addr6))
|
||||
goto toobig_peers;
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
{
|
||||
if (!mnl_attr_put_u16_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
|
||||
peer->persistent_keepalive_interval))
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
|
||||
if (!mnl_attr_put_u16_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, peer->persistent_keepalive_interval))
|
||||
goto toobig_peers;
|
||||
}
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY)
|
||||
{
|
||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
|
||||
if (peer->advanced_security)
|
||||
mnl_attr_put_check(
|
||||
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
|
||||
mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
|
||||
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)
|
||||
|
@ -296,52 +251,30 @@ again:
|
|||
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_SPECIAL_HANDSHAKE, 0, NULL);
|
||||
flags |= WGPEER_F_HAS_SPECIAL_HANDSHAKE;
|
||||
}
|
||||
if (flags)
|
||||
{
|
||||
if (flags) {
|
||||
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
|
||||
goto toobig_peers;
|
||||
}
|
||||
if (peer->first_allowedip)
|
||||
{
|
||||
if (peer->first_allowedip) {
|
||||
if (!allowedip)
|
||||
allowedip = peer->first_allowedip;
|
||||
allowedips_nest =
|
||||
mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ALLOWEDIPS);
|
||||
allowedips_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ALLOWEDIPS);
|
||||
if (!allowedips_nest)
|
||||
goto toobig_allowedips;
|
||||
for (; allowedip; allowedip = allowedip->next_allowedip)
|
||||
{
|
||||
for (; allowedip; allowedip = allowedip->next_allowedip) {
|
||||
allowedip_nest = mnl_attr_nest_start_check(nlh, SOCKET_BUFFER_SIZE, 0);
|
||||
if (!allowedip_nest)
|
||||
goto toobig_allowedips;
|
||||
if (!mnl_attr_put_u16_check(
|
||||
nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FAMILY, allowedip->family))
|
||||
if (!mnl_attr_put_u16_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FAMILY, allowedip->family))
|
||||
goto toobig_allowedips;
|
||||
if (allowedip->family == AF_INET)
|
||||
{
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGALLOWEDIP_A_IPADDR,
|
||||
sizeof(allowedip->ip4),
|
||||
&allowedip->ip4))
|
||||
if (allowedip->family == AF_INET) {
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip4), &allowedip->ip4))
|
||||
goto toobig_allowedips;
|
||||
} else if (allowedip->family == AF_INET6) {
|
||||
if (!mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_IPADDR, sizeof(allowedip->ip6), &allowedip->ip6))
|
||||
goto toobig_allowedips;
|
||||
}
|
||||
else if (allowedip->family == AF_INET6)
|
||||
{
|
||||
if (!mnl_attr_put_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGALLOWEDIP_A_IPADDR,
|
||||
sizeof(allowedip->ip6),
|
||||
&allowedip->ip6))
|
||||
goto toobig_allowedips;
|
||||
}
|
||||
if (!mnl_attr_put_u8_check(
|
||||
nlh,
|
||||
SOCKET_BUFFER_SIZE,
|
||||
WGALLOWEDIP_A_CIDR_MASK,
|
||||
allowedip->cidr))
|
||||
if (!mnl_attr_put_u8_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_CIDR_MASK, allowedip->cidr))
|
||||
goto toobig_allowedips;
|
||||
mnl_attr_nest_end(nlh, allowedip_nest);
|
||||
allowedip_nest = NULL;
|
||||
|
@ -370,14 +303,12 @@ toobig_peers:
|
|||
mnl_attr_nest_end(nlh, peers_nest);
|
||||
goto send;
|
||||
send:
|
||||
if (mnlg_socket_send(nlg, nlh) < 0)
|
||||
{
|
||||
if (mnlg_socket_send(nlg, nlh) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
errno = 0;
|
||||
if (mnlg_socket_recv_run(nlg, NULL, NULL) < 0)
|
||||
{
|
||||
if (mnlg_socket_recv_run(nlg, NULL, NULL) < 0) {
|
||||
ret = errno ? -errno : -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -390,12 +321,11 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int parse_allowedip(const struct nlattr* attr, void* data)
|
||||
static int parse_allowedip(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wgallowedip* allowedip = data;
|
||||
struct wgallowedip *allowedip = data;
|
||||
|
||||
switch (mnl_attr_get_type(attr))
|
||||
{
|
||||
switch (mnl_attr_get_type(attr)) {
|
||||
case WGALLOWEDIP_A_UNSPEC:
|
||||
break;
|
||||
case WGALLOWEDIP_A_FAMILY:
|
||||
|
@ -417,72 +347,59 @@ static int parse_allowedip(const struct nlattr* attr, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int parse_allowedips(const struct nlattr* attr, void* data)
|
||||
static int parse_allowedips(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wgpeer* peer = data;
|
||||
struct wgallowedip* new_allowedip = calloc(1, sizeof(*new_allowedip));
|
||||
struct wgpeer *peer = data;
|
||||
struct wgallowedip *new_allowedip = calloc(1, sizeof(*new_allowedip));
|
||||
int ret;
|
||||
|
||||
if (!new_allowedip)
|
||||
{
|
||||
if (!new_allowedip) {
|
||||
perror("calloc");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
if (!peer->first_allowedip)
|
||||
peer->first_allowedip = peer->last_allowedip = new_allowedip;
|
||||
else
|
||||
{
|
||||
else {
|
||||
peer->last_allowedip->next_allowedip = new_allowedip;
|
||||
peer->last_allowedip = new_allowedip;
|
||||
}
|
||||
ret = mnl_attr_parse_nested(attr, parse_allowedip, new_allowedip);
|
||||
if (!ret)
|
||||
return ret;
|
||||
if (!((new_allowedip->family == AF_INET && new_allowedip->cidr <= 32) ||
|
||||
(new_allowedip->family == AF_INET6 && new_allowedip->cidr <= 128)))
|
||||
if (!((new_allowedip->family == AF_INET && new_allowedip->cidr <= 32) || (new_allowedip->family == AF_INET6 && new_allowedip->cidr <= 128)))
|
||||
return MNL_CB_ERROR;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int parse_peer(const struct nlattr* attr, void* data)
|
||||
static int parse_peer(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wgpeer* peer = data;
|
||||
struct wgpeer *peer = data;
|
||||
|
||||
switch (mnl_attr_get_type(attr))
|
||||
{
|
||||
switch (mnl_attr_get_type(attr)) {
|
||||
case WGPEER_A_UNSPEC:
|
||||
break;
|
||||
case WGPEER_A_PUBLIC_KEY:
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(peer->public_key))
|
||||
{
|
||||
memcpy(
|
||||
peer->public_key, mnl_attr_get_payload(attr), sizeof(peer->public_key));
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(peer->public_key)) {
|
||||
memcpy(peer->public_key, mnl_attr_get_payload(attr), sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
break;
|
||||
case WGPEER_A_PRESHARED_KEY:
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(peer->preshared_key))
|
||||
{
|
||||
memcpy(
|
||||
peer->preshared_key,
|
||||
mnl_attr_get_payload(attr),
|
||||
sizeof(peer->preshared_key));
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(peer->preshared_key)) {
|
||||
memcpy(peer->preshared_key, mnl_attr_get_payload(attr), sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
break;
|
||||
case WGPEER_A_ENDPOINT: {
|
||||
struct sockaddr* addr;
|
||||
struct sockaddr *addr;
|
||||
|
||||
if (mnl_attr_get_payload_len(attr) < sizeof(*addr))
|
||||
break;
|
||||
addr = mnl_attr_get_payload(attr);
|
||||
if (addr->sa_family == AF_INET &&
|
||||
mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr4))
|
||||
if (addr->sa_family == AF_INET && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr4))
|
||||
memcpy(&peer->endpoint.addr4, addr, sizeof(peer->endpoint.addr4));
|
||||
else if (
|
||||
addr->sa_family == AF_INET6 &&
|
||||
mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr6))
|
||||
else if (addr->sa_family == AF_INET6 && mnl_attr_get_payload_len(attr) == sizeof(peer->endpoint.addr6))
|
||||
memcpy(&peer->endpoint.addr6, addr, sizeof(peer->endpoint.addr6));
|
||||
break;
|
||||
}
|
||||
|
@ -492,10 +409,7 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
|||
break;
|
||||
case WGPEER_A_LAST_HANDSHAKE_TIME:
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(peer->last_handshake_time))
|
||||
memcpy(
|
||||
&peer->last_handshake_time,
|
||||
mnl_attr_get_payload(attr),
|
||||
sizeof(peer->last_handshake_time));
|
||||
memcpy(&peer->last_handshake_time, mnl_attr_get_payload(attr), sizeof(peer->last_handshake_time));
|
||||
break;
|
||||
case WGPEER_A_RX_BYTES:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U64))
|
||||
|
@ -506,17 +420,14 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
|||
peer->tx_bytes = mnl_attr_get_u64(attr);
|
||||
break;
|
||||
case WGPEER_A_FLAGS:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
|
||||
uint32_t flags = mnl_attr_get_u32(attr);
|
||||
|
||||
if (flags & WGPEER_F_HAS_ADVANCED_SECURITY &&
|
||||
!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY))
|
||||
{
|
||||
if (flags & WGPEER_F_HAS_ADVANCED_SECURITY && !(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
|
||||
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
||||
peer->advanced_security = false;
|
||||
}
|
||||
else if (
|
||||
if (
|
||||
flags & WGPEER_F_HAS_SPECIAL_HANDSHAKE &&
|
||||
!(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE))
|
||||
{
|
||||
|
@ -526,12 +437,10 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
|||
}
|
||||
break;
|
||||
case WGPEER_A_ADVANCED_SECURITY:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_FLAG))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) {
|
||||
peer->advanced_security = true;
|
||||
|
||||
if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY))
|
||||
{
|
||||
if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
|
||||
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
||||
}
|
||||
}
|
||||
|
@ -554,21 +463,19 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int parse_peers(const struct nlattr* attr, void* data)
|
||||
static int parse_peers(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wgdevice* device = data;
|
||||
struct wgpeer* new_peer = calloc(1, sizeof(*new_peer));
|
||||
struct wgdevice *device = data;
|
||||
struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
|
||||
int ret;
|
||||
|
||||
if (!new_peer)
|
||||
{
|
||||
if (!new_peer) {
|
||||
perror("calloc");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
if (!device->first_peer)
|
||||
device->first_peer = device->last_peer = new_peer;
|
||||
else
|
||||
{
|
||||
else {
|
||||
device->last_peer->next_peer = new_peer;
|
||||
device->last_peer = new_peer;
|
||||
}
|
||||
|
@ -580,12 +487,11 @@ static int parse_peers(const struct nlattr* attr, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int parse_device(const struct nlattr* attr, void* data)
|
||||
static int parse_device(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wgdevice* device = data;
|
||||
struct wgdevice *device = data;
|
||||
|
||||
switch (mnl_attr_get_type(attr))
|
||||
{
|
||||
switch (mnl_attr_get_type(attr)) {
|
||||
case WGDEVICE_A_UNSPEC:
|
||||
break;
|
||||
case WGDEVICE_A_IFINDEX:
|
||||
|
@ -593,29 +499,20 @@ static int parse_device(const struct nlattr* attr, void* data)
|
|||
device->ifindex = mnl_attr_get_u32(attr);
|
||||
break;
|
||||
case WGDEVICE_A_IFNAME:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING)) {
|
||||
strncpy(device->name, mnl_attr_get_str(attr), sizeof(device->name) - 1);
|
||||
device->name[sizeof(device->name) - 1] = '\0';
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_PRIVATE_KEY:
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(device->private_key))
|
||||
{
|
||||
memcpy(
|
||||
device->private_key,
|
||||
mnl_attr_get_payload(attr),
|
||||
sizeof(device->private_key));
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(device->private_key)) {
|
||||
memcpy(device->private_key, mnl_attr_get_payload(attr), sizeof(device->private_key));
|
||||
device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_PUBLIC_KEY:
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(device->public_key))
|
||||
{
|
||||
memcpy(
|
||||
device->public_key,
|
||||
mnl_attr_get_payload(attr),
|
||||
sizeof(device->public_key));
|
||||
if (mnl_attr_get_payload_len(attr) == sizeof(device->public_key)) {
|
||||
memcpy(device->public_key, mnl_attr_get_payload(attr), sizeof(device->public_key));
|
||||
device->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
break;
|
||||
|
@ -630,64 +527,55 @@ static int parse_device(const struct nlattr* attr, void* data)
|
|||
case WGDEVICE_A_PEERS:
|
||||
return mnl_attr_parse_nested(attr, parse_peers, device);
|
||||
case WGDEVICE_A_JC:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
|
||||
device->junk_packet_count = mnl_attr_get_u16(attr);
|
||||
device->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_JMIN:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
|
||||
device->junk_packet_min_size = mnl_attr_get_u16(attr);
|
||||
device->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_JMAX:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
|
||||
device->junk_packet_max_size = mnl_attr_get_u16(attr);
|
||||
device->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_S1:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
|
||||
device->init_packet_junk_size = mnl_attr_get_u16(attr);
|
||||
device->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_S2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U16)) {
|
||||
device->response_packet_junk_size = mnl_attr_get_u16(attr);
|
||||
device->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_H1:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
|
||||
device->init_packet_magic_header = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_H2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
|
||||
device->response_packet_magic_header = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_H3:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
|
||||
device->underload_packet_magic_header = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_H4:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32))
|
||||
{
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
|
||||
device->transport_packet_magic_header = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
@ -760,30 +648,24 @@ static int parse_device(const struct nlattr* attr, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int read_device_cb(const struct nlmsghdr* nlh, void* data)
|
||||
static int read_device_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), parse_device, data);
|
||||
}
|
||||
|
||||
static void coalesce_peers(struct wgdevice* device)
|
||||
static void coalesce_peers(struct wgdevice *device)
|
||||
{
|
||||
struct wgpeer *old_next_peer, *peer = device->first_peer;
|
||||
|
||||
while (peer && peer->next_peer)
|
||||
{
|
||||
if (memcmp(
|
||||
peer->public_key, peer->next_peer->public_key, sizeof(peer->public_key)))
|
||||
{
|
||||
while (peer && peer->next_peer) {
|
||||
if (memcmp(peer->public_key, peer->next_peer->public_key, sizeof(peer->public_key))) {
|
||||
peer = peer->next_peer;
|
||||
continue;
|
||||
}
|
||||
if (!peer->first_allowedip)
|
||||
{
|
||||
if (!peer->first_allowedip) {
|
||||
peer->first_allowedip = peer->next_peer->first_allowedip;
|
||||
peer->last_allowedip = peer->next_peer->last_allowedip;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
peer->last_allowedip->next_allowedip = peer->next_peer->first_allowedip;
|
||||
peer->last_allowedip = peer->next_peer->last_allowedip;
|
||||
}
|
||||
|
@ -793,15 +675,14 @@ static void coalesce_peers(struct wgdevice* device)
|
|||
}
|
||||
}
|
||||
|
||||
static int kernel_get_device(struct wgdevice** device, const char* iface)
|
||||
static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||
{
|
||||
int ret;
|
||||
struct nlmsghdr* nlh;
|
||||
struct mnlg_socket* nlg;
|
||||
struct nlmsghdr *nlh;
|
||||
struct mnlg_socket *nlg;
|
||||
|
||||
/* libmnl doesn't check the buffer size, so enforce that before using. */
|
||||
if (strlen(iface) >= IFNAMSIZ)
|
||||
{
|
||||
if (strlen(iface) >= IFNAMSIZ) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
@ -813,24 +694,20 @@ try_again:
|
|||
return -errno;
|
||||
|
||||
nlg = mnlg_socket_open(WG_GENL_NAME, WG_GENL_VERSION);
|
||||
if (!nlg)
|
||||
{
|
||||
if (!nlg) {
|
||||
free_wgdevice(*device);
|
||||
*device = NULL;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
nlh =
|
||||
mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
|
||||
nlh = mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
|
||||
mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, iface);
|
||||
if (mnlg_socket_send(nlg, nlh) < 0)
|
||||
{
|
||||
if (mnlg_socket_send(nlg, nlh) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
errno = 0;
|
||||
if (mnlg_socket_recv_run(nlg, read_device_cb, *device) < 0)
|
||||
{
|
||||
if (mnlg_socket_recv_run(nlg, read_device_cb, *device) < 0) {
|
||||
ret = errno ? -errno : -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -839,8 +716,7 @@ try_again:
|
|||
out:
|
||||
if (nlg)
|
||||
mnlg_socket_close(nlg);
|
||||
if (ret)
|
||||
{
|
||||
if (ret) {
|
||||
free_wgdevice(*device);
|
||||
if (ret == -EINTR)
|
||||
goto try_again;
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
* 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
|
||||
|
||||
|
@ -27,10 +27,10 @@ static int get_dgram_socket(void)
|
|||
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;
|
||||
struct ifgroupreq ifgr = { .ifgr_name = "wg" };
|
||||
struct ifg_req *ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
|
||||
if (s < 0)
|
||||
|
@ -42,14 +42,12 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
{
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
|
||||
{
|
||||
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);
|
||||
|
@ -60,15 +58,15 @@ out:
|
|||
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;
|
||||
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)
|
||||
|
@ -76,8 +74,7 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
|
||||
*device = NULL;
|
||||
strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name));
|
||||
for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size)
|
||||
{
|
||||
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)
|
||||
|
@ -93,80 +90,67 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
goto out;
|
||||
strlcpy(dev->name, iface, sizeof(dev->name));
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -226,8 +210,7 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
}
|
||||
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for (size_t i = 0; i < wg_iface->i_peers_count; ++i)
|
||||
{
|
||||
for (size_t i = 0; i < wg_iface->i_peers_count; ++i) {
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto out;
|
||||
|
@ -238,27 +221,23 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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))
|
||||
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;
|
||||
|
@ -268,8 +247,7 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
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)
|
||||
{
|
||||
for (size_t j = 0; j < wg_peer->p_aips_count; ++j) {
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto out;
|
||||
|
@ -281,19 +259,16 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
peer->last_allowedip = aip;
|
||||
|
||||
aip->family = wg_aip->a_af;
|
||||
if (wg_aip->a_af == AF_INET)
|
||||
{
|
||||
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)
|
||||
{
|
||||
} 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;
|
||||
wg_peer = (struct wg_peer_io *)wg_aip;
|
||||
}
|
||||
*device = dev;
|
||||
errno = 0;
|
||||
|
@ -303,44 +278,41 @@ out:
|
|||
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;
|
||||
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;
|
||||
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK) {
|
||||
wg_iface->i_rtable = dev->fwmark;
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE;
|
||||
}
|
||||
|
@ -348,56 +320,48 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS;
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
{
|
||||
|
||||
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)
|
||||
{
|
||||
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_JMAX)
|
||||
{
|
||||
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_S1)
|
||||
{
|
||||
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_S2)
|
||||
{
|
||||
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_H1)
|
||||
{
|
||||
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_H2)
|
||||
{
|
||||
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_H3)
|
||||
{
|
||||
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_H4)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -458,29 +422,23 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
|
||||
peer_count = 0;
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
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_PRESHARED_KEY)
|
||||
{
|
||||
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->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
{
|
||||
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->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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -492,8 +450,7 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
|
||||
aip_count = 0;
|
||||
wg_aip = &wg_peer->p_aips[0];
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
wg_aip->a_af = aip->family;
|
||||
wg_aip->a_cidr = aip->cidr;
|
||||
|
||||
|
@ -508,7 +465,7 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
}
|
||||
wg_peer->p_aips_count = aip_count;
|
||||
++peer_count;
|
||||
wg_peer = (struct wg_peer_io*)wg_aip;
|
||||
wg_peer = (struct wg_peer_io *)wg_aip;
|
||||
}
|
||||
wg_iface->i_peers_count = peer_count;
|
||||
|
||||
|
|
252
src/ipc-uapi.h
252
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,24 +25,23 @@
|
|||
#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;
|
||||
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 *key = NULL, *value;
|
||||
|
||||
f = userspace_interface_file(dev->name);
|
||||
if (!f)
|
||||
return -errno;
|
||||
fprintf(f, "set=1\n");
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
|
||||
key_to_hex(hex, dev->private_key);
|
||||
fprintf(f, "private_key=%s\n", hex);
|
||||
}
|
||||
|
@ -70,6 +69,7 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
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)
|
||||
|
@ -89,14 +89,10 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
fprintf(f, "itime=%u\n", dev->itime);
|
||||
|
||||
printf("i1: %s\n", dev->i1);
|
||||
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -105,33 +101,21 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
{
|
||||
if (peer->flags & WGPEER_REMOVE_ME) {
|
||||
fprintf(f, "remove=true\n");
|
||||
continue;
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 (!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
|
||||
|
@ -139,25 +123,17 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
}
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
fprintf(
|
||||
f,
|
||||
"persistent_keepalive_interval=%u\n",
|
||||
peer->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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
} else if (allowedip->family == AF_INET6) {
|
||||
if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
} else
|
||||
continue;
|
||||
fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
|
||||
}
|
||||
|
@ -165,8 +141,7 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
fprintf(f, "\n");
|
||||
fflush(f);
|
||||
|
||||
while (getline(&key, &line_buffer_len, f) > 0)
|
||||
{
|
||||
while (getline(&key, &line_buffer_len, f) > 0) {
|
||||
line_len = strlen(key);
|
||||
ret = set_errno;
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
|
@ -176,10 +151,9 @@ static int userspace_set_device(struct wgdevice* dev)
|
|||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
|
||||
if (!strcmp(key, "errno"))
|
||||
{
|
||||
if (!strcmp(key, "errno")) {
|
||||
long long num;
|
||||
char* end;
|
||||
char *end;
|
||||
if (value[0] != '-' && !char_is_digit(value[0]))
|
||||
break;
|
||||
num = strtoll(value, &end, 10);
|
||||
|
@ -196,26 +170,25 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define NUM(max) \
|
||||
({ \
|
||||
#define NUM(max) ({ \
|
||||
unsigned long long num; \
|
||||
char* end; \
|
||||
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;
|
||||
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;
|
||||
char *key = NULL, *value;
|
||||
FILE *f;
|
||||
int ret = -EPROTO;
|
||||
|
||||
*out = dev = calloc(1, sizeof(*dev));
|
||||
|
@ -223,8 +196,7 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
return -errno;
|
||||
|
||||
f = userspace_interface_file(iface);
|
||||
if (!f)
|
||||
{
|
||||
if (!f) {
|
||||
ret = -errno;
|
||||
free(dev);
|
||||
*out = NULL;
|
||||
|
@ -237,8 +209,7 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
strncpy(dev->name, iface, IFNAMSIZ - 1);
|
||||
dev->name[IFNAMSIZ - 1] = '\0';
|
||||
|
||||
while (getline(&key, &line_buffer_len, f) > 0)
|
||||
{
|
||||
while (getline(&key, &line_buffer_len, f) > 0) {
|
||||
line_len = strlen(key);
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
goto err;
|
||||
|
@ -247,119 +218,83 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
|
||||
if (!peer && !strcmp(key, "private_key"))
|
||||
{
|
||||
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"))
|
||||
{
|
||||
} else if (!peer && !strcmp(key, "listen_port")) {
|
||||
dev->listen_port = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "fwmark"))
|
||||
{
|
||||
} else if (!peer && !strcmp(key, "fwmark")) {
|
||||
dev->fwmark = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jc"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "jc")) {
|
||||
dev->junk_packet_count = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jmin"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "jmin")) {
|
||||
dev->junk_packet_min_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jmax"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "jmax")) {
|
||||
dev->junk_packet_max_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "s1"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "s1")) {
|
||||
dev->init_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "s2"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "s2")) {
|
||||
dev->response_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h1"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "h1")) {
|
||||
dev->init_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h2"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "h2")) {
|
||||
dev->response_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h3"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "h3")) {
|
||||
dev->underload_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h4"))
|
||||
{
|
||||
} else if(!peer && !strcmp(key, "h4")) {
|
||||
dev->transport_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i1"))
|
||||
{
|
||||
} else if (!peer && !strcmp(key, "i1")) {
|
||||
dev->i1 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i2"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "i2")) {
|
||||
dev->i2 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i3"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "i3")) {
|
||||
dev->i3 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i4"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "i4")) {
|
||||
dev->i4 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I4;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i5"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "i5")) {
|
||||
dev->i5 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I5;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j1"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "j1")) {
|
||||
dev->j1 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j2"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "j2")) {
|
||||
dev->j2 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j3"))
|
||||
{
|
||||
else if (!peer && !strcmp(key, "j3")) {
|
||||
dev->j3 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "itime"))
|
||||
{
|
||||
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));
|
||||
} else if (!strcmp(key, "public_key")) {
|
||||
struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
|
||||
|
||||
if (!new_peer)
|
||||
{
|
||||
if (!new_peer) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
@ -372,26 +307,22 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
if (!key_from_hex(peer->public_key, value))
|
||||
break;
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
else if (peer && !strcmp(key, "preshared_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;
|
||||
} 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};
|
||||
.ai_protocol = IPPROTO_UDP
|
||||
};
|
||||
if (!strlen(value))
|
||||
break;
|
||||
if (value[0] == '[')
|
||||
{
|
||||
if (value[0] == '[') {
|
||||
begin = &value[1];
|
||||
end = strchr(value, ']');
|
||||
if (!end)
|
||||
|
@ -399,47 +330,36 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
begin = value;
|
||||
end = strrchr(value, ':');
|
||||
if (!end || !*(end + 1))
|
||||
break;
|
||||
*end++ = '\0';
|
||||
}
|
||||
if (getaddrinfo(begin, end, &hints, &resolved) != 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)))
|
||||
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
|
||||
{
|
||||
else {
|
||||
freeaddrinfo(resolved);
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
}
|
||||
else if (peer && !strcmp(key, "persistent_keepalive_interval"))
|
||||
{
|
||||
} 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, "/");
|
||||
} 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)
|
||||
{
|
||||
if (!new_allowedip) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
@ -449,23 +369,17 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
peer->first_allowedip = new_allowedip;
|
||||
allowedip = new_allowedip;
|
||||
allowedip->family = AF_UNSPEC;
|
||||
if (strchr(ip, ':'))
|
||||
{
|
||||
if (strchr(ip, ':')) {
|
||||
if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1)
|
||||
allowedip->family = AF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
} 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))
|
||||
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"))
|
||||
} 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);
|
||||
|
@ -479,13 +393,13 @@ static int userspace_get_device(struct wgdevice** out, const char* iface)
|
|||
ret = -EPROTO;
|
||||
err:
|
||||
free(key);
|
||||
if (ret)
|
||||
{
|
||||
if (ret) {
|
||||
free_wgdevice(dev);
|
||||
*out = NULL;
|
||||
}
|
||||
fclose(f);
|
||||
errno = -ret;
|
||||
return ret;
|
||||
|
||||
}
|
||||
#undef NUM
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
*/
|
||||
|
||||
#include "containers.h"
|
||||
#include <cfgmgr32.h>
|
||||
#include <ddk/ndisguid.h>
|
||||
#include <devguid.h>
|
||||
#include <hashtable.h>
|
||||
#include <initguid.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <setupapi.h>
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <initguid.h>
|
||||
#include <devguid.h>
|
||||
#include <ddk/ndisguid.h>
|
||||
#include <wireguard.h>
|
||||
#include <hashtable.h>
|
||||
|
||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||
|
||||
|
@ -21,50 +21,34 @@ static struct hashtable cached_kernel_interfaces;
|
|||
static const DEVPROPKEY devpkey_name = DEVPKEY_WG_NAME;
|
||||
extern bool is_win7;
|
||||
|
||||
static int kernel_get_wireguard_interfaces(struct string_list* list)
|
||||
static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||
{
|
||||
HDEVINFO dev_info = SetupDiGetClassDevsExW(
|
||||
&GUID_DEVCLASS_NET,
|
||||
is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard",
|
||||
NULL,
|
||||
DIGCF_PRESENT,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
bool will_have_cached_kernel_interfaces = true;
|
||||
|
||||
if (dev_info == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (dev_info == INVALID_HANDLE_VALUE) {
|
||||
errno = EACCES;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (DWORD i = 0;; ++i)
|
||||
{
|
||||
for (DWORD i = 0;; ++i) {
|
||||
DWORD buf_len;
|
||||
WCHAR adapter_name[MAX_ADAPTER_NAME];
|
||||
SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)};
|
||||
SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) };
|
||||
DEVPROPTYPE prop_type;
|
||||
ULONG status, problem_code;
|
||||
char* interface_name;
|
||||
struct hashtable_entry* entry;
|
||||
char *interface_name;
|
||||
struct hashtable_entry *entry;
|
||||
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data))
|
||||
{
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDevicePropertyW(
|
||||
dev_info,
|
||||
&dev_info_data,
|
||||
&devpkey_name,
|
||||
&prop_type,
|
||||
(PBYTE)adapter_name,
|
||||
sizeof(adapter_name),
|
||||
NULL,
|
||||
0) ||
|
||||
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
|
||||
&prop_type, (PBYTE)adapter_name,
|
||||
sizeof(adapter_name), NULL, 0) ||
|
||||
prop_type != DEVPROP_TYPE_STRING)
|
||||
continue;
|
||||
adapter_name[_countof(adapter_name) - 1] = L'0';
|
||||
|
@ -76,16 +60,13 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
interface_name = malloc(buf_len);
|
||||
if (!interface_name)
|
||||
continue;
|
||||
buf_len = WideCharToMultiByte(
|
||||
CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||
if (!buf_len)
|
||||
{
|
||||
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||
if (!buf_len) {
|
||||
free(interface_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) ==
|
||||
CR_SUCCESS &&
|
||||
if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS &&
|
||||
(status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED))
|
||||
string_list_add(list, interface_name);
|
||||
|
||||
|
@ -94,15 +75,12 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
if (!entry)
|
||||
continue;
|
||||
|
||||
if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
continue;
|
||||
entry->value = calloc(sizeof(WCHAR), buf_len);
|
||||
if (!entry->value)
|
||||
continue;
|
||||
if (!SetupDiGetDeviceInstanceIdW(
|
||||
dev_info, &dev_info_data, entry->value, buf_len, &buf_len))
|
||||
{
|
||||
if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, entry->value, buf_len, &buf_len)) {
|
||||
free(entry->value);
|
||||
entry->value = NULL;
|
||||
continue;
|
||||
|
@ -115,94 +93,64 @@ static int kernel_get_wireguard_interfaces(struct string_list* list)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static HANDLE kernel_interface_handle(const char* iface)
|
||||
static HANDLE kernel_interface_handle(const char *iface)
|
||||
{
|
||||
HDEVINFO dev_info;
|
||||
WCHAR* interfaces = NULL;
|
||||
WCHAR *interfaces = NULL;
|
||||
HANDLE handle;
|
||||
|
||||
if (have_cached_kernel_interfaces)
|
||||
{
|
||||
struct hashtable_entry* entry =
|
||||
hashtable_find_entry(&cached_kernel_interfaces, iface);
|
||||
if (entry)
|
||||
{
|
||||
if (have_cached_kernel_interfaces) {
|
||||
struct hashtable_entry *entry = hashtable_find_entry(&cached_kernel_interfaces, iface);
|
||||
if (entry) {
|
||||
DWORD buf_len;
|
||||
if (CM_Get_Device_Interface_List_SizeW(
|
||||
&buf_len,
|
||||
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||
(DEVINSTID_W)entry->value,
|
||||
&buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
|
||||
goto err_hash;
|
||||
interfaces = calloc(buf_len, sizeof(*interfaces));
|
||||
if (!interfaces)
|
||||
goto err_hash;
|
||||
if (CM_Get_Device_Interface_ListW(
|
||||
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||
(DEVINSTID_W)entry->value,
|
||||
interfaces,
|
||||
buf_len,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
|
||||
!interfaces[0])
|
||||
{
|
||||
(GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value, interfaces, buf_len,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
|
||||
free(interfaces);
|
||||
interfaces = NULL;
|
||||
goto err_hash;
|
||||
}
|
||||
handle = CreateFileW(
|
||||
interfaces,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
free(interfaces);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
goto err_hash;
|
||||
return handle;
|
||||
err_hash:
|
||||
err_hash:
|
||||
errno = EACCES;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dev_info = SetupDiGetClassDevsExW(
|
||||
&GUID_DEVCLASS_NET,
|
||||
is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard",
|
||||
NULL,
|
||||
DIGCF_PRESENT,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
if (dev_info == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
for (DWORD i = 0; !interfaces; ++i)
|
||||
{
|
||||
for (DWORD i = 0; !interfaces; ++i) {
|
||||
bool found;
|
||||
DWORD buf_len;
|
||||
WCHAR * buf, adapter_name[MAX_ADAPTER_NAME];
|
||||
SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)};
|
||||
WCHAR *buf, adapter_name[MAX_ADAPTER_NAME];
|
||||
SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) };
|
||||
DEVPROPTYPE prop_type;
|
||||
char* interface_name;
|
||||
char *interface_name;
|
||||
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data))
|
||||
{
|
||||
if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) {
|
||||
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SetupDiGetDevicePropertyW(
|
||||
dev_info,
|
||||
&dev_info_data,
|
||||
&devpkey_name,
|
||||
&prop_type,
|
||||
(PBYTE)adapter_name,
|
||||
sizeof(adapter_name),
|
||||
NULL,
|
||||
0) ||
|
||||
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
|
||||
&prop_type, (PBYTE)adapter_name,
|
||||
sizeof(adapter_name), NULL, 0) ||
|
||||
prop_type != DEVPROP_TYPE_STRING)
|
||||
continue;
|
||||
adapter_name[_countof(adapter_name) - 1] = L'0';
|
||||
|
@ -214,10 +162,8 @@ static HANDLE kernel_interface_handle(const char* iface)
|
|||
interface_name = malloc(buf_len);
|
||||
if (!interface_name)
|
||||
continue;
|
||||
buf_len = WideCharToMultiByte(
|
||||
CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||
if (!buf_len)
|
||||
{
|
||||
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||
if (!buf_len) {
|
||||
free(interface_name);
|
||||
continue;
|
||||
}
|
||||
|
@ -226,73 +172,57 @@ static HANDLE kernel_interface_handle(const char* iface)
|
|||
if (!found)
|
||||
continue;
|
||||
|
||||
if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) ||
|
||||
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
continue;
|
||||
buf = calloc(sizeof(*buf), buf_len);
|
||||
if (!buf)
|
||||
continue;
|
||||
if (!SetupDiGetDeviceInstanceIdW(
|
||||
dev_info, &dev_info_data, buf, buf_len, &buf_len))
|
||||
if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, buf, buf_len, &buf_len))
|
||||
goto cleanup_instance_id;
|
||||
if (CM_Get_Device_Interface_List_SizeW(
|
||||
&buf_len,
|
||||
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||
(DEVINSTID_W)buf,
|
||||
&buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
|
||||
goto cleanup_instance_id;
|
||||
interfaces = calloc(buf_len, sizeof(*interfaces));
|
||||
if (!interfaces)
|
||||
goto cleanup_instance_id;
|
||||
if (CM_Get_Device_Interface_ListW(
|
||||
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||
(DEVINSTID_W)buf,
|
||||
interfaces,
|
||||
buf_len,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
|
||||
!interfaces[0])
|
||||
{
|
||||
(GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf, interfaces, buf_len,
|
||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
|
||||
free(interfaces);
|
||||
interfaces = NULL;
|
||||
goto cleanup_instance_id;
|
||||
}
|
||||
cleanup_instance_id:
|
||||
cleanup_instance_id:
|
||||
free(buf);
|
||||
}
|
||||
SetupDiDestroyDeviceInfoList(dev_info);
|
||||
if (!interfaces)
|
||||
{
|
||||
if (!interfaces) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
handle = CreateFileW(
|
||||
interfaces,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
free(interfaces);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
errno = EACCES;
|
||||
return NULL;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
static int kernel_get_device(struct wgdevice** device, const char* iface)
|
||||
static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||
{
|
||||
WG_IOCTL_INTERFACE* wg_iface;
|
||||
WG_IOCTL_PEER* wg_peer;
|
||||
WG_IOCTL_ALLOWED_IP* wg_aip;
|
||||
void* buf = NULL;
|
||||
WG_IOCTL_INTERFACE *wg_iface;
|
||||
WG_IOCTL_PEER *wg_peer;
|
||||
WG_IOCTL_ALLOWED_IP *wg_aip;
|
||||
void *buf = NULL;
|
||||
DWORD buf_len = 0;
|
||||
HANDLE handle = kernel_interface_handle(iface);
|
||||
struct wgdevice* dev;
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip;
|
||||
struct wgdevice *dev;
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip;
|
||||
int ret;
|
||||
|
||||
*device = NULL;
|
||||
|
@ -300,11 +230,9 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
if (!handle)
|
||||
return -errno;
|
||||
|
||||
while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL))
|
||||
{
|
||||
while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) {
|
||||
free(buf);
|
||||
if (GetLastError() != ERROR_MORE_DATA)
|
||||
{
|
||||
if (GetLastError() != ERROR_MORE_DATA) {
|
||||
errno = EACCES;
|
||||
return -errno;
|
||||
}
|
||||
|
@ -313,73 +241,61 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
wg_iface = (WG_IOCTL_INTERFACE*)buf;
|
||||
wg_iface = (WG_IOCTL_INTERFACE *)buf;
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
goto out;
|
||||
strncpy(dev->name, iface, sizeof(dev->name));
|
||||
dev->name[sizeof(dev->name) - 1] = '\0';
|
||||
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT) {
|
||||
dev->listen_port = wg_iface->ListenPort;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY) {
|
||||
memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY) {
|
||||
memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC) {
|
||||
dev->junk_packet_count = wg_iface->JunkPacketCount;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN) {
|
||||
dev->junk_packet_min_size = wg_iface->JunkPacketMinSize;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX) {
|
||||
dev->junk_packet_max_size = wg_iface->JunkPacketMaxSize;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1) {
|
||||
dev->init_packet_junk_size = wg_iface->InitPacketJunkSize;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2) {
|
||||
dev->response_packet_junk_size = wg_iface->ResponsePacketJunkSize;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1) {
|
||||
dev->init_packet_magic_header = wg_iface->InitPacketMagicHeader;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2) {
|
||||
dev->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3) {
|
||||
dev->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4)
|
||||
{
|
||||
if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4) {
|
||||
dev->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
@ -446,8 +362,7 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
}
|
||||
|
||||
wg_peer = buf + sizeof(WG_IOCTL_INTERFACE);
|
||||
for (ULONG i = 0; i < wg_iface->PeersCount; ++i)
|
||||
{
|
||||
for (ULONG i = 0; i < wg_iface->PeersCount; ++i) {
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto out;
|
||||
|
@ -458,28 +373,23 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY)
|
||||
{
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY) {
|
||||
memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
memcpy(
|
||||
peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY) {
|
||||
memcpy(peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE)
|
||||
{
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE) {
|
||||
peer->persistent_keepalive_interval = wg_peer->PersistentKeepalive;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT)
|
||||
{
|
||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT) {
|
||||
if (wg_peer->Endpoint.si_family == AF_INET)
|
||||
peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4;
|
||||
else if (wg_peer->Endpoint.si_family == AF_INET6)
|
||||
|
@ -489,16 +399,13 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
peer->rx_bytes = wg_peer->RxBytes;
|
||||
peer->tx_bytes = wg_peer->TxBytes;
|
||||
|
||||
if (wg_peer->LastHandshake)
|
||||
{
|
||||
peer->last_handshake_time.tv_sec =
|
||||
wg_peer->LastHandshake / 10000000 - 11644473600LL;
|
||||
if (wg_peer->LastHandshake) {
|
||||
peer->last_handshake_time.tv_sec = wg_peer->LastHandshake / 10000000 - 11644473600LL;
|
||||
peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100;
|
||||
}
|
||||
|
||||
wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||
for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j)
|
||||
{
|
||||
wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||
for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j) {
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto out;
|
||||
|
@ -510,19 +417,16 @@ static int kernel_get_device(struct wgdevice** device, const char* iface)
|
|||
peer->last_allowedip = aip;
|
||||
|
||||
aip->family = wg_aip->AddressFamily;
|
||||
if (wg_aip->AddressFamily == AF_INET)
|
||||
{
|
||||
if (wg_aip->AddressFamily == AF_INET) {
|
||||
memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4));
|
||||
aip->cidr = wg_aip->Cidr;
|
||||
}
|
||||
else if (wg_aip->AddressFamily == AF_INET6)
|
||||
{
|
||||
} else if (wg_aip->AddressFamily == AF_INET6) {
|
||||
memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6));
|
||||
aip->cidr = wg_aip->Cidr;
|
||||
}
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer = (WG_IOCTL_PEER*)wg_aip;
|
||||
wg_peer = (WG_IOCTL_PEER *)wg_aip;
|
||||
}
|
||||
*device = dev;
|
||||
errno = 0;
|
||||
|
@ -533,33 +437,29 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_set_device(struct wgdevice* dev)
|
||||
static int kernel_set_device(struct wgdevice *dev)
|
||||
{
|
||||
WG_IOCTL_INTERFACE* wg_iface = NULL;
|
||||
WG_IOCTL_PEER* wg_peer;
|
||||
WG_IOCTL_ALLOWED_IP* wg_aip;
|
||||
WG_IOCTL_INTERFACE *wg_iface = NULL;
|
||||
WG_IOCTL_PEER *wg_peer;
|
||||
WG_IOCTL_ALLOWED_IP *wg_aip;
|
||||
DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
|
||||
HANDLE handle = kernel_interface_handle(dev->name);
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip;
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip;
|
||||
size_t peer_count, aip_count;
|
||||
int ret = 0;
|
||||
|
||||
if (!handle)
|
||||
return -errno;
|
||||
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER))
|
||||
{
|
||||
for_each_wgpeer(dev, peer) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) {
|
||||
errno = EOVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
buf_len += sizeof(WG_IOCTL_PEER);
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP))
|
||||
{
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) {
|
||||
errno = EOVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
@ -570,14 +470,12 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
if (!wg_iface)
|
||||
goto out;
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
|
||||
memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) {
|
||||
wg_iface->ListenPort = dev->listen_port;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT;
|
||||
}
|
||||
|
@ -585,59 +483,51 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_REPLACE_PEERS;
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_JC) {
|
||||
wg_iface->JunkPacketCount = dev->junk_packet_count;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JC;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN) {
|
||||
wg_iface->JunkPacketMinSize = dev->junk_packet_min_size;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX) {
|
||||
wg_iface->JunkPacketMaxSize = dev->junk_packet_max_size;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_S1) {
|
||||
wg_iface->InitPacketJunkSize = dev->init_packet_junk_size;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_S1;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_S2) {
|
||||
wg_iface->ResponsePacketJunkSize = dev->response_packet_junk_size;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_S2;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_H1) {
|
||||
wg_iface->InitPacketMagicHeader = dev->init_packet_magic_header;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H1;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_H2) {
|
||||
wg_iface->ResponsePacketMagicHeader = dev->response_packet_magic_header;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H2;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_H3) {
|
||||
wg_iface->UnderloadPacketMagicHeader = dev->underload_packet_magic_header;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H3;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
{
|
||||
if (dev->flags & WGDEVICE_HAS_H4) {
|
||||
wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header;
|
||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H4;
|
||||
}
|
||||
|
||||
if (dev->flags & WG_DEVICE_HAS_I1)
|
||||
{
|
||||
const size_t i1_size = strlen(dev->i1) + 1;
|
||||
|
@ -701,34 +591,25 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
}
|
||||
|
||||
peer_count = 0;
|
||||
wg_peer = (void*)wg_iface + sizeof(WG_IOCTL_INTERFACE);
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
wg_peer = (void *)wg_iface + sizeof(WG_IOCTL_INTERFACE);
|
||||
for_each_wgpeer(dev, peer) {
|
||||
wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY;
|
||||
memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey));
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
memcpy(
|
||||
wg_peer->PresharedKey,
|
||||
peer->preshared_key,
|
||||
sizeof(wg_peer->PresharedKey));
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
|
||||
memcpy(wg_peer->PresharedKey, peer->preshared_key, sizeof(wg_peer->PresharedKey));
|
||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
{
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
|
||||
wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval;
|
||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE;
|
||||
}
|
||||
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
{
|
||||
if (peer->endpoint.addr.sa_family == AF_INET) {
|
||||
wg_peer->Endpoint.Ipv4 = peer->endpoint.addr4;
|
||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
|
||||
}
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
{
|
||||
} else if (peer->endpoint.addr.sa_family == AF_INET6) {
|
||||
wg_peer->Endpoint.Ipv6 = peer->endpoint.addr6;
|
||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
|
||||
}
|
||||
|
@ -740,9 +621,8 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
wg_peer->Flags |= WG_IOCTL_PEER_REMOVE;
|
||||
|
||||
aip_count = 0;
|
||||
wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
wg_aip->AddressFamily = aip->family;
|
||||
wg_aip->Cidr = aip->cidr;
|
||||
|
||||
|
@ -757,13 +637,11 @@ static int kernel_set_device(struct wgdevice* dev)
|
|||
}
|
||||
wg_peer->AllowedIPsCount = aip_count;
|
||||
++peer_count;
|
||||
wg_peer = (WG_IOCTL_PEER*)wg_aip;
|
||||
wg_peer = (WG_IOCTL_PEER *)wg_aip;
|
||||
}
|
||||
wg_iface->PeersCount = peer_count;
|
||||
|
||||
if (!DeviceIoControl(
|
||||
handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL))
|
||||
{
|
||||
if (!DeviceIoControl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) {
|
||||
errno = EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
|
461
src/netlink.h
461
src/netlink.h
|
@ -6,27 +6,26 @@
|
|||
|
||||
/* This is a minimized version of libmnl meant to be #include'd */
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#define MNL_SOCKET_AUTOPID 0
|
||||
#define MNL_ALIGNTO 4
|
||||
#define MNL_ALIGN(len) (((len) + MNL_ALIGNTO - 1) & ~(MNL_ALIGNTO - 1))
|
||||
#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1))
|
||||
#define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
|
||||
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
||||
|
||||
enum mnl_attr_data_type
|
||||
{
|
||||
enum mnl_attr_data_type {
|
||||
MNL_TYPE_UNSPEC,
|
||||
MNL_TYPE_U8,
|
||||
MNL_TYPE_U16,
|
||||
|
@ -44,30 +43,28 @@ enum mnl_attr_data_type
|
|||
|
||||
#define mnl_attr_for_each(attr, nlh, offset) \
|
||||
for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \
|
||||
mnl_attr_ok((attr), (char*)mnl_nlmsg_get_payload_tail(nlh) - (char*)(attr)); \
|
||||
mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_nested(attr, nest) \
|
||||
for ((attr) = mnl_attr_get_payload(nest); mnl_attr_ok( \
|
||||
(attr), \
|
||||
(char*)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - \
|
||||
(char*)(attr)); \
|
||||
for ((attr) = mnl_attr_get_payload(nest); \
|
||||
mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define mnl_attr_for_each_payload(payload, payload_size) \
|
||||
for ((attr) = (payload); \
|
||||
mnl_attr_ok((attr), (char*)(payload) + payload_size - (char*)(attr)); \
|
||||
mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \
|
||||
(attr) = mnl_attr_next(attr))
|
||||
|
||||
#define MNL_CB_ERROR -1
|
||||
#define MNL_CB_STOP 0
|
||||
#define MNL_CB_OK 1
|
||||
|
||||
typedef int (*mnl_attr_cb_t)(const struct nlattr* attr, void* data);
|
||||
typedef int (*mnl_cb_t)(const struct nlmsghdr* nlh, void* data);
|
||||
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data);
|
||||
typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data);
|
||||
|
||||
#ifndef MNL_ARRAY_SIZE
|
||||
#define MNL_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
static size_t mnl_ideal_socket_buffer_size(void)
|
||||
|
@ -82,137 +79,133 @@ static size_t mnl_ideal_socket_buffer_size(void)
|
|||
return size;
|
||||
}
|
||||
|
||||
static size_t mnl_nlmsg_size(size_t len) { return len + MNL_NLMSG_HDRLEN; }
|
||||
static size_t mnl_nlmsg_size(size_t len)
|
||||
{
|
||||
return len + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
static struct nlmsghdr* mnl_nlmsg_put_header(void* buf)
|
||||
static struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
|
||||
{
|
||||
int len = MNL_ALIGN(sizeof(struct nlmsghdr));
|
||||
struct nlmsghdr* nlh = buf;
|
||||
struct nlmsghdr *nlh = buf;
|
||||
|
||||
memset(buf, 0, len);
|
||||
nlh->nlmsg_len = len;
|
||||
return nlh;
|
||||
}
|
||||
|
||||
static void* mnl_nlmsg_put_extra_header(struct nlmsghdr* nlh, size_t size)
|
||||
static void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
|
||||
{
|
||||
char* ptr = (char*)nlh + nlh->nlmsg_len;
|
||||
char *ptr = (char *)nlh + nlh->nlmsg_len;
|
||||
size_t len = MNL_ALIGN(size);
|
||||
nlh->nlmsg_len += len;
|
||||
memset(ptr, 0, len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void* mnl_nlmsg_get_payload(const struct nlmsghdr* nlh)
|
||||
static void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void*)nlh + MNL_NLMSG_HDRLEN;
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN;
|
||||
}
|
||||
|
||||
static void* mnl_nlmsg_get_payload_offset(const struct nlmsghdr* nlh, size_t offset)
|
||||
static void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
|
||||
{
|
||||
return (void*)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
|
||||
return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
|
||||
}
|
||||
|
||||
static bool mnl_nlmsg_ok(const struct nlmsghdr* nlh, int len)
|
||||
static bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlmsghdr) &&
|
||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) && (int)nlh->nlmsg_len <= len;
|
||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||
(int)nlh->nlmsg_len <= len;
|
||||
}
|
||||
|
||||
static struct nlmsghdr* mnl_nlmsg_next(const struct nlmsghdr* nlh, int* len)
|
||||
static struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
|
||||
{
|
||||
*len -= MNL_ALIGN(nlh->nlmsg_len);
|
||||
return (struct nlmsghdr*)((void*)nlh + MNL_ALIGN(nlh->nlmsg_len));
|
||||
return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
|
||||
}
|
||||
|
||||
static void* mnl_nlmsg_get_payload_tail(const struct nlmsghdr* nlh)
|
||||
static void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
|
||||
{
|
||||
return (void*)nlh + MNL_ALIGN(nlh->nlmsg_len);
|
||||
return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
|
||||
}
|
||||
|
||||
static bool mnl_nlmsg_seq_ok(const struct nlmsghdr* nlh, unsigned int seq)
|
||||
static bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
|
||||
{
|
||||
return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
|
||||
}
|
||||
|
||||
static bool mnl_nlmsg_portid_ok(const struct nlmsghdr* nlh, unsigned int portid)
|
||||
static bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
|
||||
{
|
||||
return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
|
||||
}
|
||||
|
||||
static uint16_t mnl_attr_get_type(const struct nlattr* attr)
|
||||
static uint16_t mnl_attr_get_type(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_type & NLA_TYPE_MASK;
|
||||
}
|
||||
|
||||
static uint16_t mnl_attr_get_payload_len(const struct nlattr* attr)
|
||||
static uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
|
||||
{
|
||||
return attr->nla_len - MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
static void* mnl_attr_get_payload(const struct nlattr* attr)
|
||||
static void *mnl_attr_get_payload(const struct nlattr *attr)
|
||||
{
|
||||
return (void*)attr + MNL_ATTR_HDRLEN;
|
||||
return (void *)attr + MNL_ATTR_HDRLEN;
|
||||
}
|
||||
|
||||
static bool mnl_attr_ok(const struct nlattr* attr, int len)
|
||||
static bool mnl_attr_ok(const struct nlattr *attr, int len)
|
||||
{
|
||||
return len >= (int)sizeof(struct nlattr) && attr->nla_len >= sizeof(struct nlattr) &&
|
||||
return len >= (int)sizeof(struct nlattr) &&
|
||||
attr->nla_len >= sizeof(struct nlattr) &&
|
||||
(int)attr->nla_len <= len;
|
||||
}
|
||||
|
||||
static struct nlattr* mnl_attr_next(const struct nlattr* attr)
|
||||
static struct nlattr *mnl_attr_next(const struct nlattr *attr)
|
||||
{
|
||||
return (struct nlattr*)((void*)attr + MNL_ALIGN(attr->nla_len));
|
||||
return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
|
||||
}
|
||||
|
||||
static int mnl_attr_type_valid(const struct nlattr* attr, uint16_t max)
|
||||
static int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
|
||||
{
|
||||
if (mnl_attr_get_type(attr) > max)
|
||||
{
|
||||
if (mnl_attr_get_type(attr) > max) {
|
||||
errno = EOPNOTSUPP;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __mnl_attr_validate(
|
||||
const struct nlattr* attr,
|
||||
enum mnl_attr_data_type type,
|
||||
size_t exp_len)
|
||||
static int __mnl_attr_validate(const struct nlattr *attr,
|
||||
enum mnl_attr_data_type type, size_t exp_len)
|
||||
{
|
||||
uint16_t attr_len = mnl_attr_get_payload_len(attr);
|
||||
const char* attr_data = mnl_attr_get_payload(attr);
|
||||
const char *attr_data = mnl_attr_get_payload(attr);
|
||||
|
||||
if (attr_len < exp_len)
|
||||
{
|
||||
if (attr_len < exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
switch(type) {
|
||||
case MNL_TYPE_FLAG:
|
||||
if (attr_len > 0)
|
||||
{
|
||||
if (attr_len > 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
if (attr_len == 0)
|
||||
{
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
if (attr_data[attr_len - 1] != '\0')
|
||||
{
|
||||
if (attr_data[attr_len-1] != '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case MNL_TYPE_STRING:
|
||||
if (attr_len == 0)
|
||||
{
|
||||
if (attr_len == 0) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
@ -222,8 +215,7 @@ static int __mnl_attr_validate(
|
|||
if (attr_len == 0)
|
||||
break;
|
||||
|
||||
if (attr_len < MNL_ATTR_HDRLEN)
|
||||
{
|
||||
if (attr_len < MNL_ATTR_HDRLEN) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
@ -232,8 +224,7 @@ static int __mnl_attr_validate(
|
|||
|
||||
break;
|
||||
}
|
||||
if (exp_len && attr_len > exp_len)
|
||||
{
|
||||
if (exp_len && attr_len > exp_len) {
|
||||
errno = ERANGE;
|
||||
return -1;
|
||||
}
|
||||
|
@ -248,12 +239,11 @@ static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
|
|||
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
||||
};
|
||||
|
||||
static int mnl_attr_validate(const struct nlattr* attr, enum mnl_attr_data_type type)
|
||||
static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
|
||||
{
|
||||
int exp_len;
|
||||
|
||||
if (type >= MNL_TYPE_MAX)
|
||||
{
|
||||
if (type >= MNL_TYPE_MAX) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
@ -261,105 +251,99 @@ static int mnl_attr_validate(const struct nlattr* attr, enum mnl_attr_data_type
|
|||
return __mnl_attr_validate(attr, type, exp_len);
|
||||
}
|
||||
|
||||
static int mnl_attr_parse(
|
||||
const struct nlmsghdr* nlh,
|
||||
unsigned int offset,
|
||||
mnl_attr_cb_t cb,
|
||||
void* data)
|
||||
static int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
|
||||
mnl_attr_cb_t cb, void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr* attr;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each(
|
||||
attr, nlh, offset) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
|
||||
mnl_attr_for_each(attr, nlh, offset)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mnl_attr_parse_nested(const struct nlattr* nested, mnl_attr_cb_t cb, void* data)
|
||||
static int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
|
||||
void *data)
|
||||
{
|
||||
int ret = MNL_CB_OK;
|
||||
const struct nlattr* attr;
|
||||
const struct nlattr *attr;
|
||||
|
||||
mnl_attr_for_each_nested(
|
||||
attr, nested) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
|
||||
mnl_attr_for_each_nested(attr, nested)
|
||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t mnl_attr_get_u8(const struct nlattr* attr)
|
||||
static uint8_t mnl_attr_get_u8(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint8_t*)mnl_attr_get_payload(attr));
|
||||
return *((uint8_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
static uint16_t mnl_attr_get_u16(const struct nlattr* attr)
|
||||
static uint16_t mnl_attr_get_u16(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint16_t*)mnl_attr_get_payload(attr));
|
||||
return *((uint16_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
static uint32_t mnl_attr_get_u32(const struct nlattr* attr)
|
||||
static uint32_t mnl_attr_get_u32(const struct nlattr *attr)
|
||||
{
|
||||
return *((uint32_t*)mnl_attr_get_payload(attr));
|
||||
return *((uint32_t *)mnl_attr_get_payload(attr));
|
||||
}
|
||||
|
||||
static uint64_t mnl_attr_get_u64(const struct nlattr* attr)
|
||||
static uint64_t mnl_attr_get_u64(const struct nlattr *attr)
|
||||
{
|
||||
uint64_t tmp;
|
||||
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static const char* mnl_attr_get_str(const struct nlattr* attr)
|
||||
static const char *mnl_attr_get_str(const struct nlattr *attr)
|
||||
{
|
||||
return mnl_attr_get_payload(attr);
|
||||
}
|
||||
|
||||
static void
|
||||
mnl_attr_put(struct nlmsghdr* nlh, uint16_t type, size_t len, const void* data)
|
||||
static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len,
|
||||
const void *data)
|
||||
{
|
||||
struct nlattr* attr = mnl_nlmsg_get_payload_tail(nlh);
|
||||
struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
|
||||
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
|
||||
int pad;
|
||||
|
||||
attr->nla_type = type;
|
||||
attr->nla_len = payload_len;
|
||||
memcpy(mnl_attr_get_payload(attr), data, len);
|
||||
|
||||
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
||||
pad = MNL_ALIGN(len) - len;
|
||||
if (pad > 0)
|
||||
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
||||
}
|
||||
|
||||
static void mnl_attr_put_u16(struct nlmsghdr* nlh, uint16_t type, uint16_t data)
|
||||
static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
static void mnl_attr_put_u32(struct nlmsghdr* nlh, uint16_t type, uint32_t data)
|
||||
static void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
static void mnl_attr_put_strz(struct nlmsghdr* nlh, uint16_t type, const char* data)
|
||||
static void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
|
||||
{
|
||||
mnl_attr_put(nlh, type, strlen(data) + 1, data);
|
||||
mnl_attr_put(nlh, type, strlen(data)+1, data);
|
||||
}
|
||||
|
||||
static struct nlattr* mnl_attr_nest_start(struct nlmsghdr* nlh, uint16_t type)
|
||||
static struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
|
||||
{
|
||||
struct nlattr* start = mnl_nlmsg_get_payload_tail(nlh);
|
||||
struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
|
||||
|
||||
start->nla_type = NLA_F_NESTED | type;
|
||||
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
||||
return start;
|
||||
}
|
||||
|
||||
static bool mnl_attr_put_check(
|
||||
struct nlmsghdr* nlh,
|
||||
size_t buflen,
|
||||
uint16_t type,
|
||||
size_t len,
|
||||
const void* data)
|
||||
static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, size_t len, const void *data)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
|
||||
return false;
|
||||
|
@ -367,55 +351,52 @@ static bool mnl_attr_put_check(
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
mnl_attr_put_u8_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint8_t data)
|
||||
static bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint8_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
static bool
|
||||
mnl_attr_put_u16_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint16_t data)
|
||||
static bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint16_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
||||
}
|
||||
|
||||
static bool
|
||||
mnl_attr_put_u32_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint32_t data)
|
||||
static bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type, uint32_t data)
|
||||
{
|
||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
||||
}
|
||||
|
||||
static struct nlattr*
|
||||
mnl_attr_nest_start_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type)
|
||||
static struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen,
|
||||
uint16_t type)
|
||||
{
|
||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
||||
return NULL;
|
||||
return mnl_attr_nest_start(nlh, type);
|
||||
}
|
||||
|
||||
static void mnl_attr_nest_end(struct nlmsghdr* nlh, struct nlattr* start)
|
||||
static void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
|
||||
{
|
||||
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
|
||||
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
static void mnl_attr_nest_cancel(struct nlmsghdr* nlh, struct nlattr* start)
|
||||
static void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
|
||||
{
|
||||
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
|
||||
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
||||
}
|
||||
|
||||
static int mnl_cb_noop(
|
||||
__attribute__((unused)) const struct nlmsghdr* nlh,
|
||||
__attribute__((unused)) void* data)
|
||||
static int mnl_cb_noop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
||||
{
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int mnl_cb_error(const struct nlmsghdr* nlh, __attribute__((unused)) void* data)
|
||||
static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
||||
{
|
||||
const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh);
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
|
||||
{
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
||||
errno = EBADMSG;
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
@ -428,9 +409,7 @@ static int mnl_cb_error(const struct nlmsghdr* nlh, __attribute__((unused)) void
|
|||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
static int mnl_cb_stop(
|
||||
__attribute__((unused)) const struct nlmsghdr* nlh,
|
||||
__attribute__((unused)) void* data)
|
||||
static int mnl_cb_stop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
||||
{
|
||||
return MNL_CB_STOP;
|
||||
}
|
||||
|
@ -442,60 +421,45 @@ static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
|
|||
[NLMSG_OVERRUN] = mnl_cb_noop,
|
||||
};
|
||||
|
||||
static int __mnl_cb_run(
|
||||
const void* buf,
|
||||
size_t numbytes,
|
||||
unsigned int seq,
|
||||
unsigned int portid,
|
||||
mnl_cb_t cb_data,
|
||||
void* data,
|
||||
const mnl_cb_t* cb_ctl_array,
|
||||
static int __mnl_cb_run(const void *buf, size_t numbytes,
|
||||
unsigned int seq, unsigned int portid,
|
||||
mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
{
|
||||
int ret = MNL_CB_OK, len = numbytes;
|
||||
const struct nlmsghdr* nlh = buf;
|
||||
const struct nlmsghdr *nlh = buf;
|
||||
|
||||
while (mnl_nlmsg_ok(nlh, len))
|
||||
{
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
|
||||
if (!mnl_nlmsg_portid_ok(nlh, portid))
|
||||
{
|
||||
if (!mnl_nlmsg_portid_ok(nlh, portid)) {
|
||||
errno = ESRCH;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!mnl_nlmsg_seq_ok(nlh, seq))
|
||||
{
|
||||
if (!mnl_nlmsg_seq_ok(nlh, seq)) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR)
|
||||
{
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE)
|
||||
{
|
||||
if (cb_data)
|
||||
{
|
||||
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
|
||||
if (cb_data){
|
||||
ret = cb_data(nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (nlh->nlmsg_type < cb_ctl_array_len)
|
||||
{
|
||||
if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type])
|
||||
{
|
||||
} else if (nlh->nlmsg_type < cb_ctl_array_len) {
|
||||
if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
|
||||
ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if (default_cb_array[nlh->nlmsg_type])
|
||||
{
|
||||
} else if (default_cb_array[nlh->nlmsg_type]) {
|
||||
ret = default_cb_array[nlh->nlmsg_type](nlh, data);
|
||||
if (ret <= MNL_CB_STOP)
|
||||
goto out;
|
||||
|
@ -506,53 +470,40 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mnl_cb_run2(
|
||||
const void* buf,
|
||||
size_t numbytes,
|
||||
unsigned int seq,
|
||||
unsigned int portid,
|
||||
mnl_cb_t cb_data,
|
||||
void* data,
|
||||
const mnl_cb_t* cb_ctl_array,
|
||||
unsigned int cb_ctl_array_len)
|
||||
static int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data,
|
||||
const mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
|
||||
{
|
||||
return __mnl_cb_run(
|
||||
buf, numbytes, seq, portid, cb_data, data, cb_ctl_array, cb_ctl_array_len);
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
|
||||
cb_ctl_array, cb_ctl_array_len);
|
||||
}
|
||||
|
||||
static int mnl_cb_run(
|
||||
const void* buf,
|
||||
size_t numbytes,
|
||||
unsigned int seq,
|
||||
unsigned int portid,
|
||||
mnl_cb_t cb_data,
|
||||
void* data)
|
||||
static int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
|
||||
unsigned int portid, mnl_cb_t cb_data, void *data)
|
||||
{
|
||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
||||
}
|
||||
|
||||
struct mnl_socket
|
||||
{
|
||||
struct mnl_socket {
|
||||
int fd;
|
||||
struct sockaddr_nl addr;
|
||||
};
|
||||
|
||||
static unsigned int mnl_socket_get_portid(const struct mnl_socket* nl)
|
||||
static unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
||||
{
|
||||
return nl->addr.nl_pid;
|
||||
}
|
||||
|
||||
static struct mnl_socket* __mnl_socket_open(int bus, int flags)
|
||||
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||
{
|
||||
struct mnl_socket* nl;
|
||||
struct mnl_socket *nl;
|
||||
|
||||
nl = calloc(1, sizeof(struct mnl_socket));
|
||||
if (nl == NULL)
|
||||
return NULL;
|
||||
|
||||
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||
if (nl->fd == -1)
|
||||
{
|
||||
if (nl->fd == -1) {
|
||||
free(nl);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -560,9 +511,12 @@ static struct mnl_socket* __mnl_socket_open(int bus, int flags)
|
|||
return nl;
|
||||
}
|
||||
|
||||
static struct mnl_socket* mnl_socket_open(int bus) { return __mnl_socket_open(bus, 0); }
|
||||
static struct mnl_socket *mnl_socket_open(int bus)
|
||||
{
|
||||
return __mnl_socket_open(bus, 0);
|
||||
}
|
||||
|
||||
static int mnl_socket_bind(struct mnl_socket* nl, unsigned int groups, pid_t pid)
|
||||
static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
socklen_t addr_len;
|
||||
|
@ -571,35 +525,38 @@ static int mnl_socket_bind(struct mnl_socket* nl, unsigned int groups, pid_t pid
|
|||
nl->addr.nl_groups = groups;
|
||||
nl->addr.nl_pid = pid;
|
||||
|
||||
ret = bind(nl->fd, (struct sockaddr*)&nl->addr, sizeof(nl->addr));
|
||||
ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
addr_len = sizeof(nl->addr);
|
||||
ret = getsockname(nl->fd, (struct sockaddr*)&nl->addr, &addr_len);
|
||||
ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (addr_len != sizeof(nl->addr))
|
||||
{
|
||||
if (addr_len != sizeof(nl->addr)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nl->addr.nl_family != AF_NETLINK)
|
||||
{
|
||||
if (nl->addr.nl_family != AF_NETLINK) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t mnl_socket_sendto(const struct mnl_socket* nl, const void* buf, size_t len)
|
||||
static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf,
|
||||
size_t len)
|
||||
{
|
||||
static const struct sockaddr_nl snl = {.nl_family = AF_NETLINK};
|
||||
return sendto(nl->fd, buf, len, 0, (struct sockaddr*)&snl, sizeof(snl));
|
||||
static const struct sockaddr_nl snl = {
|
||||
.nl_family = AF_NETLINK
|
||||
};
|
||||
return sendto(nl->fd, buf, len, 0,
|
||||
(struct sockaddr *) &snl, sizeof(snl));
|
||||
}
|
||||
|
||||
static ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_t bufsiz)
|
||||
static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf,
|
||||
size_t bufsiz)
|
||||
{
|
||||
ssize_t ret;
|
||||
struct sockaddr_nl addr;
|
||||
|
@ -620,20 +577,18 @@ static ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_
|
|||
if (ret == -1)
|
||||
return ret;
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC)
|
||||
{
|
||||
if (msg.msg_flags & MSG_TRUNC) {
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
}
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl))
|
||||
{
|
||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mnl_socket_close(struct mnl_socket* nl)
|
||||
static int mnl_socket_close(struct mnl_socket *nl)
|
||||
{
|
||||
int ret = close(nl->fd);
|
||||
free(nl);
|
||||
|
@ -642,25 +597,21 @@ static int mnl_socket_close(struct mnl_socket* nl)
|
|||
|
||||
/* This is a wrapper for generic netlink, originally from Jiri Pirko <jiri@mellanox.com>: */
|
||||
|
||||
struct mnlg_socket
|
||||
{
|
||||
struct mnl_socket* nl;
|
||||
char* buf;
|
||||
struct mnlg_socket {
|
||||
struct mnl_socket *nl;
|
||||
char *buf;
|
||||
uint16_t id;
|
||||
uint8_t version;
|
||||
unsigned int seq;
|
||||
unsigned int portid;
|
||||
};
|
||||
|
||||
static struct nlmsghdr* __mnlg_msg_prepare(
|
||||
struct mnlg_socket* nlg,
|
||||
uint8_t cmd,
|
||||
uint16_t flags,
|
||||
uint16_t id,
|
||||
static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
||||
uint16_t flags, uint16_t id,
|
||||
uint8_t version)
|
||||
{
|
||||
struct nlmsghdr* nlh;
|
||||
struct genlmsghdr* genl;
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *genl;
|
||||
|
||||
nlh = mnl_nlmsg_put_header(nlg->buf);
|
||||
nlh->nlmsg_type = id;
|
||||
|
@ -675,31 +626,30 @@ static struct nlmsghdr* __mnlg_msg_prepare(
|
|||
return nlh;
|
||||
}
|
||||
|
||||
static struct nlmsghdr*
|
||||
mnlg_msg_prepare(struct mnlg_socket* nlg, uint8_t cmd, uint16_t flags)
|
||||
static struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
||||
uint16_t flags)
|
||||
{
|
||||
return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
|
||||
}
|
||||
|
||||
static int mnlg_socket_send(struct mnlg_socket* nlg, const struct nlmsghdr* nlh)
|
||||
static int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
|
||||
{
|
||||
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
|
||||
}
|
||||
|
||||
static int mnlg_cb_noop(const struct nlmsghdr* nlh, void* data)
|
||||
static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
(void)nlh;
|
||||
(void)data;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int mnlg_cb_error(const struct nlmsghdr* nlh, void* data)
|
||||
static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh);
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
(void)data;
|
||||
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
|
||||
{
|
||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
||||
errno = EBADMSG;
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
@ -712,12 +662,11 @@ static int mnlg_cb_error(const struct nlmsghdr* nlh, void* data)
|
|||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
static int mnlg_cb_stop(const struct nlmsghdr* nlh, void* data)
|
||||
static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
(void)data;
|
||||
if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int)))
|
||||
{
|
||||
int error = *(int*)mnl_nlmsg_get_payload(nlh);
|
||||
if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) {
|
||||
int error = *(int *)mnl_nlmsg_get_payload(nlh);
|
||||
/* Netlink subsystems returns the errno value with different signess */
|
||||
if (error < 0)
|
||||
errno = -error;
|
||||
|
@ -736,47 +685,41 @@ static const mnl_cb_t mnlg_cb_array[] = {
|
|||
[NLMSG_OVERRUN] = mnlg_cb_noop,
|
||||
};
|
||||
|
||||
static int mnlg_socket_recv_run(struct mnlg_socket* nlg, mnl_cb_t data_cb, void* data)
|
||||
static int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
do
|
||||
{
|
||||
err = mnl_socket_recvfrom(nlg->nl, nlg->buf, mnl_ideal_socket_buffer_size());
|
||||
do {
|
||||
err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
|
||||
mnl_ideal_socket_buffer_size());
|
||||
if (err <= 0)
|
||||
break;
|
||||
err = mnl_cb_run2(
|
||||
nlg->buf,
|
||||
err,
|
||||
nlg->seq,
|
||||
nlg->portid,
|
||||
data_cb,
|
||||
data,
|
||||
mnlg_cb_array,
|
||||
MNL_ARRAY_SIZE(mnlg_cb_array));
|
||||
err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
|
||||
data_cb, data, mnlg_cb_array, MNL_ARRAY_SIZE(mnlg_cb_array));
|
||||
} while (err > 0);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int get_family_id_attr_cb(const struct nlattr* attr, void* data)
|
||||
static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
const struct nlattr** tb = data;
|
||||
const struct nlattr **tb = data;
|
||||
int type = mnl_attr_get_type(attr);
|
||||
|
||||
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
||||
return MNL_CB_ERROR;
|
||||
|
||||
if (type == CTRL_ATTR_FAMILY_ID && mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
||||
if (type == CTRL_ATTR_FAMILY_ID &&
|
||||
mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
||||
return MNL_CB_ERROR;
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int get_family_id_cb(const struct nlmsghdr* nlh, void* data)
|
||||
static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
uint16_t* p_id = data;
|
||||
struct nlattr* tb[CTRL_ATTR_MAX + 1] = {0};
|
||||
uint16_t *p_id = data;
|
||||
struct nlattr *tb[CTRL_ATTR_MAX + 1] = { 0 };
|
||||
|
||||
mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
|
||||
if (!tb[CTRL_ATTR_FAMILY_ID])
|
||||
|
@ -785,10 +728,10 @@ static int get_family_id_cb(const struct nlmsghdr* nlh, void* data)
|
|||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static struct mnlg_socket* mnlg_socket_open(const char* family_name, uint8_t version)
|
||||
static struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
|
||||
{
|
||||
struct mnlg_socket* nlg;
|
||||
struct nlmsghdr* nlh;
|
||||
struct mnlg_socket *nlg;
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
|
||||
nlg = malloc(sizeof(*nlg));
|
||||
|
@ -802,33 +745,29 @@ static struct mnlg_socket* mnlg_socket_open(const char* family_name, uint8_t ver
|
|||
goto err_buf_alloc;
|
||||
|
||||
nlg->nl = mnl_socket_open(NETLINK_GENERIC);
|
||||
if (!nlg->nl)
|
||||
{
|
||||
if (!nlg->nl) {
|
||||
err = -errno;
|
||||
goto err_mnl_socket_open;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
{
|
||||
if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
err = -errno;
|
||||
goto err_mnl_socket_bind;
|
||||
}
|
||||
|
||||
nlg->portid = mnl_socket_get_portid(nlg->nl);
|
||||
|
||||
nlh = __mnlg_msg_prepare(
|
||||
nlg, CTRL_CMD_GETFAMILY, NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
|
||||
nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
|
||||
NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
|
||||
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
|
||||
|
||||
if (mnlg_socket_send(nlg, nlh) < 0)
|
||||
{
|
||||
if (mnlg_socket_send(nlg, nlh) < 0) {
|
||||
err = -errno;
|
||||
goto err_mnlg_socket_send;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0)
|
||||
{
|
||||
if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0) {
|
||||
errno = errno == ENOENT ? EPROTONOSUPPORT : errno;
|
||||
err = errno ? -errno : -ENOSYS;
|
||||
goto err_mnlg_socket_recv_run;
|
||||
|
@ -850,7 +789,7 @@ err_buf_alloc:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void mnlg_socket_close(struct mnlg_socket* nlg)
|
||||
static void mnlg_socket_close(struct mnlg_socket *nlg)
|
||||
{
|
||||
mnl_socket_close(nlg->nl);
|
||||
free(nlg->buf);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
@ -27,12 +28,10 @@
|
|||
#define a_ipv4 a_addr.addr_ipv4
|
||||
#define a_ipv6 a_addr.addr_ipv6
|
||||
|
||||
struct wg_aip_io
|
||||
{
|
||||
struct wg_aip_io {
|
||||
sa_family_t a_af;
|
||||
int a_cidr;
|
||||
union wg_aip_addr
|
||||
{
|
||||
union wg_aip_addr {
|
||||
struct in_addr addr_ipv4;
|
||||
struct in6_addr addr_ipv6;
|
||||
} a_addr;
|
||||
|
@ -50,15 +49,13 @@ struct wg_aip_io
|
|||
#define p_sin p_endpoint.sa_sin
|
||||
#define p_sin6 p_endpoint.sa_sin6
|
||||
|
||||
struct wg_peer_io
|
||||
{
|
||||
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
|
||||
{
|
||||
union wg_peer_endpoint {
|
||||
struct sockaddr sa_sa;
|
||||
struct sockaddr_in sa_sin;
|
||||
struct sockaddr_in6 sa_sin6;
|
||||
|
@ -94,8 +91,7 @@ struct wg_peer_io
|
|||
#define WG_INTERFACE_DEVICE_HAS_J3 (1 << 21)
|
||||
#define WG_INTERFACE_DEVICE_HAS_ITIME (1 << 22)
|
||||
|
||||
struct wg_interface_io
|
||||
{
|
||||
struct wg_interface_io {
|
||||
uint16_t i_flags;
|
||||
in_port_t i_port;
|
||||
int i_rtable;
|
||||
|
@ -125,11 +121,10 @@ struct wg_interface_io
|
|||
uint32_t i_itime;
|
||||
};
|
||||
|
||||
struct wg_data_io
|
||||
{
|
||||
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_interface_io *wgd_interface;
|
||||
};
|
||||
|
||||
#endif /* __IF_WG_H__ */
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
#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
|
||||
|
||||
|
@ -94,6 +94,7 @@ typedef struct _WG_IOCTL_INTERFACE
|
|||
ULONG ResponsePacketMagicHeader;
|
||||
ULONG UnderloadPacketMagicHeader;
|
||||
ULONG TransportPacketMagicHeader;
|
||||
|
||||
UCHAR* I1;
|
||||
UCHAR* I2;
|
||||
UCHAR* I3;
|
||||
|
@ -105,14 +106,13 @@ typedef struct _WG_IOCTL_INTERFACE
|
|||
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