mirror of
https://github.com/amnezia-vpn/amneziawg-tools.git
synced 2025-08-02 09:32:51 +02:00
feat: special handshake continue
This commit is contained in:
parent
3be9c02b19
commit
09e36b2416
14 changed files with 1552 additions and 1120 deletions
|
@ -72,7 +72,8 @@ enum wgdevice_attribute {
|
||||||
enum wgpeer_flag {
|
enum wgpeer_flag {
|
||||||
WGPEER_F_REMOVE_ME = 1U << 0,
|
WGPEER_F_REMOVE_ME = 1U << 0,
|
||||||
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
|
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
|
||||||
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3
|
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
|
||||||
|
WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4
|
||||||
};
|
};
|
||||||
enum wgpeer_attribute {
|
enum wgpeer_attribute {
|
||||||
WGPEER_A_UNSPEC,
|
WGPEER_A_UNSPEC,
|
||||||
|
@ -87,6 +88,7 @@ enum wgpeer_attribute {
|
||||||
WGPEER_A_ALLOWEDIPS,
|
WGPEER_A_ALLOWEDIPS,
|
||||||
WGPEER_A_PROTOCOL_VERSION,
|
WGPEER_A_PROTOCOL_VERSION,
|
||||||
WGPEER_A_ADVANCED_SECURITY,
|
WGPEER_A_ADVANCED_SECURITY,
|
||||||
|
WGPEER_A_SPECIAL_HANDSHAKE,
|
||||||
__WGPEER_A_LAST
|
__WGPEER_A_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ INTERFACE_NAME=$2
|
||||||
PUBLIC_KEY=$3
|
PUBLIC_KEY=$3
|
||||||
ENDPOINT=$4
|
ENDPOINT=$4
|
||||||
ADVANCED_SECURITY=$5
|
ADVANCED_SECURITY=$5
|
||||||
|
SPECIAL_HANDSHAKE=$6
|
||||||
|
|
||||||
ACCOUNT_STR=`grep "${PUBLIC_KEY}" "${ACCOUNTS_FILE}"`
|
ACCOUNT_STR=`grep "${PUBLIC_KEY}" "${ACCOUNTS_FILE}"`
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ PSK=$(echo ${ACCOUNT[2]}|tr -d '"')
|
||||||
PSK_FILE=$(tempfile)
|
PSK_FILE=$(tempfile)
|
||||||
echo "${PSK}" > "${PSK_FILE}"
|
echo "${PSK}" > "${PSK_FILE}"
|
||||||
|
|
||||||
awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}"
|
awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}" special-handshake "${SPECIAL_HANDSHAKE}"
|
||||||
EXIT_CODE=$?
|
EXIT_CODE=$?
|
||||||
|
|
||||||
rm -f "{$PSK_FILE}"
|
rm -f "{$PSK_FILE}"
|
||||||
|
|
|
@ -116,18 +116,19 @@ static int get_endpoint(struct nlattr *peer[], char **endpoint_ip)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security)
|
static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security, bool special_handshake)
|
||||||
{
|
{
|
||||||
char** new_argv = malloc((cb_argc + 2) * sizeof *new_argv);
|
char** new_argv = malloc((cb_argc + 2) * sizeof *new_argv);
|
||||||
|
|
||||||
new_argv[0] = cb_argv[1];
|
new_argv[0] = cb_argv[1];
|
||||||
for (int i = 2; i < cb_argc - 3; i++) {
|
for (int i = 2; i < cb_argc - 4; i++) {
|
||||||
new_argv[i - 1] = cb_argv[i];
|
new_argv[i - 1] = cb_argv[i];
|
||||||
}
|
}
|
||||||
new_argv[cb_argc - 4] = ifname;
|
new_argv[cb_argc - 5] = ifname;
|
||||||
new_argv[cb_argc - 3] = pubkey;
|
new_argv[cb_argc - 4] = pubkey;
|
||||||
new_argv[cb_argc - 2] = endpoint_ip;
|
new_argv[cb_argc - 3] = endpoint_ip;
|
||||||
new_argv[cb_argc - 1] = (advanced_security ? "on\0" : "off\0");
|
new_argv[cb_argc - 2] = (advanced_security ? "on\0" : "off\0");
|
||||||
|
new_argv[cb_argc - 1] = (special_handshake ? "on\0" : "off\0");
|
||||||
new_argv[cb_argc] = NULL;
|
new_argv[cb_argc] = NULL;
|
||||||
|
|
||||||
int child_pid = fork(), ret;
|
int child_pid = fork(), ret;
|
||||||
|
@ -156,6 +157,7 @@ static int netlink_callback(struct nl_msg *msg, void *arg)
|
||||||
|
|
||||||
char *ifname, *pubkey, *endpoint_ip;
|
char *ifname, *pubkey, *endpoint_ip;
|
||||||
bool advanced_security = false;
|
bool advanced_security = false;
|
||||||
|
bool special_handshake = false;
|
||||||
int cb_ret;
|
int cb_ret;
|
||||||
|
|
||||||
switch (gnlh->cmd) {
|
switch (gnlh->cmd) {
|
||||||
|
@ -179,7 +181,10 @@ static int netlink_callback(struct nl_msg *msg, void *arg)
|
||||||
if (nla_get_flag(peer[WGPEER_A_ADVANCED_SECURITY])) {
|
if (nla_get_flag(peer[WGPEER_A_ADVANCED_SECURITY])) {
|
||||||
advanced_security = true;
|
advanced_security = true;
|
||||||
}
|
}
|
||||||
if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security)) {
|
if (nla_get_flag(peer[WGPEER_A_SPECIAL_HANDSHAKE])) {
|
||||||
|
special_handshake = true;
|
||||||
|
}
|
||||||
|
if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security, special_handshake)) {
|
||||||
prerr("failed to execute callback script: %d!\n", cb_ret);
|
prerr("failed to execute callback script: %d!\n", cb_ret);
|
||||||
return NL_SKIP;
|
return NL_SKIP;
|
||||||
}
|
}
|
||||||
|
|
12
src/config.c
12
src/config.c
|
@ -606,7 +606,7 @@ static bool process_line(struct config_ctx *ctx, const char *line)
|
||||||
ret = parse_string(&ctx->device->j3, "J3", value);
|
ret = parse_string(&ctx->device->j3, "J3", value);
|
||||||
if (ret)
|
if (ret)
|
||||||
ctx->device->flags |= WGDEVICE_HAS_J3;
|
ctx->device->flags |= WGDEVICE_HAS_J3;
|
||||||
} else if (key_match("ITIME")) {
|
} else if (key_match("Itime")) {
|
||||||
ret = parse_uint32(&ctx->device->itime, "Itime", value);
|
ret = parse_uint32(&ctx->device->itime, "Itime", value);
|
||||||
if (ret)
|
if (ret)
|
||||||
ctx->device->flags |= WGDEVICE_HAS_ITIME;
|
ctx->device->flags |= WGDEVICE_HAS_ITIME;
|
||||||
|
@ -631,6 +631,10 @@ static bool process_line(struct config_ctx *ctx, const char *line)
|
||||||
ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value);
|
ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value);
|
||||||
if (ret)
|
if (ret)
|
||||||
ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
||||||
|
} else if (key_match("SpecialHandshake")) {
|
||||||
|
ret = parse_bool(&ctx->last_peer->special_handshake, "SpecialHandshake", value);
|
||||||
|
if (ret)
|
||||||
|
ctx->last_peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
|
||||||
} else
|
} else
|
||||||
goto error;
|
goto error;
|
||||||
} else
|
} else
|
||||||
|
@ -934,6 +938,12 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
|
||||||
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
||||||
argv += 2;
|
argv += 2;
|
||||||
argc -= 2;
|
argc -= 2;
|
||||||
|
} else if (!strcmp(argv[0], "special-handshake") && argc >= 2 && peer) {
|
||||||
|
if (!parse_bool(&peer->special_handshake, "SpecialHandshake", argv[1]))
|
||||||
|
goto error;
|
||||||
|
peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
|
||||||
|
argv += 2;
|
||||||
|
argc -= 2;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -53,7 +53,8 @@ enum
|
||||||
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
|
WGPEER_HAS_PUBLIC_KEY = 1U << 2,
|
||||||
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
|
WGPEER_HAS_PRESHARED_KEY = 1U << 3,
|
||||||
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4,
|
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4,
|
||||||
WGPEER_HAS_ADVANCED_SECURITY = 1U << 5
|
WGPEER_HAS_ADVANCED_SECURITY = 1U << 5,
|
||||||
|
WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wgpeer
|
struct wgpeer
|
||||||
|
@ -75,6 +76,7 @@ struct wgpeer
|
||||||
uint16_t persistent_keepalive_interval;
|
uint16_t persistent_keepalive_interval;
|
||||||
|
|
||||||
bool advanced_security;
|
bool advanced_security;
|
||||||
|
bool special_handshake;
|
||||||
|
|
||||||
struct wgallowedip *first_allowedip, *last_allowedip;
|
struct wgallowedip *first_allowedip, *last_allowedip;
|
||||||
struct wgpeer* next_peer;
|
struct wgpeer* next_peer;
|
||||||
|
|
|
@ -251,7 +251,7 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
||||||
if (nvlist_exists_binary(nvl_device, "itime"))
|
if (nvlist_exists_binary(nvl_device, "itime"))
|
||||||
{
|
{
|
||||||
number = nvlist_get_number(nvl_device, "itime");
|
number = nvlist_get_number(nvl_device, "itime");
|
||||||
if (number <= INT32_MAX)
|
if (number <= UINT32_MAX)
|
||||||
{
|
{
|
||||||
dev->itime = number;
|
dev->itime = number;
|
||||||
dev->flags |= WGDEVICE_HAS_ITIME;
|
dev->flags |= WGDEVICE_HAS_ITIME;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "containers.h"
|
#include "containers.h"
|
||||||
#include "encoding.h"
|
#include "encoding.h"
|
||||||
#include "netlink.h"
|
#include "netlink.h"
|
||||||
|
#include "uapi/linux/linux/wireguard.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <linux/genetlink.h>
|
#include <linux/genetlink.h>
|
||||||
#include <linux/if_link.h>
|
#include <linux/if_link.h>
|
||||||
|
@ -191,6 +192,25 @@ again:
|
||||||
mnl_attr_put_u32(nlh, WGDEVICE_A_H3, dev->underload_packet_magic_header);
|
mnl_attr_put_u32(nlh, WGDEVICE_A_H3, dev->underload_packet_magic_header);
|
||||||
if (dev->flags & WGDEVICE_HAS_H4)
|
if (dev->flags & WGDEVICE_HAS_H4)
|
||||||
mnl_attr_put_u32(nlh, WGDEVICE_A_H4, dev->transport_packet_magic_header);
|
mnl_attr_put_u32(nlh, WGDEVICE_A_H4, dev->transport_packet_magic_header);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_I1)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_I1, dev->i1);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_I2)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_I2, dev->i2);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_I3)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_I3, dev->i3);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_I4)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_I4, dev->i4);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_I5)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_I5, dev->i5);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_J1)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_J1, dev->j1);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_J2)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_J2, dev->j2);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_J3)
|
||||||
|
mnl_attr_put_strz(nlh, WGDEVICE_A_J3, dev->j3);
|
||||||
|
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||||
|
mnl_attr_put_u32(nlh, WGDEVICE_A_ITIME, dev->itime);
|
||||||
|
|
||||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||||
mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
|
mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark);
|
||||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||||
|
@ -269,6 +289,13 @@ again:
|
||||||
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
|
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
|
||||||
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
|
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
|
||||||
}
|
}
|
||||||
|
if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)
|
||||||
|
{
|
||||||
|
if (peer->special_handshake)
|
||||||
|
mnl_attr_put_check(
|
||||||
|
nlh, SOCKET_BUFFER_SIZE, WGPEER_A_SPECIAL_HANDSHAKE, 0, NULL);
|
||||||
|
flags |= WGPEER_F_HAS_SPECIAL_HANDSHAKE;
|
||||||
|
}
|
||||||
if (flags)
|
if (flags)
|
||||||
{
|
{
|
||||||
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
|
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
|
||||||
|
@ -489,6 +516,13 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
||||||
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
|
||||||
peer->advanced_security = false;
|
peer->advanced_security = false;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
flags & WGPEER_F_HAS_SPECIAL_HANDSHAKE &&
|
||||||
|
!(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE))
|
||||||
|
{
|
||||||
|
peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
|
||||||
|
peer->special_handshake = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WGPEER_A_ADVANCED_SECURITY:
|
case WGPEER_A_ADVANCED_SECURITY:
|
||||||
|
@ -502,6 +536,17 @@ static int parse_peer(const struct nlattr* attr, void* data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WGPEER_A_SPECIAL_HANDSHAKE:
|
||||||
|
if (!mnl_attr_validate(attr, MNL_TYPE_FLAG))
|
||||||
|
{
|
||||||
|
peer->special_handshake = true;
|
||||||
|
|
||||||
|
if (!(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE))
|
||||||
|
{
|
||||||
|
peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WGPEER_A_ALLOWEDIPS:
|
case WGPEER_A_ALLOWEDIPS:
|
||||||
return mnl_attr_parse_nested(attr, parse_allowedips, peer);
|
return mnl_attr_parse_nested(attr, parse_allowedips, peer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,8 @@ static int userspace_set_device(struct wgdevice* dev)
|
||||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||||
fprintf(f, "itime=%u\n", dev->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);
|
key_to_hex(hex, peer->public_key);
|
||||||
|
@ -98,6 +100,11 @@ static int userspace_set_device(struct wgdevice* dev)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)
|
||||||
|
{
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (peer->flags & WGPEER_REMOVE_ME)
|
if (peer->flags & WGPEER_REMOVE_ME)
|
||||||
{
|
{
|
||||||
fprintf(f, "remove=true\n");
|
fprintf(f, "remove=true\n");
|
||||||
|
|
|
@ -4,15 +4,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "containers.h"
|
#include "containers.h"
|
||||||
#include <windows.h>
|
|
||||||
#include <setupapi.h>
|
|
||||||
#include <cfgmgr32.h>
|
#include <cfgmgr32.h>
|
||||||
#include <iphlpapi.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <devguid.h>
|
|
||||||
#include <ddk/ndisguid.h>
|
#include <ddk/ndisguid.h>
|
||||||
#include <wireguard.h>
|
#include <devguid.h>
|
||||||
#include <hashtable.h>
|
#include <hashtable.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
#include <setupapi.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wireguard.h>
|
||||||
|
|
||||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||||
|
|
||||||
|
@ -21,34 +21,50 @@ static struct hashtable cached_kernel_interfaces;
|
||||||
static const DEVPROPKEY devpkey_name = DEVPKEY_WG_NAME;
|
static const DEVPROPKEY devpkey_name = DEVPKEY_WG_NAME;
|
||||||
extern bool is_win7;
|
extern bool is_win7;
|
||||||
|
|
||||||
static int kernel_get_wireguard_interfaces(struct string_list *list)
|
static int kernel_get_wireguard_interfaces(struct string_list* list)
|
||||||
{
|
{
|
||||||
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
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;
|
bool will_have_cached_kernel_interfaces = true;
|
||||||
|
|
||||||
if (dev_info == INVALID_HANDLE_VALUE) {
|
if (dev_info == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DWORD i = 0;; ++i) {
|
for (DWORD i = 0;; ++i)
|
||||||
|
{
|
||||||
DWORD buf_len;
|
DWORD buf_len;
|
||||||
WCHAR adapter_name[MAX_ADAPTER_NAME];
|
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;
|
DEVPROPTYPE prop_type;
|
||||||
ULONG status, problem_code;
|
ULONG status, problem_code;
|
||||||
char *interface_name;
|
char* interface_name;
|
||||||
struct hashtable_entry *entry;
|
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)
|
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||||
break;
|
break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
|
if (!SetupDiGetDevicePropertyW(
|
||||||
&prop_type, (PBYTE)adapter_name,
|
dev_info,
|
||||||
sizeof(adapter_name), NULL, 0) ||
|
&dev_info_data,
|
||||||
|
&devpkey_name,
|
||||||
|
&prop_type,
|
||||||
|
(PBYTE)adapter_name,
|
||||||
|
sizeof(adapter_name),
|
||||||
|
NULL,
|
||||||
|
0) ||
|
||||||
prop_type != DEVPROP_TYPE_STRING)
|
prop_type != DEVPROP_TYPE_STRING)
|
||||||
continue;
|
continue;
|
||||||
adapter_name[_countof(adapter_name) - 1] = L'0';
|
adapter_name[_countof(adapter_name) - 1] = L'0';
|
||||||
|
@ -60,13 +76,16 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||||
interface_name = malloc(buf_len);
|
interface_name = malloc(buf_len);
|
||||||
if (!interface_name)
|
if (!interface_name)
|
||||||
continue;
|
continue;
|
||||||
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
buf_len = WideCharToMultiByte(
|
||||||
if (!buf_len) {
|
CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||||
|
if (!buf_len)
|
||||||
|
{
|
||||||
free(interface_name);
|
free(interface_name);
|
||||||
continue;
|
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))
|
(status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED))
|
||||||
string_list_add(list, interface_name);
|
string_list_add(list, interface_name);
|
||||||
|
|
||||||
|
@ -75,12 +94,15 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||||
if (!entry)
|
if (!entry)
|
||||||
continue;
|
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;
|
continue;
|
||||||
entry->value = calloc(sizeof(WCHAR), buf_len);
|
entry->value = calloc(sizeof(WCHAR), buf_len);
|
||||||
if (!entry->value)
|
if (!entry->value)
|
||||||
continue;
|
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);
|
free(entry->value);
|
||||||
entry->value = NULL;
|
entry->value = NULL;
|
||||||
continue;
|
continue;
|
||||||
|
@ -93,64 +115,94 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE kernel_interface_handle(const char *iface)
|
static HANDLE kernel_interface_handle(const char* iface)
|
||||||
{
|
{
|
||||||
HDEVINFO dev_info;
|
HDEVINFO dev_info;
|
||||||
WCHAR *interfaces = NULL;
|
WCHAR* interfaces = NULL;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
if (have_cached_kernel_interfaces) {
|
if (have_cached_kernel_interfaces)
|
||||||
struct hashtable_entry *entry = hashtable_find_entry(&cached_kernel_interfaces, iface);
|
{
|
||||||
if (entry) {
|
struct hashtable_entry* entry =
|
||||||
|
hashtable_find_entry(&cached_kernel_interfaces, iface);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
DWORD buf_len;
|
DWORD buf_len;
|
||||||
if (CM_Get_Device_Interface_List_SizeW(
|
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)
|
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
|
||||||
goto err_hash;
|
goto err_hash;
|
||||||
interfaces = calloc(buf_len, sizeof(*interfaces));
|
interfaces = calloc(buf_len, sizeof(*interfaces));
|
||||||
if (!interfaces)
|
if (!interfaces)
|
||||||
goto err_hash;
|
goto err_hash;
|
||||||
if (CM_Get_Device_Interface_ListW(
|
if (CM_Get_Device_Interface_ListW(
|
||||||
(GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value, interfaces, buf_len,
|
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
|
(DEVINSTID_W)entry->value,
|
||||||
|
interfaces,
|
||||||
|
buf_len,
|
||||||
|
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
|
||||||
|
!interfaces[0])
|
||||||
|
{
|
||||||
free(interfaces);
|
free(interfaces);
|
||||||
interfaces = NULL;
|
interfaces = NULL;
|
||||||
goto err_hash;
|
goto err_hash;
|
||||||
}
|
}
|
||||||
handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
|
handle = CreateFileW(
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
interfaces,
|
||||||
OPEN_EXISTING, 0, NULL);
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
free(interfaces);
|
free(interfaces);
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
goto err_hash;
|
goto err_hash;
|
||||||
return handle;
|
return handle;
|
||||||
err_hash:
|
err_hash:
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return NULL;
|
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)
|
if (dev_info == INVALID_HANDLE_VALUE)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (DWORD i = 0; !interfaces; ++i) {
|
for (DWORD i = 0; !interfaces; ++i)
|
||||||
|
{
|
||||||
bool found;
|
bool found;
|
||||||
DWORD buf_len;
|
DWORD buf_len;
|
||||||
WCHAR *buf, adapter_name[MAX_ADAPTER_NAME];
|
WCHAR * buf, 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;
|
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)
|
if (GetLastError() == ERROR_NO_MORE_ITEMS)
|
||||||
break;
|
break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name,
|
if (!SetupDiGetDevicePropertyW(
|
||||||
&prop_type, (PBYTE)adapter_name,
|
dev_info,
|
||||||
sizeof(adapter_name), NULL, 0) ||
|
&dev_info_data,
|
||||||
|
&devpkey_name,
|
||||||
|
&prop_type,
|
||||||
|
(PBYTE)adapter_name,
|
||||||
|
sizeof(adapter_name),
|
||||||
|
NULL,
|
||||||
|
0) ||
|
||||||
prop_type != DEVPROP_TYPE_STRING)
|
prop_type != DEVPROP_TYPE_STRING)
|
||||||
continue;
|
continue;
|
||||||
adapter_name[_countof(adapter_name) - 1] = L'0';
|
adapter_name[_countof(adapter_name) - 1] = L'0';
|
||||||
|
@ -162,8 +214,10 @@ err_hash:
|
||||||
interface_name = malloc(buf_len);
|
interface_name = malloc(buf_len);
|
||||||
if (!interface_name)
|
if (!interface_name)
|
||||||
continue;
|
continue;
|
||||||
buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
buf_len = WideCharToMultiByte(
|
||||||
if (!buf_len) {
|
CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL);
|
||||||
|
if (!buf_len)
|
||||||
|
{
|
||||||
free(interface_name);
|
free(interface_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -172,57 +226,73 @@ err_hash:
|
||||||
if (!found)
|
if (!found)
|
||||||
continue;
|
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;
|
continue;
|
||||||
buf = calloc(sizeof(*buf), buf_len);
|
buf = calloc(sizeof(*buf), buf_len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
continue;
|
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;
|
goto cleanup_instance_id;
|
||||||
if (CM_Get_Device_Interface_List_SizeW(
|
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)
|
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS)
|
||||||
goto cleanup_instance_id;
|
goto cleanup_instance_id;
|
||||||
interfaces = calloc(buf_len, sizeof(*interfaces));
|
interfaces = calloc(buf_len, sizeof(*interfaces));
|
||||||
if (!interfaces)
|
if (!interfaces)
|
||||||
goto cleanup_instance_id;
|
goto cleanup_instance_id;
|
||||||
if (CM_Get_Device_Interface_ListW(
|
if (CM_Get_Device_Interface_ListW(
|
||||||
(GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf, interfaces, buf_len,
|
(GUID*)&GUID_DEVINTERFACE_NET,
|
||||||
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) {
|
(DEVINSTID_W)buf,
|
||||||
|
interfaces,
|
||||||
|
buf_len,
|
||||||
|
CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS ||
|
||||||
|
!interfaces[0])
|
||||||
|
{
|
||||||
free(interfaces);
|
free(interfaces);
|
||||||
interfaces = NULL;
|
interfaces = NULL;
|
||||||
goto cleanup_instance_id;
|
goto cleanup_instance_id;
|
||||||
}
|
}
|
||||||
cleanup_instance_id:
|
cleanup_instance_id:
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
SetupDiDestroyDeviceInfoList(dev_info);
|
SetupDiDestroyDeviceInfoList(dev_info);
|
||||||
if (!interfaces) {
|
if (!interfaces)
|
||||||
|
{
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE,
|
handle = CreateFileW(
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
interfaces,
|
||||||
OPEN_EXISTING, 0, NULL);
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
free(interfaces);
|
free(interfaces);
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return handle;
|
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_INTERFACE* wg_iface;
|
||||||
WG_IOCTL_PEER *wg_peer;
|
WG_IOCTL_PEER* wg_peer;
|
||||||
WG_IOCTL_ALLOWED_IP *wg_aip;
|
WG_IOCTL_ALLOWED_IP* wg_aip;
|
||||||
void *buf = NULL;
|
void* buf = NULL;
|
||||||
DWORD buf_len = 0;
|
DWORD buf_len = 0;
|
||||||
HANDLE handle = kernel_interface_handle(iface);
|
HANDLE handle = kernel_interface_handle(iface);
|
||||||
struct wgdevice *dev;
|
struct wgdevice* dev;
|
||||||
struct wgpeer *peer;
|
struct wgpeer* peer;
|
||||||
struct wgallowedip *aip;
|
struct wgallowedip* aip;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
*device = NULL;
|
*device = NULL;
|
||||||
|
@ -230,9 +300,11 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return -errno;
|
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);
|
free(buf);
|
||||||
if (GetLastError() != ERROR_MORE_DATA) {
|
if (GetLastError() != ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
@ -241,67 +313,141 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
wg_iface = (WG_IOCTL_INTERFACE *)buf;
|
wg_iface = (WG_IOCTL_INTERFACE*)buf;
|
||||||
dev = calloc(1, sizeof(*dev));
|
dev = calloc(1, sizeof(*dev));
|
||||||
if (!dev)
|
if (!dev)
|
||||||
goto out;
|
goto out;
|
||||||
strncpy(dev->name, iface, sizeof(dev->name));
|
strncpy(dev->name, iface, sizeof(dev->name));
|
||||||
dev->name[sizeof(dev->name) - 1] = '\0';
|
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->listen_port = wg_iface->ListenPort;
|
||||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
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));
|
memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key));
|
||||||
dev->flags |= WGDEVICE_HAS_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));
|
memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key));
|
||||||
dev->flags |= WGDEVICE_HAS_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->junk_packet_count = wg_iface->JunkPacketCount;
|
||||||
dev->flags |= WGDEVICE_HAS_JC;
|
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->junk_packet_min_size = wg_iface->JunkPacketMinSize;
|
||||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
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->junk_packet_max_size = wg_iface->JunkPacketMaxSize;
|
||||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
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->init_packet_junk_size = wg_iface->InitPacketJunkSize;
|
||||||
dev->flags |= WGDEVICE_HAS_S1;
|
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->response_packet_junk_size = wg_iface->ResponsePacketJunkSize;
|
||||||
dev->flags |= WGDEVICE_HAS_S2;
|
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->init_packet_magic_header = wg_iface->InitPacketMagicHeader;
|
||||||
dev->flags |= WGDEVICE_HAS_H1;
|
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->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader;
|
||||||
dev->flags |= WGDEVICE_HAS_H2;
|
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->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader;
|
||||||
dev->flags |= WGDEVICE_HAS_H3;
|
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->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader;
|
||||||
dev->flags |= WGDEVICE_HAS_H4;
|
dev->flags |= WGDEVICE_HAS_H4;
|
||||||
}
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_I1)
|
||||||
|
{
|
||||||
|
const size_t i1_size = strlen((char*)wg_iface->I1) + 1;
|
||||||
|
dev->i1 = (char*)malloc(i1_size);
|
||||||
|
memcpy(dev->i1, wg_iface->I1, i1_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_I1;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_I2)
|
||||||
|
{
|
||||||
|
const size_t i2_size = strlen((char*)wg_iface->I2) + 1;
|
||||||
|
dev->i2 = (char*)malloc(i2_size);
|
||||||
|
memcpy(dev->i2, wg_iface->I2, i2_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_I2;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_I3)
|
||||||
|
{
|
||||||
|
const size_t i3_size = strlen((char*)wg_iface->I3) + 1;
|
||||||
|
dev->i3 = (char*)malloc(i3_size);
|
||||||
|
memcpy(dev->i3, wg_iface->I3, i3_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_I3;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_I4)
|
||||||
|
{
|
||||||
|
const size_t i4_size = strlen((char*)wg_iface->I4) + 1;
|
||||||
|
dev->i4 = (char*)malloc(i4_size);
|
||||||
|
memcpy(dev->i4, wg_iface->I4, i4_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_I4;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_I5)
|
||||||
|
{
|
||||||
|
const size_t i5_size = strlen((char*)wg_iface->I5) + 1;
|
||||||
|
dev->i5 = (char*)malloc(i5_size);
|
||||||
|
memcpy(dev->i5, wg_iface->I5, i5_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_I5;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_J1)
|
||||||
|
{
|
||||||
|
const size_t j1_size = strlen((char*)wg_iface->J1) + 1;
|
||||||
|
dev->j1 = (char*)malloc(j1_size);
|
||||||
|
memcpy(dev->j1, wg_iface->J1, j1_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_J1;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_J2)
|
||||||
|
{
|
||||||
|
const size_t j2_size = strlen((char*)wg_iface->J2) + 1;
|
||||||
|
dev->j2 = (char*)malloc(j2_size);
|
||||||
|
memcpy(dev->j2, wg_iface->J2, j2_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_J2;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_J3)
|
||||||
|
{
|
||||||
|
const size_t j3_size = strlen((char*)wg_iface->J3) + 1;
|
||||||
|
dev->j3 = (char*)malloc(j3_size);
|
||||||
|
memcpy(dev->j3, wg_iface->J3, j3_size);
|
||||||
|
dev->flags |= WGDEVICE_HAS_J3;
|
||||||
|
}
|
||||||
|
if (wg_iface->Flags & WG_IOCTL_INTERFACE_ITIME)
|
||||||
|
{
|
||||||
|
dev->itime = wg_iface->Itime;
|
||||||
|
dev->flags |= WGDEVICE_HAS_ITIME;
|
||||||
|
}
|
||||||
|
|
||||||
wg_peer = buf + sizeof(WG_IOCTL_INTERFACE);
|
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));
|
peer = calloc(1, sizeof(*peer));
|
||||||
if (!peer)
|
if (!peer)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -312,23 +458,28 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||||
dev->last_peer->next_peer = peer;
|
dev->last_peer->next_peer = peer;
|
||||||
dev->last_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));
|
memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key));
|
||||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY) {
|
if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY)
|
||||||
memcpy(peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
|
{
|
||||||
|
memcpy(
|
||||||
|
peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key));
|
||||||
if (!key_is_zero(peer->preshared_key))
|
if (!key_is_zero(peer->preshared_key))
|
||||||
peer->flags |= WGPEER_HAS_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->persistent_keepalive_interval = wg_peer->PersistentKeepalive;
|
||||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
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)
|
if (wg_peer->Endpoint.si_family == AF_INET)
|
||||||
peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4;
|
peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4;
|
||||||
else if (wg_peer->Endpoint.si_family == AF_INET6)
|
else if (wg_peer->Endpoint.si_family == AF_INET6)
|
||||||
|
@ -338,13 +489,16 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||||
peer->rx_bytes = wg_peer->RxBytes;
|
peer->rx_bytes = wg_peer->RxBytes;
|
||||||
peer->tx_bytes = wg_peer->TxBytes;
|
peer->tx_bytes = wg_peer->TxBytes;
|
||||||
|
|
||||||
if (wg_peer->LastHandshake) {
|
if (wg_peer->LastHandshake)
|
||||||
peer->last_handshake_time.tv_sec = wg_peer->LastHandshake / 10000000 - 11644473600LL;
|
{
|
||||||
|
peer->last_handshake_time.tv_sec =
|
||||||
|
wg_peer->LastHandshake / 10000000 - 11644473600LL;
|
||||||
peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100;
|
peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
|
wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||||
for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j) {
|
for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j)
|
||||||
|
{
|
||||||
aip = calloc(1, sizeof(*aip));
|
aip = calloc(1, sizeof(*aip));
|
||||||
if (!aip)
|
if (!aip)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -356,16 +510,19 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||||
peer->last_allowedip = aip;
|
peer->last_allowedip = aip;
|
||||||
|
|
||||||
aip->family = wg_aip->AddressFamily;
|
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));
|
memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4));
|
||||||
aip->cidr = wg_aip->Cidr;
|
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));
|
memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6));
|
||||||
aip->cidr = wg_aip->Cidr;
|
aip->cidr = wg_aip->Cidr;
|
||||||
}
|
}
|
||||||
++wg_aip;
|
++wg_aip;
|
||||||
}
|
}
|
||||||
wg_peer = (WG_IOCTL_PEER *)wg_aip;
|
wg_peer = (WG_IOCTL_PEER*)wg_aip;
|
||||||
}
|
}
|
||||||
*device = dev;
|
*device = dev;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -376,29 +533,33 @@ out:
|
||||||
return ret;
|
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_INTERFACE* wg_iface = NULL;
|
||||||
WG_IOCTL_PEER *wg_peer;
|
WG_IOCTL_PEER* wg_peer;
|
||||||
WG_IOCTL_ALLOWED_IP *wg_aip;
|
WG_IOCTL_ALLOWED_IP* wg_aip;
|
||||||
DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
|
DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
|
||||||
HANDLE handle = kernel_interface_handle(dev->name);
|
HANDLE handle = kernel_interface_handle(dev->name);
|
||||||
struct wgpeer *peer;
|
struct wgpeer* peer;
|
||||||
struct wgallowedip *aip;
|
struct wgallowedip* aip;
|
||||||
size_t peer_count, aip_count;
|
size_t peer_count, aip_count;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
for_each_wgpeer(dev, peer) {
|
for_each_wgpeer(dev, peer)
|
||||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) {
|
{
|
||||||
|
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER))
|
||||||
|
{
|
||||||
errno = EOVERFLOW;
|
errno = EOVERFLOW;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_len += sizeof(WG_IOCTL_PEER);
|
buf_len += sizeof(WG_IOCTL_PEER);
|
||||||
for_each_wgallowedip(peer, aip) {
|
for_each_wgallowedip(peer, aip)
|
||||||
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) {
|
{
|
||||||
|
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP))
|
||||||
|
{
|
||||||
errno = EOVERFLOW;
|
errno = EOVERFLOW;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -409,12 +570,14 @@ static int kernel_set_device(struct wgdevice *dev)
|
||||||
if (!wg_iface)
|
if (!wg_iface)
|
||||||
goto out;
|
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));
|
memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY;
|
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->ListenPort = dev->listen_port;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT;
|
wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT;
|
||||||
}
|
}
|
||||||
|
@ -422,71 +585,150 @@ static int kernel_set_device(struct wgdevice *dev)
|
||||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_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->JunkPacketCount = dev->junk_packet_count;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JC;
|
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->JunkPacketMinSize = dev->junk_packet_min_size;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN;
|
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->JunkPacketMaxSize = dev->junk_packet_max_size;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX;
|
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->InitPacketJunkSize = dev->init_packet_junk_size;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_S1;
|
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->ResponsePacketJunkSize = dev->response_packet_junk_size;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_S2;
|
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->InitPacketMagicHeader = dev->init_packet_magic_header;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H1;
|
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->ResponsePacketMagicHeader = dev->response_packet_magic_header;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H2;
|
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->UnderloadPacketMagicHeader = dev->underload_packet_magic_header;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H3;
|
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->TransportPacketMagicHeader = dev->transport_packet_magic_header;
|
||||||
wg_iface->Flags |= WG_IOCTL_INTERFACE_H4;
|
wg_iface->Flags |= WG_IOCTL_INTERFACE_H4;
|
||||||
}
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_I1)
|
||||||
|
{
|
||||||
|
const size_t i1_size = strlen(dev->i1);
|
||||||
|
wg_iface->I1 = (UCHAR*)malloc(i1_size + 1);
|
||||||
|
memcpy(wg_iface->I1, dev->i1, i1_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_I1;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_I2)
|
||||||
|
{
|
||||||
|
const size_t i2_size = strlen(dev->i2);
|
||||||
|
wg_iface->I2 = (UCHAR*)malloc(i2_size + 1);
|
||||||
|
memcpy(wg_iface->I2, dev->i2, i2_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_I2;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_I3)
|
||||||
|
{
|
||||||
|
const size_t i3_size = strlen(dev->i3);
|
||||||
|
wg_iface->I3 = (UCHAR*)malloc(i3_size + 1);
|
||||||
|
memcpy(wg_iface->I3, dev->i3, i3_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_I3;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_I4)
|
||||||
|
{
|
||||||
|
const size_t i4_size = strlen(dev->i4);
|
||||||
|
wg_iface->I4 = (UCHAR*)malloc(i4_size + 1);
|
||||||
|
memcpy(wg_iface->I4, dev->i4, i4_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_I4;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_I5)
|
||||||
|
{
|
||||||
|
const size_t i5_size = strlen(dev->i5);
|
||||||
|
wg_iface->I5 = (UCHAR*)malloc(i5_size + 1);
|
||||||
|
memcpy(wg_iface->I5, dev->i5, i5_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_I5;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_J1)
|
||||||
|
{
|
||||||
|
const size_t j1_size = strlen(dev->j1);
|
||||||
|
wg_iface->J1 = (UCHAR*)malloc(j1_size + 1);
|
||||||
|
memcpy(wg_iface->J1, dev->j1, j1_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_J1;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_J2)
|
||||||
|
{
|
||||||
|
const size_t j2_size = strlen(dev->j2);
|
||||||
|
wg_iface->J2 = (UCHAR*)malloc(j2_size + 1);
|
||||||
|
memcpy(wg_iface->J2, dev->j2, j2_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_J2;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_J3)
|
||||||
|
{
|
||||||
|
const size_t j3_size = strlen(dev->j3);
|
||||||
|
wg_iface->J3 = (UCHAR*)malloc(j3_size + 1);
|
||||||
|
memcpy(wg_iface->J3, dev->j3, j3_size);
|
||||||
|
dev->flags |= WG_IOCTL_INTERFACE_J3;
|
||||||
|
}
|
||||||
|
if (dev->flags & WG_DEVICE_HAS_ITIME)
|
||||||
|
{
|
||||||
|
wg_iface->Itime = dev->Itime;
|
||||||
|
wg_iface->flags |= WG_IOCTL_INTERFACE_HAS_ITIME;
|
||||||
|
}
|
||||||
|
|
||||||
peer_count = 0;
|
peer_count = 0;
|
||||||
wg_peer = (void *)wg_iface + sizeof(WG_IOCTL_INTERFACE);
|
wg_peer = (void*)wg_iface + sizeof(WG_IOCTL_INTERFACE);
|
||||||
for_each_wgpeer(dev, peer) {
|
for_each_wgpeer(dev, peer)
|
||||||
|
{
|
||||||
wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY;
|
wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY;
|
||||||
memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey));
|
memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey));
|
||||||
|
|
||||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
|
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||||
memcpy(wg_peer->PresharedKey, peer->preshared_key, sizeof(wg_peer->PresharedKey));
|
{
|
||||||
|
memcpy(
|
||||||
|
wg_peer->PresharedKey,
|
||||||
|
peer->preshared_key,
|
||||||
|
sizeof(wg_peer->PresharedKey));
|
||||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY;
|
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->PersistentKeepalive = peer->persistent_keepalive_interval;
|
||||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE;
|
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->Endpoint.Ipv4 = peer->endpoint.addr4;
|
||||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
|
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->Endpoint.Ipv6 = peer->endpoint.addr6;
|
||||||
wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
|
wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT;
|
||||||
}
|
}
|
||||||
|
@ -498,8 +740,9 @@ static int kernel_set_device(struct wgdevice *dev)
|
||||||
wg_peer->Flags |= WG_IOCTL_PEER_REMOVE;
|
wg_peer->Flags |= WG_IOCTL_PEER_REMOVE;
|
||||||
|
|
||||||
aip_count = 0;
|
aip_count = 0;
|
||||||
wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER);
|
wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER);
|
||||||
for_each_wgallowedip(peer, aip) {
|
for_each_wgallowedip(peer, aip)
|
||||||
|
{
|
||||||
wg_aip->AddressFamily = aip->family;
|
wg_aip->AddressFamily = aip->family;
|
||||||
wg_aip->Cidr = aip->cidr;
|
wg_aip->Cidr = aip->cidr;
|
||||||
|
|
||||||
|
@ -514,11 +757,13 @@ static int kernel_set_device(struct wgdevice *dev)
|
||||||
}
|
}
|
||||||
wg_peer->AllowedIPsCount = aip_count;
|
wg_peer->AllowedIPsCount = aip_count;
|
||||||
++peer_count;
|
++peer_count;
|
||||||
wg_peer = (WG_IOCTL_PEER *)wg_aip;
|
wg_peer = (WG_IOCTL_PEER*)wg_aip;
|
||||||
}
|
}
|
||||||
wg_iface->PeersCount = peer_count;
|
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;
|
errno = EACCES;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
459
src/netlink.h
459
src/netlink.h
|
@ -6,26 +6,27 @@
|
||||||
|
|
||||||
/* This is a minimized version of libmnl meant to be #include'd */
|
/* This is a minimized version of libmnl meant to be #include'd */
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <linux/netlink.h>
|
|
||||||
#include <linux/genetlink.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>
|
||||||
|
|
||||||
#define MNL_SOCKET_AUTOPID 0
|
#define MNL_SOCKET_AUTOPID 0
|
||||||
#define MNL_ALIGNTO 4
|
#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_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr))
|
||||||
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
#define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr))
|
||||||
|
|
||||||
enum mnl_attr_data_type {
|
enum mnl_attr_data_type
|
||||||
|
{
|
||||||
MNL_TYPE_UNSPEC,
|
MNL_TYPE_UNSPEC,
|
||||||
MNL_TYPE_U8,
|
MNL_TYPE_U8,
|
||||||
MNL_TYPE_U16,
|
MNL_TYPE_U16,
|
||||||
|
@ -43,28 +44,30 @@ enum mnl_attr_data_type {
|
||||||
|
|
||||||
#define mnl_attr_for_each(attr, nlh, offset) \
|
#define mnl_attr_for_each(attr, nlh, offset) \
|
||||||
for ((attr) = mnl_nlmsg_get_payload_offset((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))
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
#define mnl_attr_for_each_nested(attr, nest) \
|
#define mnl_attr_for_each_nested(attr, nest) \
|
||||||
for ((attr) = mnl_attr_get_payload(nest); \
|
for ((attr) = mnl_attr_get_payload(nest); mnl_attr_ok( \
|
||||||
mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \
|
(attr), \
|
||||||
|
(char*)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - \
|
||||||
|
(char*)(attr)); \
|
||||||
(attr) = mnl_attr_next(attr))
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
#define mnl_attr_for_each_payload(payload, payload_size) \
|
#define mnl_attr_for_each_payload(payload, payload_size) \
|
||||||
for ((attr) = (payload); \
|
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))
|
(attr) = mnl_attr_next(attr))
|
||||||
|
|
||||||
#define MNL_CB_ERROR -1
|
#define MNL_CB_ERROR -1
|
||||||
#define MNL_CB_STOP 0
|
#define MNL_CB_STOP 0
|
||||||
#define MNL_CB_OK 1
|
#define MNL_CB_OK 1
|
||||||
|
|
||||||
typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, 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);
|
typedef int (*mnl_cb_t)(const struct nlmsghdr* nlh, void* data);
|
||||||
|
|
||||||
#ifndef MNL_ARRAY_SIZE
|
#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
|
#endif
|
||||||
|
|
||||||
static size_t mnl_ideal_socket_buffer_size(void)
|
static size_t mnl_ideal_socket_buffer_size(void)
|
||||||
|
@ -79,133 +82,137 @@ static size_t mnl_ideal_socket_buffer_size(void)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t mnl_nlmsg_size(size_t len)
|
static size_t mnl_nlmsg_size(size_t len) { return len + MNL_NLMSG_HDRLEN; }
|
||||||
{
|
|
||||||
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));
|
int len = MNL_ALIGN(sizeof(struct nlmsghdr));
|
||||||
struct nlmsghdr *nlh = buf;
|
struct nlmsghdr* nlh = buf;
|
||||||
|
|
||||||
memset(buf, 0, len);
|
memset(buf, 0, len);
|
||||||
nlh->nlmsg_len = len;
|
nlh->nlmsg_len = len;
|
||||||
return nlh;
|
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);
|
size_t len = MNL_ALIGN(size);
|
||||||
nlh->nlmsg_len += len;
|
nlh->nlmsg_len += len;
|
||||||
memset(ptr, 0, len);
|
memset(ptr, 0, len);
|
||||||
return ptr;
|
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) &&
|
return len >= (int)sizeof(struct nlmsghdr) &&
|
||||||
nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
nlh->nlmsg_len >= sizeof(struct nlmsghdr) && (int)nlh->nlmsg_len <= len;
|
||||||
(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);
|
*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;
|
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;
|
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;
|
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;
|
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) &&
|
return len >= (int)sizeof(struct nlattr) && attr->nla_len >= sizeof(struct nlattr) &&
|
||||||
attr->nla_len >= sizeof(struct nlattr) &&
|
|
||||||
(int)attr->nla_len <= len;
|
(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;
|
errno = EOPNOTSUPP;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __mnl_attr_validate(const struct nlattr *attr,
|
static int __mnl_attr_validate(
|
||||||
enum mnl_attr_data_type type, size_t exp_len)
|
const struct nlattr* attr,
|
||||||
|
enum mnl_attr_data_type type,
|
||||||
|
size_t exp_len)
|
||||||
{
|
{
|
||||||
uint16_t attr_len = mnl_attr_get_payload_len(attr);
|
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;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
switch(type) {
|
switch (type)
|
||||||
|
{
|
||||||
case MNL_TYPE_FLAG:
|
case MNL_TYPE_FLAG:
|
||||||
if (attr_len > 0) {
|
if (attr_len > 0)
|
||||||
|
{
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MNL_TYPE_NUL_STRING:
|
case MNL_TYPE_NUL_STRING:
|
||||||
if (attr_len == 0) {
|
if (attr_len == 0)
|
||||||
|
{
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (attr_data[attr_len-1] != '\0') {
|
if (attr_data[attr_len - 1] != '\0')
|
||||||
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MNL_TYPE_STRING:
|
case MNL_TYPE_STRING:
|
||||||
if (attr_len == 0) {
|
if (attr_len == 0)
|
||||||
|
{
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +222,8 @@ static int __mnl_attr_validate(const struct nlattr *attr,
|
||||||
if (attr_len == 0)
|
if (attr_len == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (attr_len < MNL_ATTR_HDRLEN) {
|
if (attr_len < MNL_ATTR_HDRLEN)
|
||||||
|
{
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -224,7 +232,8 @@ static int __mnl_attr_validate(const struct nlattr *attr,
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (exp_len && attr_len > exp_len) {
|
if (exp_len && attr_len > exp_len)
|
||||||
|
{
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -239,11 +248,12 @@ static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
|
||||||
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
[MNL_TYPE_MSECS] = sizeof(uint64_t),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
|
static int mnl_attr_validate(const struct nlattr* attr, enum mnl_attr_data_type type)
|
||||||
{
|
{
|
||||||
int exp_len;
|
int exp_len;
|
||||||
|
|
||||||
if (type >= MNL_TYPE_MAX) {
|
if (type >= MNL_TYPE_MAX)
|
||||||
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -251,99 +261,105 @@ static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type
|
||||||
return __mnl_attr_validate(attr, type, exp_len);
|
return __mnl_attr_validate(attr, type, exp_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset,
|
static int mnl_attr_parse(
|
||||||
mnl_attr_cb_t cb, void *data)
|
const struct nlmsghdr* nlh,
|
||||||
|
unsigned int offset,
|
||||||
|
mnl_attr_cb_t cb,
|
||||||
|
void* data)
|
||||||
{
|
{
|
||||||
int ret = MNL_CB_OK;
|
int ret = MNL_CB_OK;
|
||||||
const struct nlattr *attr;
|
const struct nlattr* attr;
|
||||||
|
|
||||||
mnl_attr_for_each(attr, nlh, offset)
|
mnl_attr_for_each(
|
||||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
attr, nlh, offset) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
|
||||||
return ret;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb,
|
static int
|
||||||
void *data)
|
mnl_attr_parse_nested(const struct nlattr* nested, mnl_attr_cb_t cb, void* data)
|
||||||
{
|
{
|
||||||
int ret = MNL_CB_OK;
|
int ret = MNL_CB_OK;
|
||||||
const struct nlattr *attr;
|
const struct nlattr* attr;
|
||||||
|
|
||||||
mnl_attr_for_each_nested(attr, nested)
|
mnl_attr_for_each_nested(
|
||||||
if ((ret = cb(attr, data)) <= MNL_CB_STOP)
|
attr, nested) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret;
|
||||||
return ret;
|
|
||||||
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;
|
uint64_t tmp;
|
||||||
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *mnl_attr_get_str(const struct nlattr *attr)
|
static const char* mnl_attr_get_str(const struct nlattr* attr)
|
||||||
{
|
{
|
||||||
return mnl_attr_get_payload(attr);
|
return mnl_attr_get_payload(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len,
|
static void
|
||||||
const void *data)
|
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;
|
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
|
||||||
int pad;
|
int pad;
|
||||||
|
|
||||||
attr->nla_type = type;
|
attr->nla_type = type;
|
||||||
attr->nla_len = payload_len;
|
attr->nla_len = payload_len;
|
||||||
memcpy(mnl_attr_get_payload(attr), data, len);
|
memcpy(mnl_attr_get_payload(attr), data, len);
|
||||||
|
|
||||||
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
nlh->nlmsg_len += MNL_ALIGN(payload_len);
|
||||||
pad = MNL_ALIGN(len) - len;
|
pad = MNL_ALIGN(len) - len;
|
||||||
if (pad > 0)
|
if (pad > 0)
|
||||||
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
memset(mnl_attr_get_payload(attr) + len, 0, pad);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
|
static void mnl_attr_put_u16(struct nlmsghdr* nlh, uint16_t type, uint16_t data)
|
||||||
{
|
{
|
||||||
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data)
|
static void mnl_attr_put_u32(struct nlmsghdr* nlh, uint16_t type, uint32_t data)
|
||||||
{
|
{
|
||||||
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data)
|
static void mnl_attr_put_strz(struct nlmsghdr* nlh, uint16_t type, const char* data)
|
||||||
{
|
{
|
||||||
mnl_attr_put(nlh, type, strlen(data)+1, data);
|
mnl_attr_put(nlh, type, strlen(data) + 1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type)
|
static struct nlattr* mnl_attr_nest_start(struct nlmsghdr* nlh, uint16_t type)
|
||||||
{
|
{
|
||||||
struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
|
struct nlattr* start = mnl_nlmsg_get_payload_tail(nlh);
|
||||||
|
|
||||||
start->nla_type = NLA_F_NESTED | type;
|
start->nla_type = NLA_F_NESTED | type;
|
||||||
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
static bool mnl_attr_put_check(
|
||||||
uint16_t type, size_t len, const void *data)
|
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)
|
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
|
||||||
return false;
|
return false;
|
||||||
|
@ -351,52 +367,55 @@ static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
|
static bool
|
||||||
uint16_t type, uint8_t data)
|
mnl_attr_put_u8_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint8_t data)
|
||||||
{
|
{
|
||||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
|
static bool
|
||||||
uint16_t type, uint16_t data)
|
mnl_attr_put_u16_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint16_t data)
|
||||||
{
|
{
|
||||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
|
static bool
|
||||||
uint16_t type, uint32_t data)
|
mnl_attr_put_u32_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint32_t data)
|
||||||
{
|
{
|
||||||
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen,
|
static struct nlattr*
|
||||||
uint16_t type)
|
mnl_attr_nest_start_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type)
|
||||||
{
|
{
|
||||||
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
|
||||||
return NULL;
|
return NULL;
|
||||||
return mnl_attr_nest_start(nlh, type);
|
return mnl_attr_nest_start(nlh, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start)
|
static void mnl_attr_nest_end(struct nlmsghdr* nlh, struct nlattr* start)
|
||||||
{
|
{
|
||||||
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start)
|
static void mnl_attr_nest_cancel(struct nlmsghdr* nlh, struct nlattr* start)
|
||||||
{
|
{
|
||||||
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
|
nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void*)start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_cb_noop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
static int mnl_cb_noop(
|
||||||
|
__attribute__((unused)) const struct nlmsghdr* nlh,
|
||||||
|
__attribute__((unused)) void* data)
|
||||||
{
|
{
|
||||||
return MNL_CB_OK;
|
return MNL_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
static int mnl_cb_error(const struct nlmsghdr* nlh, __attribute__((unused)) void* data)
|
||||||
{
|
{
|
||||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
|
||||||
|
{
|
||||||
errno = EBADMSG;
|
errno = EBADMSG;
|
||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -409,7 +428,9 @@ static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void
|
||||||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_cb_stop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data)
|
static int mnl_cb_stop(
|
||||||
|
__attribute__((unused)) const struct nlmsghdr* nlh,
|
||||||
|
__attribute__((unused)) void* data)
|
||||||
{
|
{
|
||||||
return MNL_CB_STOP;
|
return MNL_CB_STOP;
|
||||||
}
|
}
|
||||||
|
@ -421,45 +442,60 @@ static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
|
||||||
[NLMSG_OVERRUN] = mnl_cb_noop,
|
[NLMSG_OVERRUN] = mnl_cb_noop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __mnl_cb_run(const void *buf, size_t numbytes,
|
static int __mnl_cb_run(
|
||||||
unsigned int seq, unsigned int portid,
|
const void* buf,
|
||||||
mnl_cb_t cb_data, void *data,
|
size_t numbytes,
|
||||||
const mnl_cb_t *cb_ctl_array,
|
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)
|
unsigned int cb_ctl_array_len)
|
||||||
{
|
{
|
||||||
int ret = MNL_CB_OK, len = numbytes;
|
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;
|
errno = ESRCH;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mnl_nlmsg_seq_ok(nlh, seq)) {
|
if (!mnl_nlmsg_seq_ok(nlh, seq))
|
||||||
|
{
|
||||||
errno = EPROTO;
|
errno = EPROTO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
|
if (nlh->nlmsg_flags & NLM_F_DUMP_INTR)
|
||||||
|
{
|
||||||
errno = EINTR;
|
errno = EINTR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
|
if (nlh->nlmsg_type >= NLMSG_MIN_TYPE)
|
||||||
if (cb_data){
|
{
|
||||||
|
if (cb_data)
|
||||||
|
{
|
||||||
ret = cb_data(nlh, data);
|
ret = cb_data(nlh, data);
|
||||||
if (ret <= MNL_CB_STOP)
|
if (ret <= MNL_CB_STOP)
|
||||||
goto out;
|
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);
|
ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
|
||||||
if (ret <= MNL_CB_STOP)
|
if (ret <= MNL_CB_STOP)
|
||||||
goto out;
|
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);
|
ret = default_cb_array[nlh->nlmsg_type](nlh, data);
|
||||||
if (ret <= MNL_CB_STOP)
|
if (ret <= MNL_CB_STOP)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -470,40 +506,53 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq,
|
static int mnl_cb_run2(
|
||||||
unsigned int portid, mnl_cb_t cb_data, void *data,
|
const void* buf,
|
||||||
const mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len)
|
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,
|
return __mnl_cb_run(
|
||||||
cb_ctl_array, cb_ctl_array_len);
|
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,
|
static int mnl_cb_run(
|
||||||
unsigned int portid, mnl_cb_t cb_data, void *data)
|
const void* buf,
|
||||||
|
size_t numbytes,
|
||||||
|
unsigned int seq,
|
||||||
|
unsigned int portid,
|
||||||
|
mnl_cb_t cb_data,
|
||||||
|
void* data)
|
||||||
{
|
{
|
||||||
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mnl_socket {
|
struct mnl_socket
|
||||||
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
|
static unsigned int mnl_socket_get_portid(const struct mnl_socket* nl)
|
||||||
{
|
{
|
||||||
return nl->addr.nl_pid;
|
return nl->addr.nl_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
static struct mnl_socket* __mnl_socket_open(int bus, int flags)
|
||||||
{
|
{
|
||||||
struct mnl_socket *nl;
|
struct mnl_socket* nl;
|
||||||
|
|
||||||
nl = calloc(1, sizeof(struct mnl_socket));
|
nl = calloc(1, sizeof(struct mnl_socket));
|
||||||
if (nl == NULL)
|
if (nl == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
|
||||||
if (nl->fd == -1) {
|
if (nl->fd == -1)
|
||||||
|
{
|
||||||
free(nl);
|
free(nl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -511,12 +560,9 @@ static struct mnl_socket *__mnl_socket_open(int bus, int flags)
|
||||||
return nl;
|
return nl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct mnl_socket *mnl_socket_open(int bus)
|
static struct mnl_socket* mnl_socket_open(int bus) { return __mnl_socket_open(bus, 0); }
|
||||||
{
|
|
||||||
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;
|
int ret;
|
||||||
socklen_t addr_len;
|
socklen_t addr_len;
|
||||||
|
@ -525,38 +571,35 @@ static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid
|
||||||
nl->addr.nl_groups = groups;
|
nl->addr.nl_groups = groups;
|
||||||
nl->addr.nl_pid = pid;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
addr_len = sizeof(nl->addr);
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (addr_len != sizeof(nl->addr)) {
|
if (addr_len != sizeof(nl->addr))
|
||||||
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (nl->addr.nl_family != AF_NETLINK) {
|
if (nl->addr.nl_family != AF_NETLINK)
|
||||||
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf,
|
static ssize_t mnl_socket_sendto(const struct mnl_socket* nl, const void* buf, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
static const struct sockaddr_nl snl = {
|
static const struct sockaddr_nl snl = {.nl_family = AF_NETLINK};
|
||||||
.nl_family = AF_NETLINK
|
return sendto(nl->fd, buf, len, 0, (struct sockaddr*)&snl, sizeof(snl));
|
||||||
};
|
|
||||||
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,
|
static ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_t bufsiz)
|
||||||
size_t bufsiz)
|
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
|
@ -577,18 +620,20 @@ static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf,
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (msg.msg_flags & MSG_TRUNC) {
|
if (msg.msg_flags & MSG_TRUNC)
|
||||||
|
{
|
||||||
errno = ENOSPC;
|
errno = ENOSPC;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
|
if (msg.msg_namelen != sizeof(struct sockaddr_nl))
|
||||||
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return ret;
|
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);
|
int ret = close(nl->fd);
|
||||||
free(nl);
|
free(nl);
|
||||||
|
@ -597,21 +642,25 @@ static int mnl_socket_close(struct mnl_socket *nl)
|
||||||
|
|
||||||
/* This is a wrapper for generic netlink, originally from Jiri Pirko <jiri@mellanox.com>: */
|
/* This is a wrapper for generic netlink, originally from Jiri Pirko <jiri@mellanox.com>: */
|
||||||
|
|
||||||
struct mnlg_socket {
|
struct mnlg_socket
|
||||||
struct mnl_socket *nl;
|
{
|
||||||
char *buf;
|
struct mnl_socket* nl;
|
||||||
|
char* buf;
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
unsigned int seq;
|
unsigned int seq;
|
||||||
unsigned int portid;
|
unsigned int portid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
static struct nlmsghdr* __mnlg_msg_prepare(
|
||||||
uint16_t flags, uint16_t id,
|
struct mnlg_socket* nlg,
|
||||||
|
uint8_t cmd,
|
||||||
|
uint16_t flags,
|
||||||
|
uint16_t id,
|
||||||
uint8_t version)
|
uint8_t version)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr* nlh;
|
||||||
struct genlmsghdr *genl;
|
struct genlmsghdr* genl;
|
||||||
|
|
||||||
nlh = mnl_nlmsg_put_header(nlg->buf);
|
nlh = mnl_nlmsg_put_header(nlg->buf);
|
||||||
nlh->nlmsg_type = id;
|
nlh->nlmsg_type = id;
|
||||||
|
@ -626,30 +675,31 @@ static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
||||||
return nlh;
|
return nlh;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
|
static struct nlmsghdr*
|
||||||
uint16_t flags)
|
mnlg_msg_prepare(struct mnlg_socket* nlg, uint8_t cmd, uint16_t flags)
|
||||||
{
|
{
|
||||||
return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
|
return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
|
static int mnlg_socket_send(struct mnlg_socket* nlg, const struct nlmsghdr* nlh)
|
||||||
{
|
{
|
||||||
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
|
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data)
|
static int mnlg_cb_noop(const struct nlmsghdr* nlh, void* data)
|
||||||
{
|
{
|
||||||
(void)nlh;
|
(void)nlh;
|
||||||
(void)data;
|
(void)data;
|
||||||
return MNL_CB_OK;
|
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;
|
(void)data;
|
||||||
|
|
||||||
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
|
if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
|
||||||
|
{
|
||||||
errno = EBADMSG;
|
errno = EBADMSG;
|
||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -662,11 +712,12 @@ static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data)
|
||||||
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data)
|
static int mnlg_cb_stop(const struct nlmsghdr* nlh, void* data)
|
||||||
{
|
{
|
||||||
(void)data;
|
(void)data;
|
||||||
if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) {
|
if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int)))
|
||||||
int error = *(int *)mnl_nlmsg_get_payload(nlh);
|
{
|
||||||
|
int error = *(int*)mnl_nlmsg_get_payload(nlh);
|
||||||
/* Netlink subsystems returns the errno value with different signess */
|
/* Netlink subsystems returns the errno value with different signess */
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
errno = -error;
|
errno = -error;
|
||||||
|
@ -685,41 +736,47 @@ static const mnl_cb_t mnlg_cb_array[] = {
|
||||||
[NLMSG_OVERRUN] = mnlg_cb_noop,
|
[NLMSG_OVERRUN] = mnlg_cb_noop,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
|
static int mnlg_socket_recv_run(struct mnlg_socket* nlg, mnl_cb_t data_cb, void* data)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
do {
|
do
|
||||||
err = mnl_socket_recvfrom(nlg->nl, nlg->buf,
|
{
|
||||||
mnl_ideal_socket_buffer_size());
|
err = mnl_socket_recvfrom(nlg->nl, nlg->buf, mnl_ideal_socket_buffer_size());
|
||||||
if (err <= 0)
|
if (err <= 0)
|
||||||
break;
|
break;
|
||||||
err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid,
|
err = mnl_cb_run2(
|
||||||
data_cb, data, mnlg_cb_array, MNL_ARRAY_SIZE(mnlg_cb_array));
|
nlg->buf,
|
||||||
|
err,
|
||||||
|
nlg->seq,
|
||||||
|
nlg->portid,
|
||||||
|
data_cb,
|
||||||
|
data,
|
||||||
|
mnlg_cb_array,
|
||||||
|
MNL_ARRAY_SIZE(mnlg_cb_array));
|
||||||
} while (err > 0);
|
} while (err > 0);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
|
static int get_family_id_attr_cb(const struct nlattr* attr, void* data)
|
||||||
{
|
{
|
||||||
const struct nlattr **tb = data;
|
const struct nlattr** tb = data;
|
||||||
int type = mnl_attr_get_type(attr);
|
int type = mnl_attr_get_type(attr);
|
||||||
|
|
||||||
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
|
|
||||||
if (type == CTRL_ATTR_FAMILY_ID &&
|
if (type == CTRL_ATTR_FAMILY_ID && mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
||||||
mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
|
||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
tb[type] = attr;
|
tb[type] = attr;
|
||||||
return MNL_CB_OK;
|
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;
|
uint16_t* p_id = data;
|
||||||
struct nlattr *tb[CTRL_ATTR_MAX + 1] = { 0 };
|
struct nlattr* tb[CTRL_ATTR_MAX + 1] = {0};
|
||||||
|
|
||||||
mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
|
mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb);
|
||||||
if (!tb[CTRL_ATTR_FAMILY_ID])
|
if (!tb[CTRL_ATTR_FAMILY_ID])
|
||||||
|
@ -728,10 +785,10 @@ static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
return MNL_CB_OK;
|
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 mnlg_socket* nlg;
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr* nlh;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
nlg = malloc(sizeof(*nlg));
|
nlg = malloc(sizeof(*nlg));
|
||||||
|
@ -745,29 +802,33 @@ static struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t ver
|
||||||
goto err_buf_alloc;
|
goto err_buf_alloc;
|
||||||
|
|
||||||
nlg->nl = mnl_socket_open(NETLINK_GENERIC);
|
nlg->nl = mnl_socket_open(NETLINK_GENERIC);
|
||||||
if (!nlg->nl) {
|
if (!nlg->nl)
|
||||||
|
{
|
||||||
err = -errno;
|
err = -errno;
|
||||||
goto err_mnl_socket_open;
|
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;
|
err = -errno;
|
||||||
goto err_mnl_socket_bind;
|
goto err_mnl_socket_bind;
|
||||||
}
|
}
|
||||||
|
|
||||||
nlg->portid = mnl_socket_get_portid(nlg->nl);
|
nlg->portid = mnl_socket_get_portid(nlg->nl);
|
||||||
|
|
||||||
nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
|
nlh = __mnlg_msg_prepare(
|
||||||
NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
|
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);
|
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;
|
err = -errno;
|
||||||
goto err_mnlg_socket_send;
|
goto err_mnlg_socket_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
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;
|
errno = errno == ENOENT ? EPROTONOSUPPORT : errno;
|
||||||
err = errno ? -errno : -ENOSYS;
|
err = errno ? -errno : -ENOSYS;
|
||||||
goto err_mnlg_socket_recv_run;
|
goto err_mnlg_socket_recv_run;
|
||||||
|
@ -789,7 +850,7 @@ err_buf_alloc:
|
||||||
return NULL;
|
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);
|
mnl_socket_close(nlg->nl);
|
||||||
free(nlg->buf);
|
free(nlg->buf);
|
||||||
|
|
|
@ -94,6 +94,9 @@ int showconf_main(int argc, const char *argv[])
|
||||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
|
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
|
||||||
printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off");
|
printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off");
|
||||||
}
|
}
|
||||||
|
if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE) {
|
||||||
|
printf("SpecialHandshake = %s\n", peer->special_handshake ? "on" : "off");
|
||||||
|
}
|
||||||
if (peer->first_allowedip)
|
if (peer->first_allowedip)
|
||||||
printf("AllowedIPs = ");
|
printf("AllowedIPs = ");
|
||||||
for_each_wgallowedip(peer, allowedip) {
|
for_each_wgallowedip(peer, allowedip) {
|
||||||
|
|
|
@ -114,6 +114,9 @@
|
||||||
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
|
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
|
||||||
* techniques provided by AmneziaWG should
|
* techniques provided by AmneziaWG should
|
||||||
* be used.
|
* be used.
|
||||||
|
* WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake
|
||||||
|
* techniques provided by AmneziaWG should
|
||||||
|
* be used.
|
||||||
* 0: NLA_NESTED
|
* 0: NLA_NESTED
|
||||||
* ...
|
* ...
|
||||||
* ...
|
* ...
|
||||||
|
@ -147,6 +150,9 @@
|
||||||
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
|
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
|
||||||
* techniques provided by AmneziaWG should
|
* techniques provided by AmneziaWG should
|
||||||
* be used.
|
* be used.
|
||||||
|
* WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake
|
||||||
|
* techniques provided by AmneziaWG should
|
||||||
|
* be used.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -210,6 +216,7 @@ enum wgpeer_flag {
|
||||||
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
|
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
|
||||||
WGPEER_F_UPDATE_ONLY = 1U << 2,
|
WGPEER_F_UPDATE_ONLY = 1U << 2,
|
||||||
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
|
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
|
||||||
|
WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4,
|
||||||
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
|
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
|
||||||
WGPEER_F_UPDATE_ONLY
|
WGPEER_F_UPDATE_ONLY
|
||||||
};
|
};
|
||||||
|
@ -226,6 +233,7 @@ enum wgpeer_attribute {
|
||||||
WGPEER_A_ALLOWEDIPS,
|
WGPEER_A_ALLOWEDIPS,
|
||||||
WGPEER_A_PROTOCOL_VERSION,
|
WGPEER_A_PROTOCOL_VERSION,
|
||||||
WGPEER_A_ADVANCED_SECURITY,
|
WGPEER_A_ADVANCED_SECURITY,
|
||||||
|
WGPEER_A_SPECIAL_HANDSHAKE,
|
||||||
__WGPEER_A_LAST
|
__WGPEER_A_LAST
|
||||||
};
|
};
|
||||||
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
|
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
|
||||||
|
|
|
@ -7,13 +7,12 @@
|
||||||
#ifndef __IF_WG_H__
|
#ifndef __IF_WG_H__
|
||||||
#define __IF_WG_H__
|
#define __IF_WG_H__
|
||||||
|
|
||||||
#include <sys/limits.h>
|
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
#include <sys/limits.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the public interface to the WireGuard network interface.
|
* This is the public interface to the WireGuard network interface.
|
||||||
*
|
*
|
||||||
|
@ -28,10 +27,12 @@
|
||||||
#define a_ipv4 a_addr.addr_ipv4
|
#define a_ipv4 a_addr.addr_ipv4
|
||||||
#define a_ipv6 a_addr.addr_ipv6
|
#define a_ipv6 a_addr.addr_ipv6
|
||||||
|
|
||||||
struct wg_aip_io {
|
struct wg_aip_io
|
||||||
|
{
|
||||||
sa_family_t a_af;
|
sa_family_t a_af;
|
||||||
int a_cidr;
|
int a_cidr;
|
||||||
union wg_aip_addr {
|
union wg_aip_addr
|
||||||
|
{
|
||||||
struct in_addr addr_ipv4;
|
struct in_addr addr_ipv4;
|
||||||
struct in6_addr addr_ipv6;
|
struct in6_addr addr_ipv6;
|
||||||
} a_addr;
|
} a_addr;
|
||||||
|
@ -49,13 +50,15 @@ struct wg_aip_io {
|
||||||
#define p_sin p_endpoint.sa_sin
|
#define p_sin p_endpoint.sa_sin
|
||||||
#define p_sin6 p_endpoint.sa_sin6
|
#define p_sin6 p_endpoint.sa_sin6
|
||||||
|
|
||||||
struct wg_peer_io {
|
struct wg_peer_io
|
||||||
|
{
|
||||||
int p_flags;
|
int p_flags;
|
||||||
int p_protocol_version;
|
int p_protocol_version;
|
||||||
uint8_t p_public[WG_KEY_LEN];
|
uint8_t p_public[WG_KEY_LEN];
|
||||||
uint8_t p_psk[WG_KEY_LEN];
|
uint8_t p_psk[WG_KEY_LEN];
|
||||||
uint16_t p_pka;
|
uint16_t p_pka;
|
||||||
union wg_peer_endpoint {
|
union wg_peer_endpoint
|
||||||
|
{
|
||||||
struct sockaddr sa_sa;
|
struct sockaddr sa_sa;
|
||||||
struct sockaddr_in sa_sin;
|
struct sockaddr_in sa_sin;
|
||||||
struct sockaddr_in6 sa_sin6;
|
struct sockaddr_in6 sa_sin6;
|
||||||
|
@ -81,8 +84,18 @@ struct wg_peer_io {
|
||||||
#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11)
|
#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11)
|
||||||
#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12)
|
#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12)
|
||||||
#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13)
|
#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_I1 (1 << 14)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_I2 (1 << 15)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_I3 (1 << 16)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_I4 (1 << 17)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_I5 (1 << 18)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_J1 (1 << 19)
|
||||||
|
#define WG_INTERFACE_DEVICE_HAS_J2 (1 << 20)
|
||||||
|
#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;
|
uint16_t i_flags;
|
||||||
in_port_t i_port;
|
in_port_t i_port;
|
||||||
int i_rtable;
|
int i_rtable;
|
||||||
|
@ -100,12 +113,23 @@ struct wg_interface_io {
|
||||||
uint32_t i_response_packet_magic_header;
|
uint32_t i_response_packet_magic_header;
|
||||||
uint32_t i_underload_packet_magic_header;
|
uint32_t i_underload_packet_magic_header;
|
||||||
uint32_t i_transport_packet_magic_header;
|
uint32_t i_transport_packet_magic_header;
|
||||||
|
|
||||||
|
uint8_t* i_i1;
|
||||||
|
uint8_t* i_i2;
|
||||||
|
uint8_t* i_i3;
|
||||||
|
uint8_t* i_i4;
|
||||||
|
uint8_t* i_i5;
|
||||||
|
uint8_t* i_j1;
|
||||||
|
uint8_t* i_j2;
|
||||||
|
uint8_t* i_j3;
|
||||||
|
uint32_t i_itime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wg_data_io {
|
struct wg_data_io
|
||||||
|
{
|
||||||
char wgd_name[IFNAMSIZ];
|
char wgd_name[IFNAMSIZ];
|
||||||
size_t wgd_size; /* total size of the memory pointed to by wgd_interface */
|
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__ */
|
#endif /* __IF_WG_H__ */
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
#ifndef _WIREGUARD_NT_H
|
#ifndef _WIREGUARD_NT_H
|
||||||
#define _WIREGUARD_NT_H
|
#define _WIREGUARD_NT_H
|
||||||
|
|
||||||
|
#include <in6addr.h>
|
||||||
|
#include <inaddr.h>
|
||||||
#include <ntdef.h>
|
#include <ntdef.h>
|
||||||
#include <ws2def.h>
|
#include <ws2def.h>
|
||||||
#include <ws2ipdef.h>
|
#include <ws2ipdef.h>
|
||||||
#include <inaddr.h>
|
|
||||||
#include <in6addr.h>
|
|
||||||
|
|
||||||
#define WG_KEY_LEN 32
|
#define WG_KEY_LEN 32
|
||||||
|
|
||||||
|
@ -66,7 +66,16 @@ typedef enum
|
||||||
WG_IOCTL_INTERFACE_H1 = 1 << 10,
|
WG_IOCTL_INTERFACE_H1 = 1 << 10,
|
||||||
WG_IOCTL_INTERFACE_H2 = 1 << 11,
|
WG_IOCTL_INTERFACE_H2 = 1 << 11,
|
||||||
WG_IOCTL_INTERFACE_H3 = 1 << 12,
|
WG_IOCTL_INTERFACE_H3 = 1 << 12,
|
||||||
WG_IOCTL_INTERFACE_H4 = 1 << 13
|
WG_IOCTL_INTERFACE_H4 = 1 << 13,
|
||||||
|
WG_IOCTL_INTERFACE_I1 = 1U << 14,
|
||||||
|
WG_IOCTL_INTERFACE_I2 = 1U << 15,
|
||||||
|
WG_IOCTL_INTERFACE_I3 = 1U << 16,
|
||||||
|
WG_IOCTL_INTERFACE_I4 = 1U << 17,
|
||||||
|
WG_IOCTL_INTERFACE_I5 = 1U << 18,
|
||||||
|
WG_IOCTL_INTERFACE_J1 = 1U << 19,
|
||||||
|
WG_IOCTL_INTERFACE_J2 = 1U << 20,
|
||||||
|
WG_IOCTL_INTERFACE_J3 = 1U << 21,
|
||||||
|
WG_IOCTL_INTERFACE_ITIME = 1U << 22
|
||||||
} WG_IOCTL_INTERFACE_FLAG;
|
} WG_IOCTL_INTERFACE_FLAG;
|
||||||
|
|
||||||
typedef struct _WG_IOCTL_INTERFACE
|
typedef struct _WG_IOCTL_INTERFACE
|
||||||
|
@ -85,15 +94,25 @@ typedef struct _WG_IOCTL_INTERFACE
|
||||||
ULONG ResponsePacketMagicHeader;
|
ULONG ResponsePacketMagicHeader;
|
||||||
ULONG UnderloadPacketMagicHeader;
|
ULONG UnderloadPacketMagicHeader;
|
||||||
ULONG TransportPacketMagicHeader;
|
ULONG TransportPacketMagicHeader;
|
||||||
|
UCHAR* I1;
|
||||||
|
UCHAR* I2;
|
||||||
|
UCHAR* I3;
|
||||||
|
UCHAR* I4;
|
||||||
|
UCHAR* I5;
|
||||||
|
UCHAR* J1;
|
||||||
|
UCHAR* J2;
|
||||||
|
UCHAR* J3;
|
||||||
|
ULONG Itime;
|
||||||
} __attribute__((aligned(8))) WG_IOCTL_INTERFACE;
|
} __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_GET \
|
||||||
#define WG_IOCTL_SET CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
|
CTL_CODE(45208U, 321, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||||
|
#define WG_IOCTL_SET \
|
||||||
#define DEVPKEY_WG_NAME (DEVPROPKEY) { \
|
CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
|
||||||
{ 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
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue