mirror of
https://github.com/amnezia-vpn/amneziawg-tools.git
synced 2025-07-31 17:02:50 +02:00
feat: add special handshake support
This commit is contained in:
parent
71219488c1
commit
3be9c02b19
11 changed files with 1576 additions and 1011 deletions
|
@ -11,7 +11,7 @@ while read -r -d $'\t' device; do
|
|||
if [[ $device != "$last_device" ]]; then
|
||||
[[ -z $last_device ]] && printf '\n' || printf '%s,\n' "$end"
|
||||
last_device="$device"
|
||||
read -r private_key public_key listen_port jc jmin jmax s1 s2 h1 h2 h3 h4 fwmark
|
||||
read -r private_key public_key listen_port jc jmin jmax s1 s2 h1 h2 h3 h4 i1 i2 i3 i4 i5 j1 j2 j3 itime fwmark
|
||||
printf '\t"%s": {' "$device"
|
||||
delim=$'\n'
|
||||
[[ $private_key == "(none)" ]] || { printf '%s\t\t"privateKey": "%s"' "$delim" "$private_key"; delim=$',\n'; }
|
||||
|
@ -26,6 +26,15 @@ while read -r -d $'\t' device; do
|
|||
[[ $h2 == "2" ]] || { printf '%s\t\t"h2": %u' "$delim" $(( $h2 )); delim=$',\n'; }
|
||||
[[ $h3 == "3" ]] || { printf '%s\t\t"h3": %u' "$delim" $(( $h3 )); delim=$',\n'; }
|
||||
[[ $h4 == "4" ]] || { printf '%s\t\t"h4": %u' "$delim" $(( $h4 )); delim=$',\n'; }
|
||||
[[ $i1 == "(none)" ]] || { printf '%s\t\t"i1": "%s"' "$delim" "$i1"; delim=$',\n'; }
|
||||
[[ $i2 == "(none)" ]] || { printf '%s\t\t"i2": "%s"' "$delim" "$i2"; delim=$',\n'; }
|
||||
[[ $i3 == "(none)" ]] || { printf '%s\t\t"i3": "%s"' "$delim" "$i3"; delim=$',\n'; }
|
||||
[[ $i4 == "(none)" ]] || { printf '%s\t\t"i4": "%s"' "$delim" "$i4"; delim=$',\n'; }
|
||||
[[ $i5 == "(none)" ]] || { printf '%s\t\t"i5": "%s"' "$delim" "$i5"; delim=$',\n'; }
|
||||
[[ $j1 == "(none)" ]] || { printf '%s\t\t"j1": "%s"' "$delim" "$j1"; delim=$',\n'; }
|
||||
[[ $j2 == "(none)" ]] || { printf '%s\t\t"j2": "%s"' "$delim" "$j2"; delim=$',\n'; }
|
||||
[[ $j3 == "(none)" ]] || { printf '%s\t\t"j3": "%s"' "$delim" "$j3"; delim=$',\n'; }
|
||||
[[ $itime == "0" ]] || { printf '%s\t\t"itime": %u' "$delim" $(( itime )); delim=$',\n'; }
|
||||
[[ $fwmark == "off" ]] || { printf '%s\t\t"fwmark": %u' "$delim" $(( $fwmark )); delim=$',\n'; }
|
||||
printf '%s\t\t"peers": {' "$delim"; end=$'\n\t\t}\n\t}'
|
||||
delim=$'\n'
|
||||
|
|
|
@ -607,7 +607,7 @@ static bool process_line(struct config_ctx *ctx, const char *line)
|
|||
if (ret)
|
||||
ctx->device->flags |= WGDEVICE_HAS_J3;
|
||||
} else if (key_match("ITIME")) {
|
||||
ret = parse_string(&ctx->device->itime, "Itime", value);
|
||||
ret = parse_uint32(&ctx->device->itime, "Itime", value);
|
||||
if (ret)
|
||||
ctx->device->flags |= WGDEVICE_HAS_ITIME;
|
||||
} else
|
||||
|
@ -872,7 +872,7 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
|
|||
argv += 2;
|
||||
argc -=2;
|
||||
} else if (!strcmp(argv[0], "itime") && argc >= 2 && !peer) {
|
||||
if (!parse_string(&device->itime, "itime", argv[1]))
|
||||
if (!parse_uint32(&device->itime, "itime", argv[1]))
|
||||
goto error;
|
||||
|
||||
device->flags |= WGDEVICE_HAS_ITIME;
|
||||
|
|
|
@ -139,7 +139,7 @@ struct wgdevice
|
|||
char* j1;
|
||||
char* j2;
|
||||
char* j3;
|
||||
char* itime;
|
||||
uint32_t itime;
|
||||
};
|
||||
|
||||
#define for_each_wgpeer(__dev, __peer) \
|
||||
|
|
|
@ -5,438 +5,606 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <dev/wg/if_wg.h>
|
||||
#include <sys/nv.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <dev/wg/if_wg.h>
|
||||
|
||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||
|
||||
static int get_dgram_socket(void)
|
||||
{
|
||||
static int sock = -1;
|
||||
if (sock < 0)
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
return sock;
|
||||
static int sock = -1;
|
||||
if (sock < 0)
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
return sock;
|
||||
}
|
||||
|
||||
static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||
static int kernel_get_wireguard_interfaces(struct string_list* list)
|
||||
{
|
||||
struct ifgroupreq ifgr = { .ifgr_name = "wg" };
|
||||
struct ifg_req *ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
struct ifgroupreq ifgr = {.ifgr_name = "wg"};
|
||||
struct ifg_req* ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) {
|
||||
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
|
||||
goto out;
|
||||
ifgr.ifgr_len -= sizeof(struct ifg_req);
|
||||
}
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
|
||||
{
|
||||
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
|
||||
goto out;
|
||||
ifgr.ifgr_len -= sizeof(struct ifg_req);
|
||||
}
|
||||
|
||||
out:
|
||||
free(ifgr.ifgr_groups);
|
||||
return ret;
|
||||
free(ifgr.ifgr_groups);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_get_device(struct wgdevice **device, const char *ifname)
|
||||
static int kernel_get_device(struct wgdevice** device, const char* ifname)
|
||||
{
|
||||
struct wg_data_io wgd = { 0 };
|
||||
nvlist_t *nvl_device = NULL;
|
||||
const nvlist_t *const *nvl_peers;
|
||||
struct wgdevice *dev = NULL;
|
||||
size_t size, peer_count, i;
|
||||
uint64_t number;
|
||||
const void *binary;
|
||||
int ret = 0, s;
|
||||
struct wg_data_io wgd = {0};
|
||||
nvlist_t* nvl_device = NULL;
|
||||
const nvlist_t* const* nvl_peers;
|
||||
struct wgdevice* dev = NULL;
|
||||
size_t size, peer_count, i;
|
||||
uint64_t number;
|
||||
const void* binary;
|
||||
int ret = 0, s;
|
||||
|
||||
*device = NULL;
|
||||
s = get_dgram_socket();
|
||||
if (s < 0)
|
||||
goto err;
|
||||
*device = NULL;
|
||||
s = get_dgram_socket();
|
||||
if (s < 0)
|
||||
goto err;
|
||||
|
||||
strlcpy(wgd.wgd_name, ifname, sizeof(wgd.wgd_name));
|
||||
if (ioctl(s, SIOCGWG, &wgd) < 0)
|
||||
goto err;
|
||||
strlcpy(wgd.wgd_name, ifname, sizeof(wgd.wgd_name));
|
||||
if (ioctl(s, SIOCGWG, &wgd) < 0)
|
||||
goto err;
|
||||
|
||||
wgd.wgd_data = malloc(wgd.wgd_size);
|
||||
if (!wgd.wgd_data)
|
||||
goto err;
|
||||
if (ioctl(s, SIOCGWG, &wgd) < 0)
|
||||
goto err;
|
||||
wgd.wgd_data = malloc(wgd.wgd_size);
|
||||
if (!wgd.wgd_data)
|
||||
goto err;
|
||||
if (ioctl(s, SIOCGWG, &wgd) < 0)
|
||||
goto err;
|
||||
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
goto err;
|
||||
strlcpy(dev->name, ifname, sizeof(dev->name));
|
||||
nvl_device = nvlist_unpack(wgd.wgd_data, wgd.wgd_size, 0);
|
||||
if (!nvl_device)
|
||||
goto err;
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
goto err;
|
||||
strlcpy(dev->name, ifname, sizeof(dev->name));
|
||||
nvl_device = nvlist_unpack(wgd.wgd_data, wgd.wgd_size, 0);
|
||||
if (!nvl_device)
|
||||
goto err;
|
||||
|
||||
if (nvlist_exists_number(nvl_device, "listen-port")) {
|
||||
number = nvlist_get_number(nvl_device, "listen-port");
|
||||
if (number <= UINT16_MAX) {
|
||||
dev->listen_port = number;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jc")) {
|
||||
number = nvlist_get_number(nvl_device, "jc");
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_count = number;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmin")) {
|
||||
number = nvlist_get_number(nvl_device, "jmin");
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_min_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmax")) {
|
||||
number = nvlist_get_number(nvl_device, "jmax");
|
||||
if (number <= UINT16_MAX){
|
||||
dev->junk_packet_max_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s1")) {
|
||||
number = nvlist_get_number(nvl_device, "s1");
|
||||
if (number <= UINT16_MAX){
|
||||
dev->init_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s2")) {
|
||||
number = nvlist_get_number(nvl_device, "s2");
|
||||
if (number <= UINT16_MAX){
|
||||
dev->response_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h1")) {
|
||||
number = nvlist_get_number(nvl_device, "h1");
|
||||
if (number <= UINT32_MAX){
|
||||
dev->init_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h2")) {
|
||||
number = nvlist_get_number(nvl_device, "h2");
|
||||
if (number <= UINT32_MAX){
|
||||
dev->response_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h3")) {
|
||||
number = nvlist_get_number(nvl_device, "h3");
|
||||
if (number <= UINT32_MAX){
|
||||
dev->underload_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h4")) {
|
||||
number = nvlist_get_number(nvl_device, "h4");
|
||||
if (number <= UINT32_MAX){
|
||||
dev->transport_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "listen-port"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "listen-port");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->listen_port = number;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jc"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "jc");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->junk_packet_count = number;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmin"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "jmin");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->junk_packet_min_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "jmax"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "jmax");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->junk_packet_max_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s1"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "s1");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->init_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "s2"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "s2");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
dev->response_packet_junk_size = number;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h1"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "h1");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
dev->init_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h2"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "h2");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
dev->response_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h3"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "h3");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
dev->underload_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_device, "h4"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "h4");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
dev->transport_packet_magic_header = number;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "i1"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "i1", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->i1 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_I1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "i2"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "i2", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->i2 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_I2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "i3"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "i3", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->i3 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_I3;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "i4"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "i4", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->i4 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_I4;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "i5"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "i5", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->i5 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_I5;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "j1"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "j1", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->j1 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_J1;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "j2"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "j2", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->j2 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_J2;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "j3"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "j3", &size);
|
||||
if (binary && size < MAX_AWG_JUNK_LEN)
|
||||
{
|
||||
dev->j3 = strdup((const char*)binary);
|
||||
dev->flags |= WGDEVICE_HAS_J3;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "itime"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "itime");
|
||||
if (number <= INT32_MAX)
|
||||
{
|
||||
dev->itime = number;
|
||||
dev->flags |= WGDEVICE_HAS_ITIME;
|
||||
}
|
||||
}
|
||||
|
||||
if (nvlist_exists_number(nvl_device, "user-cookie")) {
|
||||
number = nvlist_get_number(nvl_device, "user-cookie");
|
||||
if (number <= UINT32_MAX) {
|
||||
dev->fwmark = number;
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "public-key")) {
|
||||
binary = nvlist_get_binary(nvl_device, "public-key", &size);
|
||||
if (binary && size == sizeof(dev->public_key)) {
|
||||
memcpy(dev->public_key, binary, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "private-key")) {
|
||||
binary = nvlist_get_binary(nvl_device, "private-key", &size);
|
||||
if (binary && size == sizeof(dev->private_key)) {
|
||||
memcpy(dev->private_key, binary, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
}
|
||||
if (!nvlist_exists_nvlist_array(nvl_device, "peers"))
|
||||
goto skip_peers;
|
||||
nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count);
|
||||
if (!nvl_peers)
|
||||
goto skip_peers;
|
||||
for (i = 0; i < peer_count; ++i) {
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip = NULL;
|
||||
const nvlist_t *const *nvl_aips;
|
||||
size_t aip_count, j;
|
||||
if (nvlist_exists_number(nvl_device, "user-cookie"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_device, "user-cookie");
|
||||
if (number <= UINT32_MAX)
|
||||
{
|
||||
dev->fwmark = number;
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "public-key"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "public-key", &size);
|
||||
if (binary && size == sizeof(dev->public_key))
|
||||
{
|
||||
memcpy(dev->public_key, binary, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_device, "private-key"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_device, "private-key", &size);
|
||||
if (binary && size == sizeof(dev->private_key))
|
||||
{
|
||||
memcpy(dev->private_key, binary, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
}
|
||||
if (!nvlist_exists_nvlist_array(nvl_device, "peers"))
|
||||
goto skip_peers;
|
||||
nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count);
|
||||
if (!nvl_peers)
|
||||
goto skip_peers;
|
||||
for (i = 0; i < peer_count; ++i)
|
||||
{
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip = NULL;
|
||||
const nvlist_t* const* nvl_aips;
|
||||
size_t aip_count, j;
|
||||
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto err_peer;
|
||||
if (nvlist_exists_binary(nvl_peers[i], "public-key")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "public-key", &size);
|
||||
if (binary && size == sizeof(peer->public_key)) {
|
||||
memcpy(peer->public_key, binary, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "preshared-key")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size);
|
||||
if (binary && size == sizeof(peer->preshared_key)) {
|
||||
memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval")) {
|
||||
number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval");
|
||||
if (number <= UINT16_MAX) {
|
||||
peer->persistent_keepalive_interval = number;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "endpoint")) {
|
||||
const struct sockaddr *endpoint = nvlist_get_binary(nvl_peers[i], "endpoint", &size);
|
||||
if (endpoint && size <= sizeof(peer->endpoint) && size >= sizeof(peer->endpoint.addr) &&
|
||||
(endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6))
|
||||
memcpy(&peer->endpoint.addr, endpoint, size);
|
||||
}
|
||||
if (nvlist_exists_number(nvl_peers[i], "rx-bytes"))
|
||||
peer->rx_bytes = nvlist_get_number(nvl_peers[i], "rx-bytes");
|
||||
if (nvlist_exists_number(nvl_peers[i], "tx-bytes"))
|
||||
peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes");
|
||||
if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time")) {
|
||||
binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size);
|
||||
if (binary && size == sizeof(peer->last_handshake_time))
|
||||
memcpy(&peer->last_handshake_time, binary, sizeof(peer->last_handshake_time));
|
||||
}
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto err_peer;
|
||||
if (nvlist_exists_binary(nvl_peers[i], "public-key"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_peers[i], "public-key", &size);
|
||||
if (binary && size == sizeof(peer->public_key))
|
||||
{
|
||||
memcpy(peer->public_key, binary, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "preshared-key"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size);
|
||||
if (binary && size == sizeof(peer->preshared_key))
|
||||
{
|
||||
memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval"))
|
||||
{
|
||||
number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval");
|
||||
if (number <= UINT16_MAX)
|
||||
{
|
||||
peer->persistent_keepalive_interval = number;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
}
|
||||
if (nvlist_exists_binary(nvl_peers[i], "endpoint"))
|
||||
{
|
||||
const struct sockaddr* endpoint =
|
||||
nvlist_get_binary(nvl_peers[i], "endpoint", &size);
|
||||
if (endpoint && size <= sizeof(peer->endpoint) &&
|
||||
size >= sizeof(peer->endpoint.addr) &&
|
||||
(endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6))
|
||||
memcpy(&peer->endpoint.addr, endpoint, size);
|
||||
}
|
||||
if (nvlist_exists_number(nvl_peers[i], "rx-bytes"))
|
||||
peer->rx_bytes = nvlist_get_number(nvl_peers[i], "rx-bytes");
|
||||
if (nvlist_exists_number(nvl_peers[i], "tx-bytes"))
|
||||
peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes");
|
||||
if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size);
|
||||
if (binary && size == sizeof(peer->last_handshake_time))
|
||||
memcpy(
|
||||
&peer->last_handshake_time,
|
||||
binary,
|
||||
sizeof(peer->last_handshake_time));
|
||||
}
|
||||
|
||||
if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips"))
|
||||
goto skip_allowed_ips;
|
||||
nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count);
|
||||
if (!aip_count || !nvl_aips)
|
||||
goto skip_allowed_ips;
|
||||
for (j = 0; j < aip_count; ++j) {
|
||||
if (!nvlist_exists_number(nvl_aips[j], "cidr"))
|
||||
continue;
|
||||
if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && !nvlist_exists_binary(nvl_aips[j], "ipv6"))
|
||||
continue;
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto err_allowed_ips;
|
||||
number = nvlist_get_number(nvl_aips[j], "cidr");
|
||||
if (nvlist_exists_binary(nvl_aips[j], "ipv4")) {
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size);
|
||||
if (!binary || number > 32) {
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
aip->family = AF_INET;
|
||||
aip->cidr = number;
|
||||
memcpy(&aip->ip4, binary, sizeof(aip->ip4));
|
||||
} else {
|
||||
assert(nvlist_exists_binary(nvl_aips[j], "ipv6"));
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size);
|
||||
if (!binary || number > 128) {
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
aip->family = AF_INET6;
|
||||
aip->cidr = number;
|
||||
memcpy(&aip->ip6, binary, sizeof(aip->ip6));
|
||||
}
|
||||
if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips"))
|
||||
goto skip_allowed_ips;
|
||||
nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count);
|
||||
if (!aip_count || !nvl_aips)
|
||||
goto skip_allowed_ips;
|
||||
for (j = 0; j < aip_count; ++j)
|
||||
{
|
||||
if (!nvlist_exists_number(nvl_aips[j], "cidr"))
|
||||
continue;
|
||||
if (!nvlist_exists_binary(nvl_aips[j], "ipv4") &&
|
||||
!nvlist_exists_binary(nvl_aips[j], "ipv6"))
|
||||
continue;
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto err_allowed_ips;
|
||||
number = nvlist_get_number(nvl_aips[j], "cidr");
|
||||
if (nvlist_exists_binary(nvl_aips[j], "ipv4"))
|
||||
{
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size);
|
||||
if (!binary || number > 32)
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
aip->family = AF_INET;
|
||||
aip->cidr = number;
|
||||
memcpy(&aip->ip4, binary, sizeof(aip->ip4));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(nvlist_exists_binary(nvl_aips[j], "ipv6"));
|
||||
binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size);
|
||||
if (!binary || number > 128)
|
||||
{
|
||||
ret = EINVAL;
|
||||
goto err_allowed_ips;
|
||||
}
|
||||
aip->family = AF_INET6;
|
||||
aip->cidr = number;
|
||||
memcpy(&aip->ip6, binary, sizeof(aip->ip6));
|
||||
}
|
||||
|
||||
if (!peer->first_allowedip)
|
||||
peer->first_allowedip = aip;
|
||||
else
|
||||
peer->last_allowedip->next_allowedip = aip;
|
||||
peer->last_allowedip = aip;
|
||||
aip = NULL;
|
||||
continue;
|
||||
if (!peer->first_allowedip)
|
||||
peer->first_allowedip = aip;
|
||||
else
|
||||
peer->last_allowedip->next_allowedip = aip;
|
||||
peer->last_allowedip = aip;
|
||||
aip = NULL;
|
||||
continue;
|
||||
|
||||
err_allowed_ips:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(aip);
|
||||
goto err_peer;
|
||||
}
|
||||
err_allowed_ips:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(aip);
|
||||
goto err_peer;
|
||||
}
|
||||
|
||||
/* Nothing leaked, hopefully -- ownership transferred or aip freed. */
|
||||
assert(aip == NULL);
|
||||
skip_allowed_ips:
|
||||
if (!dev->first_peer)
|
||||
dev->first_peer = peer;
|
||||
else
|
||||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
continue;
|
||||
/* Nothing leaked, hopefully -- ownership transferred or aip freed. */
|
||||
assert(aip == NULL);
|
||||
skip_allowed_ips:
|
||||
if (!dev->first_peer)
|
||||
dev->first_peer = peer;
|
||||
else
|
||||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
continue;
|
||||
|
||||
err_peer:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(peer);
|
||||
goto err;
|
||||
}
|
||||
err_peer:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(peer);
|
||||
goto err;
|
||||
}
|
||||
|
||||
skip_peers:
|
||||
free(wgd.wgd_data);
|
||||
nvlist_destroy(nvl_device);
|
||||
*device = dev;
|
||||
return 0;
|
||||
free(wgd.wgd_data);
|
||||
nvlist_destroy(nvl_device);
|
||||
*device = dev;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(wgd.wgd_data);
|
||||
nvlist_destroy(nvl_device);
|
||||
free(dev);
|
||||
return ret;
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
free(wgd.wgd_data);
|
||||
nvlist_destroy(nvl_device);
|
||||
free(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int kernel_set_device(struct wgdevice *dev)
|
||||
static int kernel_set_device(struct wgdevice* dev)
|
||||
{
|
||||
struct wg_data_io wgd = { 0 };
|
||||
nvlist_t *nvl_device = NULL, **nvl_peers = NULL;
|
||||
size_t peer_count = 0, i = 0;
|
||||
struct wgpeer *peer;
|
||||
int ret = 0, s;
|
||||
struct wg_data_io wgd = {0};
|
||||
nvlist_t * nvl_device = NULL, **nvl_peers = NULL;
|
||||
size_t peer_count = 0, i = 0;
|
||||
struct wgpeer* peer;
|
||||
int ret = 0, s;
|
||||
|
||||
strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name));
|
||||
strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name));
|
||||
|
||||
nvl_device = nvlist_create(0);
|
||||
if (!nvl_device)
|
||||
goto err;
|
||||
nvl_device = nvlist_create(0);
|
||||
if (!nvl_device)
|
||||
goto err;
|
||||
|
||||
for_each_wgpeer(dev, peer)
|
||||
++peer_count;
|
||||
if (peer_count) {
|
||||
nvl_peers = calloc(peer_count, sizeof(*nvl_peers));
|
||||
if (!nvl_peers)
|
||||
goto err;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
nvlist_add_binary(nvl_device, "private-key", dev->private_key, sizeof(dev->private_key));
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
nvlist_add_number(nvl_device, "listen-port", dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
nvlist_add_number(nvl_device, "jc", dev->junk_packet_count);
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
nvlist_add_number(nvl_device, "jmin", dev->junk_packet_min_size);
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
nvlist_add_number(nvl_device, "jmax", dev->junk_packet_max_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
nvlist_add_number(nvl_device, "s1", dev->init_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
nvlist_add_number(nvl_device, "s2", dev->response_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
nvlist_add_number(nvl_device, "h1", dev->init_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
nvlist_add_number(nvl_device, "h2", dev->response_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
nvlist_add_number(nvl_device, "h4", dev->transport_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
nvlist_add_number(nvl_device, "user-cookie", dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
nvlist_add_bool(nvl_device, "replace-peers", true);
|
||||
for_each_wgpeer(dev, peer)++ peer_count;
|
||||
if (peer_count)
|
||||
{
|
||||
nvl_peers = calloc(peer_count, sizeof(*nvl_peers));
|
||||
if (!nvl_peers)
|
||||
goto err;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
nvlist_add_binary(
|
||||
nvl_device, "private-key", dev->private_key, sizeof(dev->private_key));
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
nvlist_add_number(nvl_device, "listen-port", dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
nvlist_add_number(nvl_device, "jc", dev->junk_packet_count);
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
nvlist_add_number(nvl_device, "jmin", dev->junk_packet_min_size);
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
nvlist_add_number(nvl_device, "jmax", dev->junk_packet_max_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
nvlist_add_number(nvl_device, "s1", dev->init_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
nvlist_add_number(nvl_device, "s2", dev->response_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
nvlist_add_number(nvl_device, "h1", dev->init_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
nvlist_add_number(nvl_device, "h2", dev->response_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
nvlist_add_number(nvl_device, "h4", dev->transport_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_I1)
|
||||
nvlist_add_binary(nvl_device, "i1", dev->i1, strlen(dev->i1) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_I2)
|
||||
nvlist_add_binary(nvl_device, "i2", dev->i2, strlen(dev->i2) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_I3)
|
||||
nvlist_add_binary(nvl_device, "i3", dev->i3, strlen(dev->i3) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_I4)
|
||||
nvlist_add_binary(nvl_device, "i4", dev->i4, strlen(dev->i4) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_I5)
|
||||
nvlist_add_binary(nvl_device, "i5", dev->i5, strlen(dev->i5) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_J1)
|
||||
nvlist_add_binary(nvl_device, "j1", dev->j1, strlen(dev->j1) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_J2)
|
||||
nvlist_add_binary(nvl_device, "j2", dev->j2, strlen(dev->j2) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_J3)
|
||||
nvlist_add_binary(nvl_device, "j3", dev->j3, strlen(dev->j3) + 1);
|
||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
nvlist_add_number(nvl_device, "itime", dev->itime);
|
||||
|
||||
for_each_wgpeer(dev, peer) {
|
||||
size_t aip_count = 0, j = 0;
|
||||
nvlist_t **nvl_aips = NULL;
|
||||
struct wgallowedip *aip;
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
nvlist_add_number(nvl_device, "user-cookie", dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
nvlist_add_bool(nvl_device, "replace-peers", true);
|
||||
|
||||
nvl_peers[i] = nvlist_create(0);
|
||||
if (!nvl_peers[i])
|
||||
goto err_peer;
|
||||
for_each_wgallowedip(peer, aip)
|
||||
++aip_count;
|
||||
if (aip_count) {
|
||||
nvl_aips = calloc(aip_count, sizeof(*nvl_aips));
|
||||
if (!nvl_aips)
|
||||
goto err_peer;
|
||||
}
|
||||
nvlist_add_binary(nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key));
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
nvlist_add_binary(nvl_peers[i], "preshared-key", peer->preshared_key, sizeof(peer->preshared_key));
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
nvlist_add_number(nvl_peers[i], "persistent-keepalive-interval", peer->persistent_keepalive_interval);
|
||||
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6)
|
||||
nvlist_add_binary(nvl_peers[i], "endpoint", &peer->endpoint.addr, peer->endpoint.addr.sa_len);
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
nvlist_add_bool(nvl_peers[i], "replace-allowedips", true);
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
nvlist_add_bool(nvl_peers[i], "remove", true);
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
nvl_aips[j] = nvlist_create(0);
|
||||
if (!nvl_aips[j])
|
||||
goto err_peer;
|
||||
nvlist_add_number(nvl_aips[j], "cidr", aip->cidr);
|
||||
if (aip->family == AF_INET)
|
||||
nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4));
|
||||
else if (aip->family == AF_INET6)
|
||||
nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6));
|
||||
++j;
|
||||
}
|
||||
if (j) {
|
||||
nvlist_add_nvlist_array(nvl_peers[i], "allowed-ips", (const nvlist_t *const *)nvl_aips, j);
|
||||
for (j = 0; j < aip_count; ++j)
|
||||
nvlist_destroy(nvl_aips[j]);
|
||||
free(nvl_aips);
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
size_t aip_count = 0, j = 0;
|
||||
nvlist_t** nvl_aips = NULL;
|
||||
struct wgallowedip* aip;
|
||||
|
||||
err_peer:
|
||||
ret = -errno;
|
||||
for (j = 0; j < aip_count && nvl_aips; ++j)
|
||||
nvlist_destroy(nvl_aips[j]);
|
||||
free(nvl_aips);
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
nvl_peers[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
if (i) {
|
||||
nvlist_add_nvlist_array(nvl_device, "peers", (const nvlist_t *const *)nvl_peers, i);
|
||||
for (i = 0; i < peer_count; ++i)
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
free(nvl_peers);
|
||||
nvl_peers = NULL;
|
||||
}
|
||||
wgd.wgd_data = nvlist_pack(nvl_device, &wgd.wgd_size);
|
||||
nvlist_destroy(nvl_device);
|
||||
nvl_device = NULL;
|
||||
if (!wgd.wgd_data)
|
||||
goto err;
|
||||
s = get_dgram_socket();
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
return ioctl(s, SIOCSWG, &wgd);
|
||||
nvl_peers[i] = nvlist_create(0);
|
||||
if (!nvl_peers[i])
|
||||
goto err_peer;
|
||||
for_each_wgallowedip(peer, aip)++ aip_count;
|
||||
if (aip_count)
|
||||
{
|
||||
nvl_aips = calloc(aip_count, sizeof(*nvl_aips));
|
||||
if (!nvl_aips)
|
||||
goto err_peer;
|
||||
}
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key));
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i],
|
||||
"preshared-key",
|
||||
peer->preshared_key,
|
||||
sizeof(peer->preshared_key));
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
nvlist_add_number(
|
||||
nvl_peers[i],
|
||||
"persistent-keepalive-interval",
|
||||
peer->persistent_keepalive_interval);
|
||||
if (peer->endpoint.addr.sa_family == AF_INET ||
|
||||
peer->endpoint.addr.sa_family == AF_INET6)
|
||||
nvlist_add_binary(
|
||||
nvl_peers[i],
|
||||
"endpoint",
|
||||
&peer->endpoint.addr,
|
||||
peer->endpoint.addr.sa_len);
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
nvlist_add_bool(nvl_peers[i], "replace-allowedips", true);
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
nvlist_add_bool(nvl_peers[i], "remove", true);
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
nvl_aips[j] = nvlist_create(0);
|
||||
if (!nvl_aips[j])
|
||||
goto err_peer;
|
||||
nvlist_add_number(nvl_aips[j], "cidr", aip->cidr);
|
||||
if (aip->family == AF_INET)
|
||||
nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4));
|
||||
else if (aip->family == AF_INET6)
|
||||
nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6));
|
||||
++j;
|
||||
}
|
||||
if (j)
|
||||
{
|
||||
nvlist_add_nvlist_array(
|
||||
nvl_peers[i], "allowed-ips", (const nvlist_t* const*)nvl_aips, j);
|
||||
for (j = 0; j < aip_count; ++j)
|
||||
nvlist_destroy(nvl_aips[j]);
|
||||
free(nvl_aips);
|
||||
}
|
||||
++i;
|
||||
continue;
|
||||
|
||||
err_peer:
|
||||
ret = -errno;
|
||||
for (j = 0; j < aip_count && nvl_aips; ++j)
|
||||
nvlist_destroy(nvl_aips[j]);
|
||||
free(nvl_aips);
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
nvl_peers[i] = NULL;
|
||||
goto err;
|
||||
}
|
||||
if (i)
|
||||
{
|
||||
nvlist_add_nvlist_array(
|
||||
nvl_device, "peers", (const nvlist_t* const*)nvl_peers, i);
|
||||
for (i = 0; i < peer_count; ++i)
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
free(nvl_peers);
|
||||
nvl_peers = NULL;
|
||||
}
|
||||
wgd.wgd_data = nvlist_pack(nvl_device, &wgd.wgd_size);
|
||||
nvlist_destroy(nvl_device);
|
||||
nvl_device = NULL;
|
||||
if (!wgd.wgd_data)
|
||||
goto err;
|
||||
s = get_dgram_socket();
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
return ioctl(s, SIOCSWG, &wgd);
|
||||
|
||||
err:
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
for (i = 0; i < peer_count && nvl_peers; ++i)
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
free(nvl_peers);
|
||||
nvlist_destroy(nvl_device);
|
||||
return ret;
|
||||
if (!ret)
|
||||
ret = -errno;
|
||||
for (i = 0; i < peer_count && nvl_peers; ++i)
|
||||
nvlist_destroy(nvl_peers[i]);
|
||||
free(nvl_peers);
|
||||
nvlist_destroy(nvl_device);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -646,53 +646,70 @@ static int parse_device(const struct nlattr* attr, void* data)
|
|||
device->transport_packet_magic_header = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
||||
break;
|
||||
case WGDEVICE_A_I1:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->i1 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_I1;
|
||||
}
|
||||
case WGDEVICE_A_I2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_I2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->i2 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_I2;
|
||||
}
|
||||
case WGDEVICE_A_I3:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_I3:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->i3 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_I3;
|
||||
}
|
||||
case WGDEVICE_A_I4:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_I4:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->i4 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_I4;
|
||||
}
|
||||
case WGDEVICE_A_I5:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_I5:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->i5 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_I5;
|
||||
}
|
||||
case WGDEVICE_A_J1:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_J1:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->j1 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_J1;
|
||||
}
|
||||
case WGDEVICE_A_J2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_J2:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->j2 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_J2;
|
||||
}
|
||||
case WGDEVICE_A_J3:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_J3:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->j3 = strdup(mnl_attr_get_str(attr));
|
||||
device->flags |= WGDEVICE_HAS_J3;
|
||||
}
|
||||
case WGDEVICE_A_ITIME:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) {
|
||||
device->itime = strdup(mnl_attr_get_str(attr));
|
||||
}
|
||||
break;
|
||||
case WGDEVICE_A_ITIME:
|
||||
if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
|
||||
{
|
||||
device->itime = mnl_attr_get_u32(attr);
|
||||
device->flags |= WGDEVICE_HAS_ITIME;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return MNL_CB_OK;
|
||||
|
|
|
@ -3,370 +3,521 @@
|
|||
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "containers.h"
|
||||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_wg.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_wg.h>
|
||||
#include <netinet/in.h>
|
||||
#include "containers.h"
|
||||
#include <time.h>
|
||||
|
||||
#define IPC_SUPPORTS_KERNEL_INTERFACE
|
||||
|
||||
static int get_dgram_socket(void)
|
||||
{
|
||||
static int sock = -1;
|
||||
if (sock < 0)
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
return sock;
|
||||
static int sock = -1;
|
||||
if (sock < 0)
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
return sock;
|
||||
}
|
||||
|
||||
static int kernel_get_wireguard_interfaces(struct string_list *list)
|
||||
static int kernel_get_wireguard_interfaces(struct string_list* list)
|
||||
{
|
||||
struct ifgroupreq ifgr = { .ifgr_name = "wg" };
|
||||
struct ifg_req *ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
struct ifgroupreq ifgr = {.ifgr_name = "wg"};
|
||||
struct ifg_req* ifg;
|
||||
int s = get_dgram_socket(), ret = 0;
|
||||
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
return errno == ENOENT ? 0 : -errno;
|
||||
|
||||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) {
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
|
||||
if (!ifgr.ifgr_groups)
|
||||
return -errno;
|
||||
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) {
|
||||
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
|
||||
goto out;
|
||||
ifgr.ifgr_len -= sizeof(struct ifg_req);
|
||||
}
|
||||
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
|
||||
{
|
||||
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
|
||||
goto out;
|
||||
ifgr.ifgr_len -= sizeof(struct ifg_req);
|
||||
}
|
||||
|
||||
out:
|
||||
free(ifgr.ifgr_groups);
|
||||
return ret;
|
||||
free(ifgr.ifgr_groups);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_get_device(struct wgdevice **device, const char *iface)
|
||||
static int kernel_get_device(struct wgdevice** device, const char* iface)
|
||||
{
|
||||
struct wg_data_io wgdata = { .wgd_size = 0 };
|
||||
struct wg_interface_io *wg_iface;
|
||||
struct wg_peer_io *wg_peer;
|
||||
struct wg_aip_io *wg_aip;
|
||||
struct wgdevice *dev;
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip;
|
||||
int s = get_dgram_socket(), ret;
|
||||
struct wg_data_io wgdata = {.wgd_size = 0};
|
||||
struct wg_interface_io* wg_iface;
|
||||
struct wg_peer_io* wg_peer;
|
||||
struct wg_aip_io* wg_aip;
|
||||
struct wgdevice* dev;
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip;
|
||||
int s = get_dgram_socket(), ret;
|
||||
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
*device = NULL;
|
||||
strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name));
|
||||
for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) {
|
||||
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0)
|
||||
goto out;
|
||||
if (last_size >= wgdata.wgd_size)
|
||||
break;
|
||||
wgdata.wgd_interface = realloc(wgdata.wgd_interface, wgdata.wgd_size);
|
||||
if (!wgdata.wgd_interface)
|
||||
goto out;
|
||||
}
|
||||
*device = NULL;
|
||||
strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name));
|
||||
for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size)
|
||||
{
|
||||
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0)
|
||||
goto out;
|
||||
if (last_size >= wgdata.wgd_size)
|
||||
break;
|
||||
wgdata.wgd_interface = realloc(wgdata.wgd_interface, wgdata.wgd_size);
|
||||
if (!wgdata.wgd_interface)
|
||||
goto out;
|
||||
}
|
||||
|
||||
wg_iface = wgdata.wgd_interface;
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
goto out;
|
||||
strlcpy(dev->name, iface, sizeof(dev->name));
|
||||
wg_iface = wgdata.wgd_interface;
|
||||
dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
goto out;
|
||||
strlcpy(dev->name, iface, sizeof(dev->name));
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE) {
|
||||
dev->fwmark = wg_iface->i_rtable;
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE)
|
||||
{
|
||||
dev->fwmark = wg_iface->i_rtable;
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT) {
|
||||
dev->listen_port = wg_iface->i_port;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT)
|
||||
{
|
||||
dev->listen_port = wg_iface->i_port;
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC) {
|
||||
memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC)
|
||||
{
|
||||
memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key));
|
||||
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE) {
|
||||
memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE)
|
||||
{
|
||||
memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key));
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC) {
|
||||
dev->junk_packet_count = wg_iface->i_junk_packet_count;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC)
|
||||
{
|
||||
dev->junk_packet_count = wg_iface->i_junk_packet_count;
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN) {
|
||||
dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN)
|
||||
{
|
||||
dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size;
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX) {
|
||||
dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX)
|
||||
{
|
||||
dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size;
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1) {
|
||||
dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1)
|
||||
{
|
||||
dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size;
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2) {
|
||||
dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2)
|
||||
{
|
||||
dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size;
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1) {
|
||||
dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1)
|
||||
{
|
||||
dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2) {
|
||||
dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2)
|
||||
{
|
||||
dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3) {
|
||||
dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3)
|
||||
{
|
||||
dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4) {
|
||||
dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for (size_t i = 0; i < wg_iface->i_peers_count; ++i) {
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto out;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4)
|
||||
{
|
||||
dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header;
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
|
||||
if (dev->first_peer == NULL)
|
||||
dev->first_peer = peer;
|
||||
else
|
||||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I1)
|
||||
{
|
||||
wg_iface->i_i1 = strdup(dev->i1);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_I1;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC) {
|
||||
memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I2)
|
||||
{
|
||||
wg_iface->i_i2 = strdup(dev->i2);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_I2;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PSK) {
|
||||
memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I3)
|
||||
{
|
||||
wg_iface->i_i3 = strdup(dev->i3);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_I3;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PKA) {
|
||||
peer->persistent_keepalive_interval = wg_peer->p_pka;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I4)
|
||||
{
|
||||
wg_iface->i_i4 = strdup(dev->i4);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_I4;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT && wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr))
|
||||
memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len);
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I5)
|
||||
{
|
||||
wg_iface->i_i5 = strdup(dev->i5);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_I5;
|
||||
}
|
||||
|
||||
peer->rx_bytes = wg_peer->p_rxbytes;
|
||||
peer->tx_bytes = wg_peer->p_txbytes;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J1)
|
||||
{
|
||||
wg_iface->i_j1 = strdup(dev->j1);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_J1;
|
||||
}
|
||||
|
||||
peer->last_handshake_time.tv_sec = wg_peer->p_last_handshake.tv_sec;
|
||||
peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J2)
|
||||
{
|
||||
wg_iface->i_j2 = strdup(dev->j2);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_J2;
|
||||
}
|
||||
|
||||
wg_aip = &wg_peer->p_aips[0];
|
||||
for (size_t j = 0; j < wg_peer->p_aips_count; ++j) {
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto out;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J3)
|
||||
{
|
||||
wg_iface->i_j3 = strdup(dev->j3);
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_J3;
|
||||
}
|
||||
|
||||
if (peer->first_allowedip == NULL)
|
||||
peer->first_allowedip = aip;
|
||||
else
|
||||
peer->last_allowedip->next_allowedip = aip;
|
||||
peer->last_allowedip = aip;
|
||||
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_ITIME)
|
||||
{
|
||||
wg_iface->i_itime = dev->itime;
|
||||
wg_iface->i_flags |= WGDEVICE_HAS_ITIME;
|
||||
}
|
||||
|
||||
aip->family = wg_aip->a_af;
|
||||
if (wg_aip->a_af == AF_INET) {
|
||||
memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4));
|
||||
aip->cidr = wg_aip->a_cidr;
|
||||
} else if (wg_aip->a_af == AF_INET6) {
|
||||
memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6));
|
||||
aip->cidr = wg_aip->a_cidr;
|
||||
}
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer = (struct wg_peer_io *)wg_aip;
|
||||
}
|
||||
*device = dev;
|
||||
errno = 0;
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for (size_t i = 0; i < wg_iface->i_peers_count; ++i)
|
||||
{
|
||||
peer = calloc(1, sizeof(*peer));
|
||||
if (!peer)
|
||||
goto out;
|
||||
|
||||
if (dev->first_peer == NULL)
|
||||
dev->first_peer = peer;
|
||||
else
|
||||
dev->last_peer->next_peer = peer;
|
||||
dev->last_peer = peer;
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC)
|
||||
{
|
||||
memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key));
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PSK)
|
||||
{
|
||||
memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key));
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_PKA)
|
||||
{
|
||||
peer->persistent_keepalive_interval = wg_peer->p_pka;
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
|
||||
if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT &&
|
||||
wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr))
|
||||
memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len);
|
||||
|
||||
peer->rx_bytes = wg_peer->p_rxbytes;
|
||||
peer->tx_bytes = wg_peer->p_txbytes;
|
||||
|
||||
peer->last_handshake_time.tv_sec = wg_peer->p_last_handshake.tv_sec;
|
||||
peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec;
|
||||
|
||||
wg_aip = &wg_peer->p_aips[0];
|
||||
for (size_t j = 0; j < wg_peer->p_aips_count; ++j)
|
||||
{
|
||||
aip = calloc(1, sizeof(*aip));
|
||||
if (!aip)
|
||||
goto out;
|
||||
|
||||
if (peer->first_allowedip == NULL)
|
||||
peer->first_allowedip = aip;
|
||||
else
|
||||
peer->last_allowedip->next_allowedip = aip;
|
||||
peer->last_allowedip = aip;
|
||||
|
||||
aip->family = wg_aip->a_af;
|
||||
if (wg_aip->a_af == AF_INET)
|
||||
{
|
||||
memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4));
|
||||
aip->cidr = wg_aip->a_cidr;
|
||||
}
|
||||
else if (wg_aip->a_af == AF_INET6)
|
||||
{
|
||||
memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6));
|
||||
aip->cidr = wg_aip->a_cidr;
|
||||
}
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer = (struct wg_peer_io*)wg_aip;
|
||||
}
|
||||
*device = dev;
|
||||
errno = 0;
|
||||
out:
|
||||
ret = -errno;
|
||||
free(wgdata.wgd_interface);
|
||||
return ret;
|
||||
ret = -errno;
|
||||
free(wgdata.wgd_interface);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kernel_set_device(struct wgdevice *dev)
|
||||
static int kernel_set_device(struct wgdevice* dev)
|
||||
{
|
||||
struct wg_data_io wgdata = { .wgd_size = sizeof(struct wg_interface_io) };
|
||||
struct wg_interface_io *wg_iface;
|
||||
struct wg_peer_io *wg_peer;
|
||||
struct wg_aip_io *wg_aip;
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *aip;
|
||||
int s = get_dgram_socket(), ret;
|
||||
size_t peer_count, aip_count;
|
||||
struct wg_data_io wgdata = {.wgd_size = sizeof(struct wg_interface_io)};
|
||||
struct wg_interface_io* wg_iface;
|
||||
struct wg_peer_io* wg_peer;
|
||||
struct wg_aip_io* wg_aip;
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* aip;
|
||||
int s = get_dgram_socket(), ret;
|
||||
size_t peer_count, aip_count;
|
||||
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
for_each_wgpeer(dev, peer) {
|
||||
wgdata.wgd_size += sizeof(struct wg_peer_io);
|
||||
for_each_wgallowedip(peer, aip)
|
||||
wgdata.wgd_size += sizeof(struct wg_aip_io);
|
||||
}
|
||||
wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size);
|
||||
if (!wgdata.wgd_interface)
|
||||
return -errno;
|
||||
strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name));
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
wgdata.wgd_size += sizeof(struct wg_peer_io);
|
||||
for_each_wgallowedip(peer, aip) wgdata.wgd_size += sizeof(struct wg_aip_io);
|
||||
}
|
||||
wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size);
|
||||
if (!wgdata.wgd_interface)
|
||||
return -errno;
|
||||
strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name));
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
|
||||
memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private));
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
{
|
||||
memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private));
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) {
|
||||
wg_iface->i_port = dev->listen_port;
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_PORT;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
{
|
||||
wg_iface->i_port = dev->listen_port;
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_PORT;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK) {
|
||||
wg_iface->i_rtable = dev->fwmark;
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
{
|
||||
wg_iface->i_rtable = dev->fwmark;
|
||||
wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS;
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS;
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
{
|
||||
wg_iface->i_junk_packet_count = dev->junk_packet_count;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JC) {
|
||||
wg_iface->i_junk_packet_count = dev->junk_packet_count;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
{
|
||||
wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN) {
|
||||
wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
{
|
||||
wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX) {
|
||||
wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
{
|
||||
wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_S1) {
|
||||
wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
{
|
||||
wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_S2) {
|
||||
wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
{
|
||||
wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H1) {
|
||||
wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
{
|
||||
wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H2) {
|
||||
wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
{
|
||||
wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H3) {
|
||||
wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
{
|
||||
wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H4;
|
||||
}
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_H4) {
|
||||
wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H4;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_I1)
|
||||
{
|
||||
wg_iface->i_i1 = strdup(dev->i1);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I1;
|
||||
}
|
||||
|
||||
peer_count = 0;
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for_each_wgpeer(dev, peer) {
|
||||
wg_peer->p_flags = WG_PEER_HAS_PUBLIC;
|
||||
memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public));
|
||||
if (dev->flags & WGDEVICE_HAS_I2)
|
||||
{
|
||||
wg_iface->i_i2 = strdup(dev->i2);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I2;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
|
||||
memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk));
|
||||
wg_peer->p_flags |= WG_PEER_HAS_PSK;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_I3)
|
||||
{
|
||||
wg_iface->i_i3 = strdup(dev->i3);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I3;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) {
|
||||
wg_peer->p_pka = peer->persistent_keepalive_interval;
|
||||
wg_peer->p_flags |= WG_PEER_HAS_PKA;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_I4)
|
||||
{
|
||||
wg_iface->i_i4 = strdup(dev->i4);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I4;
|
||||
}
|
||||
|
||||
if ((peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) &&
|
||||
peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint)) {
|
||||
memcpy(&wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len);
|
||||
wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT;
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_I5)
|
||||
{
|
||||
wg_iface->i_i5 = strdup(dev->i5);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I5;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
wg_peer->p_flags |= WG_PEER_REPLACE_AIPS;
|
||||
if (dev->flags & WGDEVICE_HAS_J1)
|
||||
{
|
||||
wg_iface->i_j1 = strdup(dev->j1);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J1;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
wg_peer->p_flags |= WG_PEER_REMOVE;
|
||||
if (dev->flags & WGDEVICE_HAS_J2)
|
||||
{
|
||||
wg_iface->i_j2 = strdup(dev->j2);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J2;
|
||||
}
|
||||
|
||||
aip_count = 0;
|
||||
wg_aip = &wg_peer->p_aips[0];
|
||||
for_each_wgallowedip(peer, aip) {
|
||||
wg_aip->a_af = aip->family;
|
||||
wg_aip->a_cidr = aip->cidr;
|
||||
if (dev->flags & WGDEVICE_HAS_J3)
|
||||
{
|
||||
wg_iface->i_j3 = strdup(dev->j3);
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J3;
|
||||
}
|
||||
|
||||
if (aip->family == AF_INET)
|
||||
memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(wg_aip->a_ipv4));
|
||||
else if (aip->family == AF_INET6)
|
||||
memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(wg_aip->a_ipv6));
|
||||
else
|
||||
continue;
|
||||
++aip_count;
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer->p_aips_count = aip_count;
|
||||
++peer_count;
|
||||
wg_peer = (struct wg_peer_io *)wg_aip;
|
||||
}
|
||||
wg_iface->i_peers_count = peer_count;
|
||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
{
|
||||
wg_iface->i_itime = dev->itime;
|
||||
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_ITIME;
|
||||
}
|
||||
|
||||
if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) < 0)
|
||||
goto out;
|
||||
errno = 0;
|
||||
peer_count = 0;
|
||||
wg_peer = &wg_iface->i_peers[0];
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
wg_peer->p_flags = WG_PEER_HAS_PUBLIC;
|
||||
memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public));
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk));
|
||||
wg_peer->p_flags |= WG_PEER_HAS_PSK;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
{
|
||||
wg_peer->p_pka = peer->persistent_keepalive_interval;
|
||||
wg_peer->p_flags |= WG_PEER_HAS_PKA;
|
||||
}
|
||||
|
||||
if ((peer->endpoint.addr.sa_family == AF_INET ||
|
||||
peer->endpoint.addr.sa_family == AF_INET6) &&
|
||||
peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint))
|
||||
{
|
||||
memcpy(
|
||||
&wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len);
|
||||
wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT;
|
||||
}
|
||||
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
wg_peer->p_flags |= WG_PEER_REPLACE_AIPS;
|
||||
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
wg_peer->p_flags |= WG_PEER_REMOVE;
|
||||
|
||||
aip_count = 0;
|
||||
wg_aip = &wg_peer->p_aips[0];
|
||||
for_each_wgallowedip(peer, aip)
|
||||
{
|
||||
wg_aip->a_af = aip->family;
|
||||
wg_aip->a_cidr = aip->cidr;
|
||||
|
||||
if (aip->family == AF_INET)
|
||||
memcpy(&wg_aip->a_ipv4, &aip->ip4, sizeof(wg_aip->a_ipv4));
|
||||
else if (aip->family == AF_INET6)
|
||||
memcpy(&wg_aip->a_ipv6, &aip->ip6, sizeof(wg_aip->a_ipv6));
|
||||
else
|
||||
continue;
|
||||
++aip_count;
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer->p_aips_count = aip_count;
|
||||
++peer_count;
|
||||
wg_peer = (struct wg_peer_io*)wg_aip;
|
||||
}
|
||||
wg_iface->i_peers_count = peer_count;
|
||||
|
||||
if (ioctl(s, SIOCSWG, (caddr_t)&wgdata) < 0)
|
||||
goto out;
|
||||
errno = 0;
|
||||
|
||||
out:
|
||||
ret = -errno;
|
||||
free(wgdata.wgd_interface);
|
||||
return ret;
|
||||
ret = -errno;
|
||||
free(wgdata.wgd_interface);
|
||||
return ret;
|
||||
}
|
||||
|
|
740
src/ipc-uapi.h
740
src/ipc-uapi.h
|
@ -3,6 +3,10 @@
|
|||
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "containers.h"
|
||||
#include "ctype.h"
|
||||
#include "curve25519.h"
|
||||
#include "encoding.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
@ -14,10 +18,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include "containers.h"
|
||||
#include "curve25519.h"
|
||||
#include "encoding.h"
|
||||
#include "ctype.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "ipc-uapi-windows.h"
|
||||
|
@ -25,322 +25,460 @@
|
|||
#include "ipc-uapi-unix.h"
|
||||
#endif
|
||||
|
||||
static int userspace_set_device(struct wgdevice *dev)
|
||||
static int userspace_set_device(struct wgdevice* dev)
|
||||
{
|
||||
char hex[WG_KEY_LEN_HEX], ip[INET6_ADDRSTRLEN], host[4096 + 1], service[512 + 1];
|
||||
struct wgpeer *peer;
|
||||
struct wgallowedip *allowedip;
|
||||
FILE *f;
|
||||
int ret, set_errno = -EPROTO;
|
||||
socklen_t addr_len;
|
||||
size_t line_buffer_len = 0, line_len;
|
||||
char *key = NULL, *value;
|
||||
char hex[WG_KEY_LEN_HEX], ip[INET6_ADDRSTRLEN], host[4096 + 1], service[512 + 1];
|
||||
struct wgpeer* peer;
|
||||
struct wgallowedip* allowedip;
|
||||
FILE* f;
|
||||
int ret, set_errno = -EPROTO;
|
||||
socklen_t addr_len;
|
||||
size_t line_buffer_len = 0, line_len;
|
||||
char * key = NULL, *value;
|
||||
|
||||
f = userspace_interface_file(dev->name);
|
||||
if (!f)
|
||||
return -errno;
|
||||
fprintf(f, "set=1\n");
|
||||
f = userspace_interface_file(dev->name);
|
||||
if (!f)
|
||||
return -errno;
|
||||
fprintf(f, "set=1\n");
|
||||
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
|
||||
key_to_hex(hex, dev->private_key);
|
||||
fprintf(f, "private_key=%s\n", hex);
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
fprintf(f, "listen_port=%u\n", dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
fprintf(f, "fwmark=%u\n", dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
fprintf(f, "replace_peers=true\n");
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
fprintf(f, "jc=%u\n", dev->junk_packet_count);
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
fprintf(f, "jmin=%u\n", dev->junk_packet_min_size);
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
fprintf(f, "jmax=%u\n", dev->junk_packet_max_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
fprintf(f, "s1=%u\n", dev->init_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
fprintf(f, "s2=%u\n", dev->response_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
fprintf(f, "h1=%u\n", dev->init_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
fprintf(f, "h2=%u\n", dev->response_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
fprintf(f, "h3=%u\n", dev->underload_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
fprintf(f, "h4=%u\n", dev->transport_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
|
||||
{
|
||||
key_to_hex(hex, dev->private_key);
|
||||
fprintf(f, "private_key=%s\n", hex);
|
||||
}
|
||||
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
|
||||
fprintf(f, "listen_port=%u\n", dev->listen_port);
|
||||
if (dev->flags & WGDEVICE_HAS_FWMARK)
|
||||
fprintf(f, "fwmark=%u\n", dev->fwmark);
|
||||
if (dev->flags & WGDEVICE_REPLACE_PEERS)
|
||||
fprintf(f, "replace_peers=true\n");
|
||||
if (dev->flags & WGDEVICE_HAS_JC)
|
||||
fprintf(f, "jc=%u\n", dev->junk_packet_count);
|
||||
if (dev->flags & WGDEVICE_HAS_JMIN)
|
||||
fprintf(f, "jmin=%u\n", dev->junk_packet_min_size);
|
||||
if (dev->flags & WGDEVICE_HAS_JMAX)
|
||||
fprintf(f, "jmax=%u\n", dev->junk_packet_max_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S1)
|
||||
fprintf(f, "s1=%u\n", dev->init_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_S2)
|
||||
fprintf(f, "s2=%u\n", dev->response_packet_junk_size);
|
||||
if (dev->flags & WGDEVICE_HAS_H1)
|
||||
fprintf(f, "h1=%u\n", dev->init_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H2)
|
||||
fprintf(f, "h2=%u\n", dev->response_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H3)
|
||||
fprintf(f, "h3=%u\n", dev->underload_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_H4)
|
||||
fprintf(f, "h4=%u\n", dev->transport_packet_magic_header);
|
||||
if (dev->flags & WGDEVICE_HAS_I1)
|
||||
fprintf(f, "i1=%s\n", dev->i1);
|
||||
if (dev->flags & WGDEVICE_HAS_I2)
|
||||
fprintf(f, "i2=%s\n", dev->i2);
|
||||
if (dev->flags & WGDEVICE_HAS_I3)
|
||||
fprintf(f, "i3=%s\n", dev->i3);
|
||||
if (dev->flags & WGDEVICE_HAS_I4)
|
||||
fprintf(f, "i4=%s\n", dev->i4);
|
||||
if (dev->flags & WGDEVICE_HAS_I5)
|
||||
fprintf(f, "i5=%s\n", dev->i5);
|
||||
if (dev->flags & WGDEVICE_HAS_J1)
|
||||
fprintf(f, "j1=%s\n", dev->j1);
|
||||
if (dev->flags & WGDEVICE_HAS_J2)
|
||||
fprintf(f, "j2=%s\n", dev->j2);
|
||||
if (dev->flags & WGDEVICE_HAS_J3)
|
||||
fprintf(f, "j3=%s\n", dev->j3);
|
||||
if (dev->flags & WGDEVICE_HAS_ITIME)
|
||||
fprintf(f, "itime=%u\n", dev->itime);
|
||||
|
||||
for_each_wgpeer(dev, peer) {
|
||||
key_to_hex(hex, peer->public_key);
|
||||
fprintf(f, "public_key=%s\n", hex);
|
||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (peer->flags & WGPEER_REMOVE_ME) {
|
||||
fprintf(f, "remove=true\n");
|
||||
continue;
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) {
|
||||
key_to_hex(hex, peer->preshared_key);
|
||||
fprintf(f, "preshared_key=%s\n", hex);
|
||||
}
|
||||
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) {
|
||||
addr_len = 0;
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
if (!getnameinfo(&peer->endpoint.addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
|
||||
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':'))
|
||||
fprintf(f, "endpoint=[%s]:%s\n", host, service);
|
||||
else
|
||||
fprintf(f, "endpoint=%s:%s\n", host, service);
|
||||
}
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
fprintf(f, "persistent_keepalive_interval=%u\n", peer->persistent_keepalive_interval);
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
fprintf(f, "replace_allowed_ips=true\n");
|
||||
for_each_wgallowedip(peer, allowedip) {
|
||||
if (allowedip->family == AF_INET) {
|
||||
if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN))
|
||||
continue;
|
||||
} else if (allowedip->family == AF_INET6) {
|
||||
if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN))
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
fflush(f);
|
||||
for_each_wgpeer(dev, peer)
|
||||
{
|
||||
key_to_hex(hex, peer->public_key);
|
||||
fprintf(f, "public_key=%s\n", hex);
|
||||
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (peer->flags & WGPEER_REMOVE_ME)
|
||||
{
|
||||
fprintf(f, "remove=true\n");
|
||||
continue;
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
|
||||
{
|
||||
key_to_hex(hex, peer->preshared_key);
|
||||
fprintf(f, "preshared_key=%s\n", hex);
|
||||
}
|
||||
if (peer->endpoint.addr.sa_family == AF_INET ||
|
||||
peer->endpoint.addr.sa_family == AF_INET6)
|
||||
{
|
||||
addr_len = 0;
|
||||
if (peer->endpoint.addr.sa_family == AF_INET)
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
else if (peer->endpoint.addr.sa_family == AF_INET6)
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
if (!getnameinfo(
|
||||
&peer->endpoint.addr,
|
||||
addr_len,
|
||||
host,
|
||||
sizeof(host),
|
||||
service,
|
||||
sizeof(service),
|
||||
NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST))
|
||||
{
|
||||
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':'))
|
||||
fprintf(f, "endpoint=[%s]:%s\n", host, service);
|
||||
else
|
||||
fprintf(f, "endpoint=%s:%s\n", host, service);
|
||||
}
|
||||
}
|
||||
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
|
||||
fprintf(
|
||||
f,
|
||||
"persistent_keepalive_interval=%u\n",
|
||||
peer->persistent_keepalive_interval);
|
||||
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
|
||||
fprintf(f, "replace_allowed_ips=true\n");
|
||||
for_each_wgallowedip(peer, allowedip)
|
||||
{
|
||||
if (allowedip->family == AF_INET)
|
||||
{
|
||||
if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN))
|
||||
continue;
|
||||
}
|
||||
else if (allowedip->family == AF_INET6)
|
||||
{
|
||||
if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
fflush(f);
|
||||
|
||||
while (getline(&key, &line_buffer_len, f) > 0) {
|
||||
line_len = strlen(key);
|
||||
ret = set_errno;
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
goto out;
|
||||
value = strchr(key, '=');
|
||||
if (!value || line_len == 0 || key[line_len - 1] != '\n')
|
||||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
while (getline(&key, &line_buffer_len, f) > 0)
|
||||
{
|
||||
line_len = strlen(key);
|
||||
ret = set_errno;
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
goto out;
|
||||
value = strchr(key, '=');
|
||||
if (!value || line_len == 0 || key[line_len - 1] != '\n')
|
||||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
|
||||
if (!strcmp(key, "errno")) {
|
||||
long long num;
|
||||
char *end;
|
||||
if (value[0] != '-' && !char_is_digit(value[0]))
|
||||
break;
|
||||
num = strtoll(value, &end, 10);
|
||||
if (*end || num > INT_MAX || num < INT_MIN)
|
||||
break;
|
||||
set_errno = num;
|
||||
}
|
||||
}
|
||||
ret = errno ? -errno : -EPROTO;
|
||||
if (!strcmp(key, "errno"))
|
||||
{
|
||||
long long num;
|
||||
char* end;
|
||||
if (value[0] != '-' && !char_is_digit(value[0]))
|
||||
break;
|
||||
num = strtoll(value, &end, 10);
|
||||
if (*end || num > INT_MAX || num < INT_MIN)
|
||||
break;
|
||||
set_errno = num;
|
||||
}
|
||||
}
|
||||
ret = errno ? -errno : -EPROTO;
|
||||
out:
|
||||
free(key);
|
||||
fclose(f);
|
||||
errno = -ret;
|
||||
return ret;
|
||||
free(key);
|
||||
fclose(f);
|
||||
errno = -ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NUM(max) ({ \
|
||||
unsigned long long num; \
|
||||
char *end; \
|
||||
if (!char_is_digit(value[0])) \
|
||||
break; \
|
||||
num = strtoull(value, &end, 10); \
|
||||
if (*end || num > max) \
|
||||
break; \
|
||||
num; \
|
||||
})
|
||||
#define NUM(max) \
|
||||
({ \
|
||||
unsigned long long num; \
|
||||
char* end; \
|
||||
if (!char_is_digit(value[0])) \
|
||||
break; \
|
||||
num = strtoull(value, &end, 10); \
|
||||
if (*end || num > max) \
|
||||
break; \
|
||||
num; \
|
||||
})
|
||||
|
||||
static int userspace_get_device(struct wgdevice **out, const char *iface)
|
||||
static int userspace_get_device(struct wgdevice** out, const char* iface)
|
||||
{
|
||||
struct wgdevice *dev;
|
||||
struct wgpeer *peer = NULL;
|
||||
struct wgallowedip *allowedip = NULL;
|
||||
size_t line_buffer_len = 0, line_len;
|
||||
char *key = NULL, *value;
|
||||
FILE *f;
|
||||
int ret = -EPROTO;
|
||||
struct wgdevice* dev;
|
||||
struct wgpeer* peer = NULL;
|
||||
struct wgallowedip* allowedip = NULL;
|
||||
size_t line_buffer_len = 0, line_len;
|
||||
char * key = NULL, *value;
|
||||
FILE* f;
|
||||
int ret = -EPROTO;
|
||||
|
||||
*out = dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
return -errno;
|
||||
*out = dev = calloc(1, sizeof(*dev));
|
||||
if (!dev)
|
||||
return -errno;
|
||||
|
||||
f = userspace_interface_file(iface);
|
||||
if (!f) {
|
||||
ret = -errno;
|
||||
free(dev);
|
||||
*out = NULL;
|
||||
return ret;
|
||||
}
|
||||
f = userspace_interface_file(iface);
|
||||
if (!f)
|
||||
{
|
||||
ret = -errno;
|
||||
free(dev);
|
||||
*out = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
fprintf(f, "get=1\n\n");
|
||||
fflush(f);
|
||||
fprintf(f, "get=1\n\n");
|
||||
fflush(f);
|
||||
|
||||
strncpy(dev->name, iface, IFNAMSIZ - 1);
|
||||
dev->name[IFNAMSIZ - 1] = '\0';
|
||||
strncpy(dev->name, iface, IFNAMSIZ - 1);
|
||||
dev->name[IFNAMSIZ - 1] = '\0';
|
||||
|
||||
while (getline(&key, &line_buffer_len, f) > 0) {
|
||||
line_len = strlen(key);
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
goto err;
|
||||
value = strchr(key, '=');
|
||||
if (!value || line_len == 0 || key[line_len - 1] != '\n')
|
||||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
while (getline(&key, &line_buffer_len, f) > 0)
|
||||
{
|
||||
line_len = strlen(key);
|
||||
if (line_len == 1 && key[0] == '\n')
|
||||
goto err;
|
||||
value = strchr(key, '=');
|
||||
if (!value || line_len == 0 || key[line_len - 1] != '\n')
|
||||
break;
|
||||
*value++ = key[--line_len] = '\0';
|
||||
|
||||
if (!peer && !strcmp(key, "private_key")) {
|
||||
if (!key_from_hex(dev->private_key, value))
|
||||
break;
|
||||
curve25519_generate_public(dev->public_key, dev->private_key);
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY;
|
||||
} else if (!peer && !strcmp(key, "listen_port")) {
|
||||
dev->listen_port = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
} else if (!peer && !strcmp(key, "fwmark")) {
|
||||
dev->fwmark = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
} else if(!peer && !strcmp(key, "jc")) {
|
||||
dev->junk_packet_count = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
} else if(!peer && !strcmp(key, "jmin")) {
|
||||
dev->junk_packet_min_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
} else if(!peer && !strcmp(key, "jmax")) {
|
||||
dev->junk_packet_max_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
} else if(!peer && !strcmp(key, "s1")) {
|
||||
dev->init_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
} else if(!peer && !strcmp(key, "s2")) {
|
||||
dev->response_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
} else if(!peer && !strcmp(key, "h1")) {
|
||||
dev->init_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
} else if(!peer && !strcmp(key, "h2")) {
|
||||
dev->response_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
} else if(!peer && !strcmp(key, "h3")) {
|
||||
dev->underload_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
} else if(!peer && !strcmp(key, "h4")) {
|
||||
dev->transport_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
} else if (!strcmp(key, "public_key")) {
|
||||
struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
|
||||
if (!peer && !strcmp(key, "private_key"))
|
||||
{
|
||||
if (!key_from_hex(dev->private_key, value))
|
||||
break;
|
||||
curve25519_generate_public(dev->public_key, dev->private_key);
|
||||
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "listen_port"))
|
||||
{
|
||||
dev->listen_port = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "fwmark"))
|
||||
{
|
||||
dev->fwmark = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_FWMARK;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jc"))
|
||||
{
|
||||
dev->junk_packet_count = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JC;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jmin"))
|
||||
{
|
||||
dev->junk_packet_min_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMIN;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "jmax"))
|
||||
{
|
||||
dev->junk_packet_max_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_JMAX;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "s1"))
|
||||
{
|
||||
dev->init_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "s2"))
|
||||
{
|
||||
dev->response_packet_junk_size = NUM(0xffffU);
|
||||
dev->flags |= WGDEVICE_HAS_S2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h1"))
|
||||
{
|
||||
dev->init_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h2"))
|
||||
{
|
||||
dev->response_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h3"))
|
||||
{
|
||||
dev->underload_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "h4"))
|
||||
{
|
||||
dev->transport_packet_magic_header = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_H4;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i1"))
|
||||
{
|
||||
dev->i1 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i2"))
|
||||
{
|
||||
dev->i2 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i3"))
|
||||
{
|
||||
dev->i3 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i4"))
|
||||
{
|
||||
dev->i4 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I4;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "i5"))
|
||||
{
|
||||
dev->i5 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_I5;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j1"))
|
||||
{
|
||||
dev->j1 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J1;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j2"))
|
||||
{
|
||||
dev->j2 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J2;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "j3"))
|
||||
{
|
||||
dev->j3 = strdup(value);
|
||||
dev->flags |= WGDEVICE_HAS_J3;
|
||||
}
|
||||
else if (!peer && !strcmp(key, "itime"))
|
||||
{
|
||||
dev->itime = NUM(0xffffffffU);
|
||||
dev->flags |= WGDEVICE_HAS_ITIME;
|
||||
}
|
||||
else if (!strcmp(key, "public_key"))
|
||||
{
|
||||
struct wgpeer* new_peer = calloc(1, sizeof(*new_peer));
|
||||
|
||||
if (!new_peer) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
allowedip = NULL;
|
||||
if (peer)
|
||||
peer->next_peer = new_peer;
|
||||
else
|
||||
dev->first_peer = new_peer;
|
||||
peer = new_peer;
|
||||
if (!key_from_hex(peer->public_key, value))
|
||||
break;
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
} else if (peer && !strcmp(key, "preshared_key")) {
|
||||
if (!key_from_hex(peer->preshared_key, value))
|
||||
break;
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
} else if (peer && !strcmp(key, "endpoint")) {
|
||||
char *begin, *end;
|
||||
struct addrinfo *resolved;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_DGRAM,
|
||||
.ai_protocol = IPPROTO_UDP
|
||||
};
|
||||
if (!strlen(value))
|
||||
break;
|
||||
if (value[0] == '[') {
|
||||
begin = &value[1];
|
||||
end = strchr(value, ']');
|
||||
if (!end)
|
||||
break;
|
||||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end)
|
||||
break;
|
||||
} else {
|
||||
begin = value;
|
||||
end = strrchr(value, ':');
|
||||
if (!end || !*(end + 1))
|
||||
break;
|
||||
*end++ = '\0';
|
||||
}
|
||||
if (getaddrinfo(begin, end, &hints, &resolved) != 0) {
|
||||
ret = ENETUNREACH;
|
||||
goto err;
|
||||
}
|
||||
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) ||
|
||||
(resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6)))
|
||||
memcpy(&peer->endpoint.addr, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else {
|
||||
freeaddrinfo(resolved);
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
} else if (peer && !strcmp(key, "persistent_keepalive_interval")) {
|
||||
peer->persistent_keepalive_interval = NUM(0xffffU);
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
} else if (peer && !strcmp(key, "allowed_ip")) {
|
||||
struct wgallowedip *new_allowedip;
|
||||
char *end, *mask = value, *ip = strsep(&mask, "/");
|
||||
if (!new_peer)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
allowedip = NULL;
|
||||
if (peer)
|
||||
peer->next_peer = new_peer;
|
||||
else
|
||||
dev->first_peer = new_peer;
|
||||
peer = new_peer;
|
||||
if (!key_from_hex(peer->public_key, value))
|
||||
break;
|
||||
peer->flags |= WGPEER_HAS_PUBLIC_KEY;
|
||||
}
|
||||
else if (peer && !strcmp(key, "preshared_key"))
|
||||
{
|
||||
if (!key_from_hex(peer->preshared_key, value))
|
||||
break;
|
||||
if (!key_is_zero(peer->preshared_key))
|
||||
peer->flags |= WGPEER_HAS_PRESHARED_KEY;
|
||||
}
|
||||
else if (peer && !strcmp(key, "endpoint"))
|
||||
{
|
||||
char * begin, *end;
|
||||
struct addrinfo* resolved;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_DGRAM,
|
||||
.ai_protocol = IPPROTO_UDP};
|
||||
if (!strlen(value))
|
||||
break;
|
||||
if (value[0] == '[')
|
||||
{
|
||||
begin = &value[1];
|
||||
end = strchr(value, ']');
|
||||
if (!end)
|
||||
break;
|
||||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin = value;
|
||||
end = strrchr(value, ':');
|
||||
if (!end || !*(end + 1))
|
||||
break;
|
||||
*end++ = '\0';
|
||||
}
|
||||
if (getaddrinfo(begin, end, &hints, &resolved) != 0)
|
||||
{
|
||||
ret = ENETUNREACH;
|
||||
goto err;
|
||||
}
|
||||
if ((resolved->ai_family == AF_INET &&
|
||||
resolved->ai_addrlen == sizeof(struct sockaddr_in)) ||
|
||||
(resolved->ai_family == AF_INET6 &&
|
||||
resolved->ai_addrlen == sizeof(struct sockaddr_in6)))
|
||||
memcpy(&peer->endpoint.addr, resolved->ai_addr, resolved->ai_addrlen);
|
||||
else
|
||||
{
|
||||
freeaddrinfo(resolved);
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
}
|
||||
else if (peer && !strcmp(key, "persistent_keepalive_interval"))
|
||||
{
|
||||
peer->persistent_keepalive_interval = NUM(0xffffU);
|
||||
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
|
||||
}
|
||||
else if (peer && !strcmp(key, "allowed_ip"))
|
||||
{
|
||||
struct wgallowedip* new_allowedip;
|
||||
char * end, *mask = value, *ip = strsep(&mask, "/");
|
||||
|
||||
if (!mask || !char_is_digit(mask[0]))
|
||||
break;
|
||||
new_allowedip = calloc(1, sizeof(*new_allowedip));
|
||||
if (!new_allowedip) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
if (allowedip)
|
||||
allowedip->next_allowedip = new_allowedip;
|
||||
else
|
||||
peer->first_allowedip = new_allowedip;
|
||||
allowedip = new_allowedip;
|
||||
allowedip->family = AF_UNSPEC;
|
||||
if (strchr(ip, ':')) {
|
||||
if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1)
|
||||
allowedip->family = AF_INET6;
|
||||
} else {
|
||||
if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1)
|
||||
allowedip->family = AF_INET;
|
||||
}
|
||||
allowedip->cidr = strtoul(mask, &end, 10);
|
||||
if (*end || allowedip->family == AF_UNSPEC || (allowedip->family == AF_INET6 && allowedip->cidr > 128) || (allowedip->family == AF_INET && allowedip->cidr > 32))
|
||||
break;
|
||||
} else if (peer && !strcmp(key, "last_handshake_time_sec"))
|
||||
peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "last_handshake_time_nsec"))
|
||||
peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "rx_bytes"))
|
||||
peer->rx_bytes = NUM(0xffffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "tx_bytes"))
|
||||
peer->tx_bytes = NUM(0xffffffffffffffffULL);
|
||||
else if (!strcmp(key, "errno"))
|
||||
ret = -NUM(0x7fffffffU);
|
||||
}
|
||||
ret = -EPROTO;
|
||||
if (!mask || !char_is_digit(mask[0]))
|
||||
break;
|
||||
new_allowedip = calloc(1, sizeof(*new_allowedip));
|
||||
if (!new_allowedip)
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
if (allowedip)
|
||||
allowedip->next_allowedip = new_allowedip;
|
||||
else
|
||||
peer->first_allowedip = new_allowedip;
|
||||
allowedip = new_allowedip;
|
||||
allowedip->family = AF_UNSPEC;
|
||||
if (strchr(ip, ':'))
|
||||
{
|
||||
if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1)
|
||||
allowedip->family = AF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1)
|
||||
allowedip->family = AF_INET;
|
||||
}
|
||||
allowedip->cidr = strtoul(mask, &end, 10);
|
||||
if (*end || allowedip->family == AF_UNSPEC ||
|
||||
(allowedip->family == AF_INET6 && allowedip->cidr > 128) ||
|
||||
(allowedip->family == AF_INET && allowedip->cidr > 32))
|
||||
break;
|
||||
}
|
||||
else if (peer && !strcmp(key, "last_handshake_time_sec"))
|
||||
peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "last_handshake_time_nsec"))
|
||||
peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "rx_bytes"))
|
||||
peer->rx_bytes = NUM(0xffffffffffffffffULL);
|
||||
else if (peer && !strcmp(key, "tx_bytes"))
|
||||
peer->tx_bytes = NUM(0xffffffffffffffffULL);
|
||||
else if (!strcmp(key, "errno"))
|
||||
ret = -NUM(0x7fffffffU);
|
||||
}
|
||||
ret = -EPROTO;
|
||||
err:
|
||||
free(key);
|
||||
if (ret) {
|
||||
free_wgdevice(dev);
|
||||
*out = NULL;
|
||||
}
|
||||
fclose(f);
|
||||
errno = -ret;
|
||||
return ret;
|
||||
|
||||
free(key);
|
||||
if (ret)
|
||||
{
|
||||
free_wgdevice(dev);
|
||||
*out = NULL;
|
||||
}
|
||||
fclose(f);
|
||||
errno = -ret;
|
||||
return ret;
|
||||
}
|
||||
#undef NUM
|
||||
|
|
|
@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
|
|||
int ret = 1;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
|
||||
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [jc <junk_count>] [jmin <min_value>] [jmax <max_value>] [s1 <init_junk>] [s2 <resp_junk>] [h1 <init_header>] [h2 <resp_header>] [h3 <cookie_header>] [h4 <transp_header>] [i1 <taged_junk>] [i2 <taged_junk>] [i3 <taged_junk>] [i4 <taged_junk>] [i5 <taged_junk>] [j1 <taged_junk>] [j2 <taged_junk>] [j3 <taged_junk>] [itime <itimeout>][peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
67
src/show.c
67
src/show.c
|
@ -202,7 +202,7 @@ static char *bytes(uint64_t b)
|
|||
static const char *COMMAND_NAME;
|
||||
static void show_usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | listen-port | fwmark | peers | preshared-keys | endpoints | allowed-ips | latest-handshakes | transfer | persistent-keepalive | dump]\n", PROG_NAME, COMMAND_NAME);
|
||||
fprintf(stderr, "Usage: %s %s { <interface> | all | interfaces } [public-key | private-key | listen-port | fwmark | peers | preshared-keys | endpoints | allowed-ips | latest-handshakes | transfer | persistent-keepalive | dump | jc | jmin | jmax | s1 | s2 | h1 | h2 | h3 | h4 | i1 | i2 | i3 | i4 | i5 | j1 | j2 | j3 | itime]\n", PROG_NAME, COMMAND_NAME);
|
||||
}
|
||||
|
||||
static void pretty_print(struct wgdevice *device)
|
||||
|
@ -238,6 +238,25 @@ static void pretty_print(struct wgdevice *device)
|
|||
terminal_printf(" " TERMINAL_BOLD "h3" TERMINAL_RESET ": %u\n", device->underload_packet_magic_header);
|
||||
if (device->transport_packet_magic_header)
|
||||
terminal_printf(" " TERMINAL_BOLD "h4" TERMINAL_RESET ": %u\n", device->transport_packet_magic_header);
|
||||
if (device->i1)
|
||||
terminal_printf(" " TERMINAL_BOLD "i1" TERMINAL_RESET ": %s\n", device->i1);
|
||||
if (device->i2)
|
||||
terminal_printf(" " TERMINAL_BOLD "i2" TERMINAL_RESET ": %s\n", device->i2);
|
||||
if (device->i3)
|
||||
terminal_printf(" " TERMINAL_BOLD "i3" TERMINAL_RESET ": %s\n", device->i3);
|
||||
if (device->i4)
|
||||
terminal_printf(" " TERMINAL_BOLD "i4" TERMINAL_RESET ": %s\n", device->i4);
|
||||
if (device->i5)
|
||||
terminal_printf(" " TERMINAL_BOLD "i5" TERMINAL_RESET ": %s\n", device->i5);
|
||||
if (device->j1)
|
||||
terminal_printf(" " TERMINAL_BOLD "j1" TERMINAL_RESET ": %s\n", device->j1);
|
||||
if (device->j2)
|
||||
terminal_printf(" " TERMINAL_BOLD "j2" TERMINAL_RESET ": %s\n", device->j2);
|
||||
if (device->j3)
|
||||
terminal_printf(" " TERMINAL_BOLD "j3" TERMINAL_RESET ": %s\n", device->j3);
|
||||
if (device->itime)
|
||||
terminal_printf(" " TERMINAL_BOLD "itime" TERMINAL_RESET ": %d\n", device->itime);
|
||||
|
||||
if (device->first_peer) {
|
||||
sort_peers(device);
|
||||
terminal_printf("\n");
|
||||
|
@ -287,6 +306,16 @@ static void dump_print(struct wgdevice *device, bool with_interface)
|
|||
printf("%u\t", device->response_packet_magic_header);
|
||||
printf("%u\t", device->underload_packet_magic_header);
|
||||
printf("%u\t", device->transport_packet_magic_header);
|
||||
printf("%s\t", device->i1);
|
||||
printf("%s\t", device->i2);
|
||||
printf("%s\t", device->i3);
|
||||
printf("%s\t", device->i4);
|
||||
printf("%s\t", device->i5);
|
||||
printf("%s\t", device->j1);
|
||||
printf("%s\t", device->j2);
|
||||
printf("%s\t", device->j3);
|
||||
printf("%d\t", device->itime);
|
||||
|
||||
if (device->fwmark)
|
||||
printf("0x%x\n", device->fwmark);
|
||||
else
|
||||
|
@ -374,6 +403,42 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
|
|||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%u\n", device->transport_packet_magic_header);
|
||||
} else if(!strcmp(param, "i1")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->i1);
|
||||
} else if(!strcmp(param, "i2")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->i2);
|
||||
} else if(!strcmp(param, "i3")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->i3);
|
||||
} else if(!strcmp(param, "i4")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->i4);
|
||||
} else if(!strcmp(param, "i5")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->i5);
|
||||
} else if(!strcmp(param, "j1")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->j1);
|
||||
} else if(!strcmp(param, "j2")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->j2);
|
||||
} else if(!strcmp(param, "j3")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%s\n", device->j3);
|
||||
} else if(!strcmp(param, "itime")) {
|
||||
if (with_interface)
|
||||
printf("%s\t", device->name);
|
||||
printf("%d\n", device->itime);
|
||||
} else if (!strcmp(param, "endpoints")) {
|
||||
for_each_wgpeer(device, peer) {
|
||||
if (with_interface)
|
||||
|
|
|
@ -64,7 +64,6 @@ int showconf_main(int argc, const char *argv[])
|
|||
printf("H3 = %u\n", device->underload_packet_magic_header);
|
||||
if (device->flags & WGDEVICE_HAS_H4)
|
||||
printf("H4 = %u\n", device->transport_packet_magic_header);
|
||||
|
||||
if (device->flags & WGDEVICE_HAS_I1)
|
||||
printf("I1 = %s\n", device->i1);
|
||||
if (device->flags & WGDEVICE_HAS_I2)
|
||||
|
@ -82,7 +81,7 @@ int showconf_main(int argc, const char *argv[])
|
|||
if (device->flags & WGDEVICE_HAS_J3)
|
||||
printf("J3 = %s\n", device->j3);
|
||||
if (device->flags & WGDEVICE_HAS_ITIME)
|
||||
printf("Itime = %s\n", device->itime);
|
||||
printf("Itime = %d\n", device->itime);
|
||||
|
||||
printf("\n");
|
||||
for_each_wgpeer(device, peer) {
|
||||
|
|
|
@ -1278,6 +1278,24 @@ static void parse_options(char **iface, char **config, unsigned int *mtu, char *
|
|||
is_asecurity_on = true;
|
||||
} else if (!strncasecmp(clean, "H4=", 3) && j > 4) {
|
||||
is_asecurity_on = true;
|
||||
} else if (!strncasecmp(clean, "I1", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "I2", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "I3", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "I4", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "I5", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "J1", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "J2", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "J3", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
} else if (!strncasecmp(clean, "Itime", 3) && j > 4) {
|
||||
is_special_handshake_on = true;
|
||||
}
|
||||
}
|
||||
*config = concat_and_free(*config, "", line);
|
||||
|
@ -1322,4 +1340,4 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue