feat: add special handshake support

This commit is contained in:
Mark Puha 2025-06-13 17:51:33 +02:00
parent 71219488c1
commit 3be9c02b19
11 changed files with 1576 additions and 1011 deletions

View file

@ -11,7 +11,7 @@ while read -r -d $'\t' device; do
if [[ $device != "$last_device" ]]; then if [[ $device != "$last_device" ]]; then
[[ -z $last_device ]] && printf '\n' || printf '%s,\n' "$end" [[ -z $last_device ]] && printf '\n' || printf '%s,\n' "$end"
last_device="$device" 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" printf '\t"%s": {' "$device"
delim=$'\n' delim=$'\n'
[[ $private_key == "(none)" ]] || { printf '%s\t\t"privateKey": "%s"' "$delim" "$private_key"; 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'; } [[ $h2 == "2" ]] || { printf '%s\t\t"h2": %u' "$delim" $(( $h2 )); delim=$',\n'; }
[[ $h3 == "3" ]] || { printf '%s\t\t"h3": %u' "$delim" $(( $h3 )); 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'; } [[ $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'; } [[ $fwmark == "off" ]] || { printf '%s\t\t"fwmark": %u' "$delim" $(( $fwmark )); delim=$',\n'; }
printf '%s\t\t"peers": {' "$delim"; end=$'\n\t\t}\n\t}' printf '%s\t\t"peers": {' "$delim"; end=$'\n\t\t}\n\t}'
delim=$'\n' delim=$'\n'

View file

@ -607,7 +607,7 @@ static bool process_line(struct config_ctx *ctx, const char *line)
if (ret) if (ret)
ctx->device->flags |= WGDEVICE_HAS_J3; ctx->device->flags |= WGDEVICE_HAS_J3;
} else if (key_match("ITIME")) { } else if (key_match("ITIME")) {
ret = parse_string(&ctx->device->itime, "Itime", value); ret = parse_uint32(&ctx->device->itime, "Itime", value);
if (ret) if (ret)
ctx->device->flags |= WGDEVICE_HAS_ITIME; ctx->device->flags |= WGDEVICE_HAS_ITIME;
} else } else
@ -872,7 +872,7 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
argv += 2; argv += 2;
argc -=2; argc -=2;
} else if (!strcmp(argv[0], "itime") && argc >= 2 && !peer) { } 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; goto error;
device->flags |= WGDEVICE_HAS_ITIME; device->flags |= WGDEVICE_HAS_ITIME;

View file

@ -139,7 +139,7 @@ struct wgdevice
char* j1; char* j1;
char* j2; char* j2;
char* j3; char* j3;
char* itime; uint32_t itime;
}; };
#define for_each_wgpeer(__dev, __peer) \ #define for_each_wgpeer(__dev, __peer) \

View file

@ -5,9 +5,9 @@
*/ */
#include <assert.h> #include <assert.h>
#include <dev/wg/if_wg.h>
#include <sys/nv.h> #include <sys/nv.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <dev/wg/if_wg.h>
#define IPC_SUPPORTS_KERNEL_INTERFACE #define IPC_SUPPORTS_KERNEL_INTERFACE
@ -19,10 +19,10 @@ static int get_dgram_socket(void)
return sock; 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 ifgroupreq ifgr = {.ifgr_name = "wg"};
struct ifg_req *ifg; struct ifg_req* ifg;
int s = get_dgram_socket(), ret = 0; int s = get_dgram_socket(), ret = 0;
if (s < 0) if (s < 0)
@ -34,12 +34,14 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
if (!ifgr.ifgr_groups) if (!ifgr.ifgr_groups)
return -errno; return -errno;
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) { if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
{
ret = -errno; ret = -errno;
goto out; goto out;
} }
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) { for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
{
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
goto out; goto out;
ifgr.ifgr_len -= sizeof(struct ifg_req); ifgr.ifgr_len -= sizeof(struct ifg_req);
@ -50,15 +52,15 @@ out:
return ret; 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 }; struct wg_data_io wgd = {0};
nvlist_t *nvl_device = NULL; nvlist_t* nvl_device = NULL;
const nvlist_t *const *nvl_peers; const nvlist_t* const* nvl_peers;
struct wgdevice *dev = NULL; struct wgdevice* dev = NULL;
size_t size, peer_count, i; size_t size, peer_count, i;
uint64_t number; uint64_t number;
const void *binary; const void* binary;
int ret = 0, s; int ret = 0, s;
*device = NULL; *device = NULL;
@ -84,94 +86,201 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
if (!nvl_device) if (!nvl_device)
goto err; goto err;
if (nvlist_exists_number(nvl_device, "listen-port")) { if (nvlist_exists_number(nvl_device, "listen-port"))
{
number = nvlist_get_number(nvl_device, "listen-port"); number = nvlist_get_number(nvl_device, "listen-port");
if (number <= UINT16_MAX) { if (number <= UINT16_MAX)
{
dev->listen_port = number; dev->listen_port = number;
dev->flags |= WGDEVICE_HAS_LISTEN_PORT; dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
} }
} }
if (nvlist_exists_number(nvl_device, "jc")) { if (nvlist_exists_number(nvl_device, "jc"))
{
number = nvlist_get_number(nvl_device, "jc"); number = nvlist_get_number(nvl_device, "jc");
if (number <= UINT16_MAX){ if (number <= UINT16_MAX)
{
dev->junk_packet_count = number; dev->junk_packet_count = number;
dev->flags |= WGDEVICE_HAS_JC; dev->flags |= WGDEVICE_HAS_JC;
} }
} }
if (nvlist_exists_number(nvl_device, "jmin")) { if (nvlist_exists_number(nvl_device, "jmin"))
{
number = nvlist_get_number(nvl_device, "jmin"); number = nvlist_get_number(nvl_device, "jmin");
if (number <= UINT16_MAX){ if (number <= UINT16_MAX)
{
dev->junk_packet_min_size = number; dev->junk_packet_min_size = number;
dev->flags |= WGDEVICE_HAS_JMIN; dev->flags |= WGDEVICE_HAS_JMIN;
} }
} }
if (nvlist_exists_number(nvl_device, "jmax")) { if (nvlist_exists_number(nvl_device, "jmax"))
{
number = nvlist_get_number(nvl_device, "jmax"); number = nvlist_get_number(nvl_device, "jmax");
if (number <= UINT16_MAX){ if (number <= UINT16_MAX)
{
dev->junk_packet_max_size = number; dev->junk_packet_max_size = number;
dev->flags |= WGDEVICE_HAS_JMAX; dev->flags |= WGDEVICE_HAS_JMAX;
} }
} }
if (nvlist_exists_number(nvl_device, "s1")) { if (nvlist_exists_number(nvl_device, "s1"))
{
number = nvlist_get_number(nvl_device, "s1"); number = nvlist_get_number(nvl_device, "s1");
if (number <= UINT16_MAX){ if (number <= UINT16_MAX)
{
dev->init_packet_junk_size = number; dev->init_packet_junk_size = number;
dev->flags |= WGDEVICE_HAS_S1; dev->flags |= WGDEVICE_HAS_S1;
} }
} }
if (nvlist_exists_number(nvl_device, "s2")) { if (nvlist_exists_number(nvl_device, "s2"))
{
number = nvlist_get_number(nvl_device, "s2"); number = nvlist_get_number(nvl_device, "s2");
if (number <= UINT16_MAX){ if (number <= UINT16_MAX)
{
dev->response_packet_junk_size = number; dev->response_packet_junk_size = number;
dev->flags |= WGDEVICE_HAS_S2; dev->flags |= WGDEVICE_HAS_S2;
} }
} }
if (nvlist_exists_number(nvl_device, "h1")) { if (nvlist_exists_number(nvl_device, "h1"))
{
number = nvlist_get_number(nvl_device, "h1"); number = nvlist_get_number(nvl_device, "h1");
if (number <= UINT32_MAX){ if (number <= UINT32_MAX)
{
dev->init_packet_magic_header = number; dev->init_packet_magic_header = number;
dev->flags |= WGDEVICE_HAS_H1; dev->flags |= WGDEVICE_HAS_H1;
} }
} }
if (nvlist_exists_number(nvl_device, "h2")) { if (nvlist_exists_number(nvl_device, "h2"))
{
number = nvlist_get_number(nvl_device, "h2"); number = nvlist_get_number(nvl_device, "h2");
if (number <= UINT32_MAX){ if (number <= UINT32_MAX)
{
dev->response_packet_magic_header = number; dev->response_packet_magic_header = number;
dev->flags |= WGDEVICE_HAS_H2; dev->flags |= WGDEVICE_HAS_H2;
} }
} }
if (nvlist_exists_number(nvl_device, "h3")) { if (nvlist_exists_number(nvl_device, "h3"))
{
number = nvlist_get_number(nvl_device, "h3"); number = nvlist_get_number(nvl_device, "h3");
if (number <= UINT32_MAX){ if (number <= UINT32_MAX)
{
dev->underload_packet_magic_header = number; dev->underload_packet_magic_header = number;
dev->flags |= WGDEVICE_HAS_H3; dev->flags |= WGDEVICE_HAS_H3;
} }
} }
if (nvlist_exists_number(nvl_device, "h4")) { if (nvlist_exists_number(nvl_device, "h4"))
{
number = nvlist_get_number(nvl_device, "h4"); number = nvlist_get_number(nvl_device, "h4");
if (number <= UINT32_MAX){ if (number <= UINT32_MAX)
{
dev->transport_packet_magic_header = number; dev->transport_packet_magic_header = number;
dev->flags |= WGDEVICE_HAS_H4; 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")) { if (nvlist_exists_number(nvl_device, "user-cookie"))
{
number = nvlist_get_number(nvl_device, "user-cookie"); number = nvlist_get_number(nvl_device, "user-cookie");
if (number <= UINT32_MAX) { if (number <= UINT32_MAX)
{
dev->fwmark = number; dev->fwmark = number;
dev->flags |= WGDEVICE_HAS_FWMARK; dev->flags |= WGDEVICE_HAS_FWMARK;
} }
} }
if (nvlist_exists_binary(nvl_device, "public-key")) { if (nvlist_exists_binary(nvl_device, "public-key"))
{
binary = nvlist_get_binary(nvl_device, "public-key", &size); binary = nvlist_get_binary(nvl_device, "public-key", &size);
if (binary && size == sizeof(dev->public_key)) { if (binary && size == sizeof(dev->public_key))
{
memcpy(dev->public_key, binary, sizeof(dev->public_key)); memcpy(dev->public_key, binary, sizeof(dev->public_key));
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
} }
} }
if (nvlist_exists_binary(nvl_device, "private-key")) { if (nvlist_exists_binary(nvl_device, "private-key"))
{
binary = nvlist_get_binary(nvl_device, "private-key", &size); binary = nvlist_get_binary(nvl_device, "private-key", &size);
if (binary && size == sizeof(dev->private_key)) { if (binary && size == sizeof(dev->private_key))
{
memcpy(dev->private_key, binary, sizeof(dev->private_key)); memcpy(dev->private_key, binary, sizeof(dev->private_key));
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
} }
@ -181,40 +290,50 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count); nvl_peers = nvlist_get_nvlist_array(nvl_device, "peers", &peer_count);
if (!nvl_peers) if (!nvl_peers)
goto skip_peers; goto skip_peers;
for (i = 0; i < peer_count; ++i) { for (i = 0; i < peer_count; ++i)
struct wgpeer *peer; {
struct wgallowedip *aip = NULL; struct wgpeer* peer;
const nvlist_t *const *nvl_aips; struct wgallowedip* aip = NULL;
const nvlist_t* const* nvl_aips;
size_t aip_count, j; size_t aip_count, j;
peer = calloc(1, sizeof(*peer)); peer = calloc(1, sizeof(*peer));
if (!peer) if (!peer)
goto err_peer; goto err_peer;
if (nvlist_exists_binary(nvl_peers[i], "public-key")) { if (nvlist_exists_binary(nvl_peers[i], "public-key"))
{
binary = nvlist_get_binary(nvl_peers[i], "public-key", &size); binary = nvlist_get_binary(nvl_peers[i], "public-key", &size);
if (binary && size == sizeof(peer->public_key)) { if (binary && size == sizeof(peer->public_key))
{
memcpy(peer->public_key, binary, sizeof(peer->public_key)); memcpy(peer->public_key, binary, sizeof(peer->public_key));
peer->flags |= WGPEER_HAS_PUBLIC_KEY; peer->flags |= WGPEER_HAS_PUBLIC_KEY;
} }
} }
if (nvlist_exists_binary(nvl_peers[i], "preshared-key")) { if (nvlist_exists_binary(nvl_peers[i], "preshared-key"))
{
binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size); binary = nvlist_get_binary(nvl_peers[i], "preshared-key", &size);
if (binary && size == sizeof(peer->preshared_key)) { if (binary && size == sizeof(peer->preshared_key))
{
memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key)); memcpy(peer->preshared_key, binary, sizeof(peer->preshared_key));
if (!key_is_zero(peer->preshared_key)) if (!key_is_zero(peer->preshared_key))
peer->flags |= WGPEER_HAS_PRESHARED_KEY; peer->flags |= WGPEER_HAS_PRESHARED_KEY;
} }
} }
if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval")) { if (nvlist_exists_number(nvl_peers[i], "persistent-keepalive-interval"))
{
number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval"); number = nvlist_get_number(nvl_peers[i], "persistent-keepalive-interval");
if (number <= UINT16_MAX) { if (number <= UINT16_MAX)
{
peer->persistent_keepalive_interval = number; peer->persistent_keepalive_interval = number;
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
} }
} }
if (nvlist_exists_binary(nvl_peers[i], "endpoint")) { 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) && 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)) (endpoint->sa_family == AF_INET || endpoint->sa_family == AF_INET6))
memcpy(&peer->endpoint.addr, endpoint, size); memcpy(&peer->endpoint.addr, endpoint, size);
} }
@ -222,10 +341,14 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
peer->rx_bytes = nvlist_get_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")) if (nvlist_exists_number(nvl_peers[i], "tx-bytes"))
peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes"); peer->tx_bytes = nvlist_get_number(nvl_peers[i], "tx-bytes");
if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time")) { if (nvlist_exists_binary(nvl_peers[i], "last-handshake-time"))
{
binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size); binary = nvlist_get_binary(nvl_peers[i], "last-handshake-time", &size);
if (binary && size == sizeof(peer->last_handshake_time)) if (binary && size == sizeof(peer->last_handshake_time))
memcpy(&peer->last_handshake_time, binary, sizeof(peer->last_handshake_time)); memcpy(
&peer->last_handshake_time,
binary,
sizeof(peer->last_handshake_time));
} }
if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips")) if (!nvlist_exists_nvlist_array(nvl_peers[i], "allowed-ips"))
@ -233,28 +356,35 @@ static int kernel_get_device(struct wgdevice **device, const char *ifname)
nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count); nvl_aips = nvlist_get_nvlist_array(nvl_peers[i], "allowed-ips", &aip_count);
if (!aip_count || !nvl_aips) if (!aip_count || !nvl_aips)
goto skip_allowed_ips; goto skip_allowed_ips;
for (j = 0; j < aip_count; ++j) { for (j = 0; j < aip_count; ++j)
{
if (!nvlist_exists_number(nvl_aips[j], "cidr")) if (!nvlist_exists_number(nvl_aips[j], "cidr"))
continue; continue;
if (!nvlist_exists_binary(nvl_aips[j], "ipv4") && !nvlist_exists_binary(nvl_aips[j], "ipv6")) if (!nvlist_exists_binary(nvl_aips[j], "ipv4") &&
!nvlist_exists_binary(nvl_aips[j], "ipv6"))
continue; continue;
aip = calloc(1, sizeof(*aip)); aip = calloc(1, sizeof(*aip));
if (!aip) if (!aip)
goto err_allowed_ips; goto err_allowed_ips;
number = nvlist_get_number(nvl_aips[j], "cidr"); number = nvlist_get_number(nvl_aips[j], "cidr");
if (nvlist_exists_binary(nvl_aips[j], "ipv4")) { if (nvlist_exists_binary(nvl_aips[j], "ipv4"))
{
binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size); binary = nvlist_get_binary(nvl_aips[j], "ipv4", &size);
if (!binary || number > 32) { if (!binary || number > 32)
{
ret = EINVAL; ret = EINVAL;
goto err_allowed_ips; goto err_allowed_ips;
} }
aip->family = AF_INET; aip->family = AF_INET;
aip->cidr = number; aip->cidr = number;
memcpy(&aip->ip4, binary, sizeof(aip->ip4)); memcpy(&aip->ip4, binary, sizeof(aip->ip4));
} else { }
else
{
assert(nvlist_exists_binary(nvl_aips[j], "ipv6")); assert(nvlist_exists_binary(nvl_aips[j], "ipv6"));
binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size); binary = nvlist_get_binary(nvl_aips[j], "ipv6", &size);
if (!binary || number > 128) { if (!binary || number > 128)
{
ret = EINVAL; ret = EINVAL;
goto err_allowed_ips; goto err_allowed_ips;
} }
@ -310,13 +440,12 @@ err:
return ret; return ret;
} }
static int kernel_set_device(struct wgdevice* dev)
static int kernel_set_device(struct wgdevice *dev)
{ {
struct wg_data_io wgd = { 0 }; struct wg_data_io wgd = {0};
nvlist_t *nvl_device = NULL, **nvl_peers = NULL; nvlist_t * nvl_device = NULL, **nvl_peers = NULL;
size_t peer_count = 0, i = 0; size_t peer_count = 0, i = 0;
struct wgpeer *peer; struct wgpeer* peer;
int ret = 0, s; int ret = 0, s;
strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name)); strlcpy(wgd.wgd_name, dev->name, sizeof(wgd.wgd_name));
@ -325,15 +454,16 @@ static int kernel_set_device(struct wgdevice *dev)
if (!nvl_device) if (!nvl_device)
goto err; goto err;
for_each_wgpeer(dev, peer) for_each_wgpeer(dev, peer)++ peer_count;
++peer_count; if (peer_count)
if (peer_count) { {
nvl_peers = calloc(peer_count, sizeof(*nvl_peers)); nvl_peers = calloc(peer_count, sizeof(*nvl_peers));
if (!nvl_peers) if (!nvl_peers)
goto err; goto err;
} }
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
nvlist_add_binary(nvl_device, "private-key", dev->private_key, sizeof(dev->private_key)); nvlist_add_binary(
nvl_device, "private-key", dev->private_key, sizeof(dev->private_key));
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
nvlist_add_number(nvl_device, "listen-port", dev->listen_port); nvlist_add_number(nvl_device, "listen-port", dev->listen_port);
if (dev->flags & WGDEVICE_HAS_JC) if (dev->flags & WGDEVICE_HAS_JC)
@ -354,38 +484,72 @@ static int kernel_set_device(struct wgdevice *dev)
nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header); nvlist_add_number(nvl_device, "h3", dev->underload_packet_magic_header);
if (dev->flags & WGDEVICE_HAS_H4) if (dev->flags & WGDEVICE_HAS_H4)
nvlist_add_number(nvl_device, "h4", dev->transport_packet_magic_header); 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);
if (dev->flags & WGDEVICE_HAS_FWMARK) if (dev->flags & WGDEVICE_HAS_FWMARK)
nvlist_add_number(nvl_device, "user-cookie", dev->fwmark); nvlist_add_number(nvl_device, "user-cookie", dev->fwmark);
if (dev->flags & WGDEVICE_REPLACE_PEERS) if (dev->flags & WGDEVICE_REPLACE_PEERS)
nvlist_add_bool(nvl_device, "replace-peers", true); nvlist_add_bool(nvl_device, "replace-peers", true);
for_each_wgpeer(dev, peer) { for_each_wgpeer(dev, peer)
{
size_t aip_count = 0, j = 0; size_t aip_count = 0, j = 0;
nvlist_t **nvl_aips = NULL; nvlist_t** nvl_aips = NULL;
struct wgallowedip *aip; struct wgallowedip* aip;
nvl_peers[i] = nvlist_create(0); nvl_peers[i] = nvlist_create(0);
if (!nvl_peers[i]) if (!nvl_peers[i])
goto err_peer; goto err_peer;
for_each_wgallowedip(peer, aip) for_each_wgallowedip(peer, aip)++ aip_count;
++aip_count; if (aip_count)
if (aip_count) { {
nvl_aips = calloc(aip_count, sizeof(*nvl_aips)); nvl_aips = calloc(aip_count, sizeof(*nvl_aips));
if (!nvl_aips) if (!nvl_aips)
goto err_peer; goto err_peer;
} }
nvlist_add_binary(nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key)); nvlist_add_binary(
nvl_peers[i], "public-key", peer->public_key, sizeof(peer->public_key));
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
nvlist_add_binary(nvl_peers[i], "preshared-key", peer->preshared_key, sizeof(peer->preshared_key)); nvlist_add_binary(
nvl_peers[i],
"preshared-key",
peer->preshared_key,
sizeof(peer->preshared_key));
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
nvlist_add_number(nvl_peers[i], "persistent-keepalive-interval", peer->persistent_keepalive_interval); nvlist_add_number(
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) nvl_peers[i],
nvlist_add_binary(nvl_peers[i], "endpoint", &peer->endpoint.addr, peer->endpoint.addr.sa_len); "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) if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
nvlist_add_bool(nvl_peers[i], "replace-allowedips", true); nvlist_add_bool(nvl_peers[i], "replace-allowedips", true);
if (peer->flags & WGPEER_REMOVE_ME) if (peer->flags & WGPEER_REMOVE_ME)
nvlist_add_bool(nvl_peers[i], "remove", true); nvlist_add_bool(nvl_peers[i], "remove", true);
for_each_wgallowedip(peer, aip) { for_each_wgallowedip(peer, aip)
{
nvl_aips[j] = nvlist_create(0); nvl_aips[j] = nvlist_create(0);
if (!nvl_aips[j]) if (!nvl_aips[j])
goto err_peer; goto err_peer;
@ -396,8 +560,10 @@ static int kernel_set_device(struct wgdevice *dev)
nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6)); nvlist_add_binary(nvl_aips[j], "ipv6", &aip->ip6, sizeof(aip->ip6));
++j; ++j;
} }
if (j) { if (j)
nvlist_add_nvlist_array(nvl_peers[i], "allowed-ips", (const nvlist_t *const *)nvl_aips, j); {
nvlist_add_nvlist_array(
nvl_peers[i], "allowed-ips", (const nvlist_t* const*)nvl_aips, j);
for (j = 0; j < aip_count; ++j) for (j = 0; j < aip_count; ++j)
nvlist_destroy(nvl_aips[j]); nvlist_destroy(nvl_aips[j]);
free(nvl_aips); free(nvl_aips);
@ -414,8 +580,10 @@ static int kernel_set_device(struct wgdevice *dev)
nvl_peers[i] = NULL; nvl_peers[i] = NULL;
goto err; goto err;
} }
if (i) { if (i)
nvlist_add_nvlist_array(nvl_device, "peers", (const nvlist_t *const *)nvl_peers, i); {
nvlist_add_nvlist_array(
nvl_device, "peers", (const nvlist_t* const*)nvl_peers, i);
for (i = 0; i < peer_count; ++i) for (i = 0; i < peer_count; ++i)
nvlist_destroy(nvl_peers[i]); nvlist_destroy(nvl_peers[i]);
free(nvl_peers); free(nvl_peers);

View file

@ -646,50 +646,67 @@ static int parse_device(const struct nlattr* attr, void* data)
device->transport_packet_magic_header = mnl_attr_get_u32(attr); device->transport_packet_magic_header = mnl_attr_get_u32(attr);
device->flags |= WGDEVICE_HAS_H4; device->flags |= WGDEVICE_HAS_H4;
} }
break;
case WGDEVICE_A_I1: 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->i1 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_I1; device->flags |= WGDEVICE_HAS_I1;
} }
break;
case WGDEVICE_A_I2: case WGDEVICE_A_I2:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->i2 = strdup(mnl_attr_get_str(attr)); device->i2 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_I2; device->flags |= WGDEVICE_HAS_I2;
} }
break;
case WGDEVICE_A_I3: case WGDEVICE_A_I3:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->i3 = strdup(mnl_attr_get_str(attr)); device->i3 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_I3; device->flags |= WGDEVICE_HAS_I3;
} }
break;
case WGDEVICE_A_I4: case WGDEVICE_A_I4:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->i4 = strdup(mnl_attr_get_str(attr)); device->i4 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_I4; device->flags |= WGDEVICE_HAS_I4;
} }
break;
case WGDEVICE_A_I5: case WGDEVICE_A_I5:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->i5 = strdup(mnl_attr_get_str(attr)); device->i5 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_I5; device->flags |= WGDEVICE_HAS_I5;
} }
break;
case WGDEVICE_A_J1: case WGDEVICE_A_J1:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->j1 = strdup(mnl_attr_get_str(attr)); device->j1 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_J1; device->flags |= WGDEVICE_HAS_J1;
} }
break;
case WGDEVICE_A_J2: case WGDEVICE_A_J2:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->j2 = strdup(mnl_attr_get_str(attr)); device->j2 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_J2; device->flags |= WGDEVICE_HAS_J2;
} }
break;
case WGDEVICE_A_J3: case WGDEVICE_A_J3:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
{
device->j3 = strdup(mnl_attr_get_str(attr)); device->j3 = strdup(mnl_attr_get_str(attr));
device->flags |= WGDEVICE_HAS_J3; device->flags |= WGDEVICE_HAS_J3;
} }
break;
case WGDEVICE_A_ITIME: case WGDEVICE_A_ITIME:
if (!mnl_attr_validate(attr, MNL_TYPE_STRING) { if (!mnl_attr_validate(attr, MNL_TYPE_STRING))
device->itime = strdup(mnl_attr_get_str(attr)); {
device->itime = mnl_attr_get_u32(attr);
device->flags |= WGDEVICE_HAS_ITIME; device->flags |= WGDEVICE_HAS_ITIME;
} }
break; break;

View file

@ -3,19 +3,19 @@
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/ */
#include "containers.h"
#include <errno.h> #include <errno.h>
#include <net/if.h>
#include <net/if_wg.h>
#include <netinet/in.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <sys/types.h> #include <sys/types.h>
#include <net/if.h> #include <time.h>
#include <net/if_wg.h>
#include <netinet/in.h>
#include "containers.h"
#define IPC_SUPPORTS_KERNEL_INTERFACE #define IPC_SUPPORTS_KERNEL_INTERFACE
@ -27,10 +27,10 @@ static int get_dgram_socket(void)
return sock; 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 ifgroupreq ifgr = {.ifgr_name = "wg"};
struct ifg_req *ifg; struct ifg_req* ifg;
int s = get_dgram_socket(), ret = 0; int s = get_dgram_socket(), ret = 0;
if (s < 0) if (s < 0)
@ -42,12 +42,14 @@ static int kernel_get_wireguard_interfaces(struct string_list *list)
ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len); ifgr.ifgr_groups = calloc(1, ifgr.ifgr_len);
if (!ifgr.ifgr_groups) if (!ifgr.ifgr_groups)
return -errno; return -errno;
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0) { if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) < 0)
{
ret = -errno; ret = -errno;
goto out; goto out;
} }
for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg) { for (ifg = ifgr.ifgr_groups; ifg && ifgr.ifgr_len > 0; ++ifg)
{
if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0) if ((ret = string_list_add(list, ifg->ifgrq_member)) < 0)
goto out; goto out;
ifgr.ifgr_len -= sizeof(struct ifg_req); ifgr.ifgr_len -= sizeof(struct ifg_req);
@ -58,15 +60,15 @@ out:
return ret; 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_data_io wgdata = {.wgd_size = 0};
struct wg_interface_io *wg_iface; struct wg_interface_io* wg_iface;
struct wg_peer_io *wg_peer; struct wg_peer_io* wg_peer;
struct wg_aip_io *wg_aip; struct wg_aip_io* wg_aip;
struct wgdevice *dev; struct wgdevice* dev;
struct wgpeer *peer; struct wgpeer* peer;
struct wgallowedip *aip; struct wgallowedip* aip;
int s = get_dgram_socket(), ret; int s = get_dgram_socket(), ret;
if (s < 0) if (s < 0)
@ -74,7 +76,8 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
*device = NULL; *device = NULL;
strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name)); strlcpy(wgdata.wgd_name, iface, sizeof(wgdata.wgd_name));
for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size) { for (size_t last_size = wgdata.wgd_size;; last_size = wgdata.wgd_size)
{
if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0) if (ioctl(s, SIOCGWG, (caddr_t)&wgdata) < 0)
goto out; goto out;
if (last_size >= wgdata.wgd_size) if (last_size >= wgdata.wgd_size)
@ -90,73 +93,141 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
goto out; goto out;
strlcpy(dev->name, iface, sizeof(dev->name)); strlcpy(dev->name, iface, sizeof(dev->name));
if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE) { if (wg_iface->i_flags & WG_INTERFACE_HAS_RTABLE)
{
dev->fwmark = wg_iface->i_rtable; dev->fwmark = wg_iface->i_rtable;
dev->flags |= WGDEVICE_HAS_FWMARK; dev->flags |= WGDEVICE_HAS_FWMARK;
} }
if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT) { if (wg_iface->i_flags & WG_INTERFACE_HAS_PORT)
{
dev->listen_port = wg_iface->i_port; dev->listen_port = wg_iface->i_port;
dev->flags |= WGDEVICE_HAS_LISTEN_PORT; dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
} }
if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC) { if (wg_iface->i_flags & WG_INTERFACE_HAS_PUBLIC)
{
memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key)); memcpy(dev->public_key, wg_iface->i_public, sizeof(dev->public_key));
dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; dev->flags |= WGDEVICE_HAS_PUBLIC_KEY;
} }
if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE) { if (wg_iface->i_flags & WG_INTERFACE_HAS_PRIVATE)
{
memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key)); memcpy(dev->private_key, wg_iface->i_private, sizeof(dev->private_key));
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; dev->flags |= WGDEVICE_HAS_PRIVATE_KEY;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JC)
{
dev->junk_packet_count = wg_iface->i_junk_packet_count; dev->junk_packet_count = wg_iface->i_junk_packet_count;
dev->flags |= WGDEVICE_HAS_JC; dev->flags |= WGDEVICE_HAS_JC;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMIN)
{
dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size; dev->junk_packet_min_size = wg_iface->i_junk_packet_min_size;
dev->flags |= WGDEVICE_HAS_JMIN; dev->flags |= WGDEVICE_HAS_JMIN;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_JMAX)
{
dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size; dev->junk_packet_max_size = wg_iface->i_junk_packet_max_size;
dev->flags |= WGDEVICE_HAS_JMAX; dev->flags |= WGDEVICE_HAS_JMAX;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S1)
{
dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size; dev->init_packet_junk_size = wg_iface->i_init_packet_junk_size;
dev->flags |= WGDEVICE_HAS_S1; dev->flags |= WGDEVICE_HAS_S1;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_S2)
{
dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size; dev->response_packet_junk_size = wg_iface->i_response_packet_junk_size;
dev->flags |= WGDEVICE_HAS_S2; dev->flags |= WGDEVICE_HAS_S2;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H1)
{
dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header; dev->init_packet_magic_header = wg_iface->i_init_packet_magic_header;
dev->flags |= WGDEVICE_HAS_H1; dev->flags |= WGDEVICE_HAS_H1;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H2)
{
dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header; dev->response_packet_magic_header = wg_iface->i_response_packet_magic_header;
dev->flags |= WGDEVICE_HAS_H2; dev->flags |= WGDEVICE_HAS_H2;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H3)
{
dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header; dev->underload_packet_magic_header = wg_iface->i_underload_packet_magic_header;
dev->flags |= WGDEVICE_HAS_H3; dev->flags |= WGDEVICE_HAS_H3;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4) { if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_H4)
{
dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header; dev->transport_packet_magic_header = wg_iface->i_transport_packet_magic_header;
dev->flags |= WGDEVICE_HAS_H4; dev->flags |= WGDEVICE_HAS_H4;
} }
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I1)
{
wg_iface->i_i1 = strdup(dev->i1);
wg_iface->i_flags |= WGDEVICE_HAS_I1;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I2)
{
wg_iface->i_i2 = strdup(dev->i2);
wg_iface->i_flags |= WGDEVICE_HAS_I2;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I3)
{
wg_iface->i_i3 = strdup(dev->i3);
wg_iface->i_flags |= WGDEVICE_HAS_I3;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I4)
{
wg_iface->i_i4 = strdup(dev->i4);
wg_iface->i_flags |= WGDEVICE_HAS_I4;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_I5)
{
wg_iface->i_i5 = strdup(dev->i5);
wg_iface->i_flags |= WGDEVICE_HAS_I5;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J1)
{
wg_iface->i_j1 = strdup(dev->j1);
wg_iface->i_flags |= WGDEVICE_HAS_J1;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J2)
{
wg_iface->i_j2 = strdup(dev->j2);
wg_iface->i_flags |= WGDEVICE_HAS_J2;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_J3)
{
wg_iface->i_j3 = strdup(dev->j3);
wg_iface->i_flags |= WGDEVICE_HAS_J3;
}
if (wg_iface->i_flags & WG_INTERFACE_DEVICE_HAS_ITIME)
{
wg_iface->i_itime = dev->itime;
wg_iface->i_flags |= WGDEVICE_HAS_ITIME;
}
wg_peer = &wg_iface->i_peers[0]; wg_peer = &wg_iface->i_peers[0];
for (size_t i = 0; i < wg_iface->i_peers_count; ++i) { for (size_t i = 0; i < wg_iface->i_peers_count; ++i)
{
peer = calloc(1, sizeof(*peer)); peer = calloc(1, sizeof(*peer));
if (!peer) if (!peer)
goto out; goto out;
@ -167,23 +238,27 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
dev->last_peer->next_peer = peer; dev->last_peer->next_peer = peer;
dev->last_peer = peer; dev->last_peer = peer;
if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC) { if (wg_peer->p_flags & WG_PEER_HAS_PUBLIC)
{
memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key)); memcpy(peer->public_key, wg_peer->p_public, sizeof(peer->public_key));
peer->flags |= WGPEER_HAS_PUBLIC_KEY; peer->flags |= WGPEER_HAS_PUBLIC_KEY;
} }
if (wg_peer->p_flags & WG_PEER_HAS_PSK) { if (wg_peer->p_flags & WG_PEER_HAS_PSK)
{
memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key)); memcpy(peer->preshared_key, wg_peer->p_psk, sizeof(peer->preshared_key));
if (!key_is_zero(peer->preshared_key)) if (!key_is_zero(peer->preshared_key))
peer->flags |= WGPEER_HAS_PRESHARED_KEY; peer->flags |= WGPEER_HAS_PRESHARED_KEY;
} }
if (wg_peer->p_flags & WG_PEER_HAS_PKA) { if (wg_peer->p_flags & WG_PEER_HAS_PKA)
{
peer->persistent_keepalive_interval = wg_peer->p_pka; peer->persistent_keepalive_interval = wg_peer->p_pka;
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
} }
if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT && wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr)) if (wg_peer->p_flags & WG_PEER_HAS_ENDPOINT &&
wg_peer->p_sa.sa_len <= sizeof(peer->endpoint.addr))
memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len); memcpy(&peer->endpoint.addr, &wg_peer->p_sa, wg_peer->p_sa.sa_len);
peer->rx_bytes = wg_peer->p_rxbytes; peer->rx_bytes = wg_peer->p_rxbytes;
@ -193,7 +268,8 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec; peer->last_handshake_time.tv_nsec = wg_peer->p_last_handshake.tv_nsec;
wg_aip = &wg_peer->p_aips[0]; wg_aip = &wg_peer->p_aips[0];
for (size_t j = 0; j < wg_peer->p_aips_count; ++j) { for (size_t j = 0; j < wg_peer->p_aips_count; ++j)
{
aip = calloc(1, sizeof(*aip)); aip = calloc(1, sizeof(*aip));
if (!aip) if (!aip)
goto out; goto out;
@ -205,16 +281,19 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
peer->last_allowedip = aip; peer->last_allowedip = aip;
aip->family = wg_aip->a_af; aip->family = wg_aip->a_af;
if (wg_aip->a_af == AF_INET) { if (wg_aip->a_af == AF_INET)
{
memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4)); memcpy(&aip->ip4, &wg_aip->a_ipv4, sizeof(aip->ip4));
aip->cidr = wg_aip->a_cidr; aip->cidr = wg_aip->a_cidr;
} else if (wg_aip->a_af == AF_INET6) { }
else if (wg_aip->a_af == AF_INET6)
{
memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6)); memcpy(&aip->ip6, &wg_aip->a_ipv6, sizeof(aip->ip6));
aip->cidr = wg_aip->a_cidr; aip->cidr = wg_aip->a_cidr;
} }
++wg_aip; ++wg_aip;
} }
wg_peer = (struct wg_peer_io *)wg_aip; wg_peer = (struct wg_peer_io*)wg_aip;
} }
*device = dev; *device = dev;
errno = 0; errno = 0;
@ -224,41 +303,44 @@ out:
return ret; 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_data_io wgdata = {.wgd_size = sizeof(struct wg_interface_io)};
struct wg_interface_io *wg_iface; struct wg_interface_io* wg_iface;
struct wg_peer_io *wg_peer; struct wg_peer_io* wg_peer;
struct wg_aip_io *wg_aip; struct wg_aip_io* wg_aip;
struct wgpeer *peer; struct wgpeer* peer;
struct wgallowedip *aip; struct wgallowedip* aip;
int s = get_dgram_socket(), ret; int s = get_dgram_socket(), ret;
size_t peer_count, aip_count; size_t peer_count, aip_count;
if (s < 0) if (s < 0)
return -errno; return -errno;
for_each_wgpeer(dev, peer) { for_each_wgpeer(dev, peer)
{
wgdata.wgd_size += sizeof(struct wg_peer_io); wgdata.wgd_size += sizeof(struct wg_peer_io);
for_each_wgallowedip(peer, aip) for_each_wgallowedip(peer, aip) wgdata.wgd_size += sizeof(struct wg_aip_io);
wgdata.wgd_size += sizeof(struct wg_aip_io);
} }
wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size); wg_iface = wgdata.wgd_interface = calloc(1, wgdata.wgd_size);
if (!wgdata.wgd_interface) if (!wgdata.wgd_interface)
return -errno; return -errno;
strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name)); strlcpy(wgdata.wgd_name, dev->name, sizeof(wgdata.wgd_name));
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
{
memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private)); memcpy(wg_iface->i_private, dev->private_key, sizeof(wg_iface->i_private));
wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE; wg_iface->i_flags |= WG_INTERFACE_HAS_PRIVATE;
} }
if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) { if (dev->flags & WGDEVICE_HAS_LISTEN_PORT)
{
wg_iface->i_port = dev->listen_port; wg_iface->i_port = dev->listen_port;
wg_iface->i_flags |= WG_INTERFACE_HAS_PORT; wg_iface->i_flags |= WG_INTERFACE_HAS_PORT;
} }
if (dev->flags & WGDEVICE_HAS_FWMARK) { if (dev->flags & WGDEVICE_HAS_FWMARK)
{
wg_iface->i_rtable = dev->fwmark; wg_iface->i_rtable = dev->fwmark;
wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE; wg_iface->i_flags |= WG_INTERFACE_HAS_RTABLE;
} }
@ -266,71 +348,139 @@ static int kernel_set_device(struct wgdevice *dev)
if (dev->flags & WGDEVICE_REPLACE_PEERS) if (dev->flags & WGDEVICE_REPLACE_PEERS)
wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS; wg_iface->i_flags |= WG_INTERFACE_REPLACE_PEERS;
if (dev->flags & WGDEVICE_HAS_JC)
if (dev->flags & WGDEVICE_HAS_JC) { {
wg_iface->i_junk_packet_count = dev->junk_packet_count; wg_iface->i_junk_packet_count = dev->junk_packet_count;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JC;
} }
if (dev->flags & WGDEVICE_HAS_JMIN) { if (dev->flags & WGDEVICE_HAS_JMIN)
{
wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size; wg_iface->i_junk_packet_min_size = dev->junk_packet_min_size;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMIN;
} }
if (dev->flags & WGDEVICE_HAS_JMAX) { if (dev->flags & WGDEVICE_HAS_JMAX)
{
wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size; wg_iface->i_junk_packet_max_size = dev->junk_packet_max_size;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_JMAX;
} }
if (dev->flags & WGDEVICE_HAS_S1) { if (dev->flags & WGDEVICE_HAS_S1)
{
wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size; wg_iface->i_init_packet_junk_size = dev->init_packet_junk_size;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S1;
} }
if (dev->flags & WGDEVICE_HAS_S2) { if (dev->flags & WGDEVICE_HAS_S2)
{
wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size; wg_iface->i_response_packet_junk_size = dev->response_packet_junk_size;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_S2;
} }
if (dev->flags & WGDEVICE_HAS_H1) { if (dev->flags & WGDEVICE_HAS_H1)
{
wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header; wg_iface->i_init_packet_magic_header = dev->init_packet_magic_header;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H1;
} }
if (dev->flags & WGDEVICE_HAS_H2) { if (dev->flags & WGDEVICE_HAS_H2)
{
wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header; wg_iface->i_response_packet_magic_header = dev->response_packet_magic_header;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H2;
} }
if (dev->flags & WGDEVICE_HAS_H3) { if (dev->flags & WGDEVICE_HAS_H3)
{
wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header; wg_iface->i_underload_packet_magic_header = dev->underload_packet_magic_header;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3; wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H3;
} }
if (dev->flags & WGDEVICE_HAS_H4) { if (dev->flags & WGDEVICE_HAS_H4)
{
wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header; wg_iface->i_transport_packet_magic_header = dev->transport_packet_magic_header;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_H4; 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;
}
if (dev->flags & WGDEVICE_HAS_I2)
{
wg_iface->i_i2 = strdup(dev->i2);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I2;
}
if (dev->flags & WGDEVICE_HAS_I3)
{
wg_iface->i_i3 = strdup(dev->i3);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I3;
}
if (dev->flags & WGDEVICE_HAS_I4)
{
wg_iface->i_i4 = strdup(dev->i4);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I4;
}
if (dev->flags & WGDEVICE_HAS_I5)
{
wg_iface->i_i5 = strdup(dev->i5);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_I5;
}
if (dev->flags & WGDEVICE_HAS_J1)
{
wg_iface->i_j1 = strdup(dev->j1);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J1;
}
if (dev->flags & WGDEVICE_HAS_J2)
{
wg_iface->i_j2 = strdup(dev->j2);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J2;
}
if (dev->flags & WGDEVICE_HAS_J3)
{
wg_iface->i_j3 = strdup(dev->j3);
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_J3;
}
if (dev->flags & WGDEVICE_HAS_ITIME)
{
wg_iface->i_itime = dev->itime;
wg_iface->i_flags |= WG_INTERFACE_DEVICE_HAS_ITIME;
}
peer_count = 0; peer_count = 0;
wg_peer = &wg_iface->i_peers[0]; wg_peer = &wg_iface->i_peers[0];
for_each_wgpeer(dev, peer) { for_each_wgpeer(dev, peer)
{
wg_peer->p_flags = WG_PEER_HAS_PUBLIC; wg_peer->p_flags = WG_PEER_HAS_PUBLIC;
memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public)); memcpy(wg_peer->p_public, peer->public_key, sizeof(wg_peer->p_public));
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
{
memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk)); memcpy(wg_peer->p_psk, peer->preshared_key, sizeof(wg_peer->p_psk));
wg_peer->p_flags |= WG_PEER_HAS_PSK; wg_peer->p_flags |= WG_PEER_HAS_PSK;
} }
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) { if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
{
wg_peer->p_pka = peer->persistent_keepalive_interval; wg_peer->p_pka = peer->persistent_keepalive_interval;
wg_peer->p_flags |= WG_PEER_HAS_PKA; wg_peer->p_flags |= WG_PEER_HAS_PKA;
} }
if ((peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) && if ((peer->endpoint.addr.sa_family == AF_INET ||
peer->endpoint.addr.sa_len <= sizeof(wg_peer->p_endpoint)) { peer->endpoint.addr.sa_family == AF_INET6) &&
memcpy(&wg_peer->p_endpoint, &peer->endpoint.addr, peer->endpoint.addr.sa_len); 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; wg_peer->p_flags |= WG_PEER_HAS_ENDPOINT;
} }
@ -342,7 +492,8 @@ static int kernel_set_device(struct wgdevice *dev)
aip_count = 0; aip_count = 0;
wg_aip = &wg_peer->p_aips[0]; wg_aip = &wg_peer->p_aips[0];
for_each_wgallowedip(peer, aip) { for_each_wgallowedip(peer, aip)
{
wg_aip->a_af = aip->family; wg_aip->a_af = aip->family;
wg_aip->a_cidr = aip->cidr; wg_aip->a_cidr = aip->cidr;
@ -357,7 +508,7 @@ static int kernel_set_device(struct wgdevice *dev)
} }
wg_peer->p_aips_count = aip_count; wg_peer->p_aips_count = aip_count;
++peer_count; ++peer_count;
wg_peer = (struct wg_peer_io *)wg_aip; wg_peer = (struct wg_peer_io*)wg_aip;
} }
wg_iface->i_peers_count = peer_count; wg_iface->i_peers_count = peer_count;

View file

@ -3,6 +3,10 @@
* Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * 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 <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
@ -14,10 +18,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "containers.h"
#include "curve25519.h"
#include "encoding.h"
#include "ctype.h"
#ifdef _WIN32 #ifdef _WIN32
#include "ipc-uapi-windows.h" #include "ipc-uapi-windows.h"
@ -25,23 +25,24 @@
#include "ipc-uapi-unix.h" #include "ipc-uapi-unix.h"
#endif #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]; char hex[WG_KEY_LEN_HEX], ip[INET6_ADDRSTRLEN], host[4096 + 1], service[512 + 1];
struct wgpeer *peer; struct wgpeer* peer;
struct wgallowedip *allowedip; struct wgallowedip* allowedip;
FILE *f; FILE* f;
int ret, set_errno = -EPROTO; int ret, set_errno = -EPROTO;
socklen_t addr_len; socklen_t addr_len;
size_t line_buffer_len = 0, line_len; size_t line_buffer_len = 0, line_len;
char *key = NULL, *value; char * key = NULL, *value;
f = userspace_interface_file(dev->name); f = userspace_interface_file(dev->name);
if (!f) if (!f)
return -errno; return -errno;
fprintf(f, "set=1\n"); fprintf(f, "set=1\n");
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY)
{
key_to_hex(hex, dev->private_key); key_to_hex(hex, dev->private_key);
fprintf(f, "private_key=%s\n", hex); fprintf(f, "private_key=%s\n", hex);
} }
@ -69,29 +70,61 @@ static int userspace_set_device(struct wgdevice *dev)
fprintf(f, "h3=%u\n", dev->underload_packet_magic_header); fprintf(f, "h3=%u\n", dev->underload_packet_magic_header);
if (dev->flags & WGDEVICE_HAS_H4) if (dev->flags & WGDEVICE_HAS_H4)
fprintf(f, "h4=%u\n", dev->transport_packet_magic_header); 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) { for_each_wgpeer(dev, peer)
{
key_to_hex(hex, peer->public_key); key_to_hex(hex, peer->public_key);
fprintf(f, "public_key=%s\n", hex); fprintf(f, "public_key=%s\n", hex);
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) { if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY)
{
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (peer->flags & WGPEER_REMOVE_ME) { if (peer->flags & WGPEER_REMOVE_ME)
{
fprintf(f, "remove=true\n"); fprintf(f, "remove=true\n");
continue; continue;
} }
if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { if (peer->flags & WGPEER_HAS_PRESHARED_KEY)
{
key_to_hex(hex, peer->preshared_key); key_to_hex(hex, peer->preshared_key);
fprintf(f, "preshared_key=%s\n", hex); fprintf(f, "preshared_key=%s\n", hex);
} }
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) { if (peer->endpoint.addr.sa_family == AF_INET ||
peer->endpoint.addr.sa_family == AF_INET6)
{
addr_len = 0; addr_len = 0;
if (peer->endpoint.addr.sa_family == AF_INET) if (peer->endpoint.addr.sa_family == AF_INET)
addr_len = sizeof(struct sockaddr_in); addr_len = sizeof(struct sockaddr_in);
else if (peer->endpoint.addr.sa_family == AF_INET6) else if (peer->endpoint.addr.sa_family == AF_INET6)
addr_len = sizeof(struct sockaddr_in6); addr_len = sizeof(struct sockaddr_in6);
if (!getnameinfo(&peer->endpoint.addr, addr_len, host, sizeof(host), service, sizeof(service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) { if (!getnameinfo(
&peer->endpoint.addr,
addr_len,
host,
sizeof(host),
service,
sizeof(service),
NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST))
{
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':')) if (peer->endpoint.addr.sa_family == AF_INET6 && strchr(host, ':'))
fprintf(f, "endpoint=[%s]:%s\n", host, service); fprintf(f, "endpoint=[%s]:%s\n", host, service);
else else
@ -99,17 +132,25 @@ static int userspace_set_device(struct wgdevice *dev)
} }
} }
if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL)
fprintf(f, "persistent_keepalive_interval=%u\n", peer->persistent_keepalive_interval); fprintf(
f,
"persistent_keepalive_interval=%u\n",
peer->persistent_keepalive_interval);
if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS)
fprintf(f, "replace_allowed_ips=true\n"); fprintf(f, "replace_allowed_ips=true\n");
for_each_wgallowedip(peer, allowedip) { for_each_wgallowedip(peer, allowedip)
if (allowedip->family == AF_INET) { {
if (allowedip->family == AF_INET)
{
if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN)) if (!inet_ntop(AF_INET, &allowedip->ip4, ip, INET6_ADDRSTRLEN))
continue; continue;
} else if (allowedip->family == AF_INET6) { }
else if (allowedip->family == AF_INET6)
{
if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN)) if (!inet_ntop(AF_INET6, &allowedip->ip6, ip, INET6_ADDRSTRLEN))
continue; continue;
} else }
else
continue; continue;
fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr); fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
} }
@ -117,7 +158,8 @@ static int userspace_set_device(struct wgdevice *dev)
fprintf(f, "\n"); fprintf(f, "\n");
fflush(f); fflush(f);
while (getline(&key, &line_buffer_len, f) > 0) { while (getline(&key, &line_buffer_len, f) > 0)
{
line_len = strlen(key); line_len = strlen(key);
ret = set_errno; ret = set_errno;
if (line_len == 1 && key[0] == '\n') if (line_len == 1 && key[0] == '\n')
@ -127,9 +169,10 @@ static int userspace_set_device(struct wgdevice *dev)
break; break;
*value++ = key[--line_len] = '\0'; *value++ = key[--line_len] = '\0';
if (!strcmp(key, "errno")) { if (!strcmp(key, "errno"))
{
long long num; long long num;
char *end; char* end;
if (value[0] != '-' && !char_is_digit(value[0])) if (value[0] != '-' && !char_is_digit(value[0]))
break; break;
num = strtoll(value, &end, 10); num = strtoll(value, &end, 10);
@ -146,25 +189,26 @@ out:
return ret; return ret;
} }
#define NUM(max) ({ \ #define NUM(max) \
({ \
unsigned long long num; \ unsigned long long num; \
char *end; \ char* end; \
if (!char_is_digit(value[0])) \ if (!char_is_digit(value[0])) \
break; \ break; \
num = strtoull(value, &end, 10); \ num = strtoull(value, &end, 10); \
if (*end || num > max) \ if (*end || num > max) \
break; \ break; \
num; \ 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 wgdevice* dev;
struct wgpeer *peer = NULL; struct wgpeer* peer = NULL;
struct wgallowedip *allowedip = NULL; struct wgallowedip* allowedip = NULL;
size_t line_buffer_len = 0, line_len; size_t line_buffer_len = 0, line_len;
char *key = NULL, *value; char * key = NULL, *value;
FILE *f; FILE* f;
int ret = -EPROTO; int ret = -EPROTO;
*out = dev = calloc(1, sizeof(*dev)); *out = dev = calloc(1, sizeof(*dev));
@ -172,7 +216,8 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
return -errno; return -errno;
f = userspace_interface_file(iface); f = userspace_interface_file(iface);
if (!f) { if (!f)
{
ret = -errno; ret = -errno;
free(dev); free(dev);
*out = NULL; *out = NULL;
@ -185,7 +230,8 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
strncpy(dev->name, iface, IFNAMSIZ - 1); strncpy(dev->name, iface, IFNAMSIZ - 1);
dev->name[IFNAMSIZ - 1] = '\0'; dev->name[IFNAMSIZ - 1] = '\0';
while (getline(&key, &line_buffer_len, f) > 0) { while (getline(&key, &line_buffer_len, f) > 0)
{
line_len = strlen(key); line_len = strlen(key);
if (line_len == 1 && key[0] == '\n') if (line_len == 1 && key[0] == '\n')
goto err; goto err;
@ -194,48 +240,119 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
break; break;
*value++ = key[--line_len] = '\0'; *value++ = key[--line_len] = '\0';
if (!peer && !strcmp(key, "private_key")) { if (!peer && !strcmp(key, "private_key"))
{
if (!key_from_hex(dev->private_key, value)) if (!key_from_hex(dev->private_key, value))
break; break;
curve25519_generate_public(dev->public_key, dev->private_key); curve25519_generate_public(dev->public_key, dev->private_key);
dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY; dev->flags |= WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_PUBLIC_KEY;
} else if (!peer && !strcmp(key, "listen_port")) { }
else if (!peer && !strcmp(key, "listen_port"))
{
dev->listen_port = NUM(0xffffU); dev->listen_port = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_LISTEN_PORT; dev->flags |= WGDEVICE_HAS_LISTEN_PORT;
} else if (!peer && !strcmp(key, "fwmark")) { }
else if (!peer && !strcmp(key, "fwmark"))
{
dev->fwmark = NUM(0xffffffffU); dev->fwmark = NUM(0xffffffffU);
dev->flags |= WGDEVICE_HAS_FWMARK; dev->flags |= WGDEVICE_HAS_FWMARK;
} else if(!peer && !strcmp(key, "jc")) { }
else if (!peer && !strcmp(key, "jc"))
{
dev->junk_packet_count = NUM(0xffffU); dev->junk_packet_count = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_JC; dev->flags |= WGDEVICE_HAS_JC;
} else if(!peer && !strcmp(key, "jmin")) { }
else if (!peer && !strcmp(key, "jmin"))
{
dev->junk_packet_min_size = NUM(0xffffU); dev->junk_packet_min_size = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_JMIN; dev->flags |= WGDEVICE_HAS_JMIN;
} else if(!peer && !strcmp(key, "jmax")) { }
else if (!peer && !strcmp(key, "jmax"))
{
dev->junk_packet_max_size = NUM(0xffffU); dev->junk_packet_max_size = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_JMAX; dev->flags |= WGDEVICE_HAS_JMAX;
} else if(!peer && !strcmp(key, "s1")) { }
else if (!peer && !strcmp(key, "s1"))
{
dev->init_packet_junk_size = NUM(0xffffU); dev->init_packet_junk_size = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_S1; dev->flags |= WGDEVICE_HAS_S1;
} else if(!peer && !strcmp(key, "s2")) { }
else if (!peer && !strcmp(key, "s2"))
{
dev->response_packet_junk_size = NUM(0xffffU); dev->response_packet_junk_size = NUM(0xffffU);
dev->flags |= WGDEVICE_HAS_S2; dev->flags |= WGDEVICE_HAS_S2;
} else if(!peer && !strcmp(key, "h1")) { }
else if (!peer && !strcmp(key, "h1"))
{
dev->init_packet_magic_header = NUM(0xffffffffU); dev->init_packet_magic_header = NUM(0xffffffffU);
dev->flags |= WGDEVICE_HAS_H1; dev->flags |= WGDEVICE_HAS_H1;
} else if(!peer && !strcmp(key, "h2")) { }
else if (!peer && !strcmp(key, "h2"))
{
dev->response_packet_magic_header = NUM(0xffffffffU); dev->response_packet_magic_header = NUM(0xffffffffU);
dev->flags |= WGDEVICE_HAS_H2; dev->flags |= WGDEVICE_HAS_H2;
} else if(!peer && !strcmp(key, "h3")) { }
else if (!peer && !strcmp(key, "h3"))
{
dev->underload_packet_magic_header = NUM(0xffffffffU); dev->underload_packet_magic_header = NUM(0xffffffffU);
dev->flags |= WGDEVICE_HAS_H3; dev->flags |= WGDEVICE_HAS_H3;
} else if(!peer && !strcmp(key, "h4")) { }
else if (!peer && !strcmp(key, "h4"))
{
dev->transport_packet_magic_header = NUM(0xffffffffU); dev->transport_packet_magic_header = NUM(0xffffffffU);
dev->flags |= WGDEVICE_HAS_H4; dev->flags |= WGDEVICE_HAS_H4;
} else if (!strcmp(key, "public_key")) { }
struct wgpeer *new_peer = calloc(1, sizeof(*new_peer)); 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) { if (!new_peer)
{
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
@ -248,22 +365,26 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
if (!key_from_hex(peer->public_key, value)) if (!key_from_hex(peer->public_key, value))
break; break;
peer->flags |= WGPEER_HAS_PUBLIC_KEY; peer->flags |= WGPEER_HAS_PUBLIC_KEY;
} else if (peer && !strcmp(key, "preshared_key")) { }
else if (peer && !strcmp(key, "preshared_key"))
{
if (!key_from_hex(peer->preshared_key, value)) if (!key_from_hex(peer->preshared_key, value))
break; break;
if (!key_is_zero(peer->preshared_key)) if (!key_is_zero(peer->preshared_key))
peer->flags |= WGPEER_HAS_PRESHARED_KEY; peer->flags |= WGPEER_HAS_PRESHARED_KEY;
} else if (peer && !strcmp(key, "endpoint")) { }
char *begin, *end; else if (peer && !strcmp(key, "endpoint"))
struct addrinfo *resolved; {
char * begin, *end;
struct addrinfo* resolved;
struct addrinfo hints = { struct addrinfo hints = {
.ai_family = AF_UNSPEC, .ai_family = AF_UNSPEC,
.ai_socktype = SOCK_DGRAM, .ai_socktype = SOCK_DGRAM,
.ai_protocol = IPPROTO_UDP .ai_protocol = IPPROTO_UDP};
};
if (!strlen(value)) if (!strlen(value))
break; break;
if (value[0] == '[') { if (value[0] == '[')
{
begin = &value[1]; begin = &value[1];
end = strchr(value, ']'); end = strchr(value, ']');
if (!end) if (!end)
@ -271,36 +392,47 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
*end++ = '\0'; *end++ = '\0';
if (*end++ != ':' || !*end) if (*end++ != ':' || !*end)
break; break;
} else { }
else
{
begin = value; begin = value;
end = strrchr(value, ':'); end = strrchr(value, ':');
if (!end || !*(end + 1)) if (!end || !*(end + 1))
break; break;
*end++ = '\0'; *end++ = '\0';
} }
if (getaddrinfo(begin, end, &hints, &resolved) != 0) { if (getaddrinfo(begin, end, &hints, &resolved) != 0)
{
ret = ENETUNREACH; ret = ENETUNREACH;
goto err; goto err;
} }
if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) || if ((resolved->ai_family == AF_INET &&
(resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6))) 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); memcpy(&peer->endpoint.addr, resolved->ai_addr, resolved->ai_addrlen);
else { else
{
freeaddrinfo(resolved); freeaddrinfo(resolved);
break; break;
} }
freeaddrinfo(resolved); freeaddrinfo(resolved);
} else if (peer && !strcmp(key, "persistent_keepalive_interval")) { }
else if (peer && !strcmp(key, "persistent_keepalive_interval"))
{
peer->persistent_keepalive_interval = NUM(0xffffU); peer->persistent_keepalive_interval = NUM(0xffffU);
peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
} else if (peer && !strcmp(key, "allowed_ip")) { }
struct wgallowedip *new_allowedip; else if (peer && !strcmp(key, "allowed_ip"))
char *end, *mask = value, *ip = strsep(&mask, "/"); {
struct wgallowedip* new_allowedip;
char * end, *mask = value, *ip = strsep(&mask, "/");
if (!mask || !char_is_digit(mask[0])) if (!mask || !char_is_digit(mask[0]))
break; break;
new_allowedip = calloc(1, sizeof(*new_allowedip)); new_allowedip = calloc(1, sizeof(*new_allowedip));
if (!new_allowedip) { if (!new_allowedip)
{
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} }
@ -310,17 +442,23 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
peer->first_allowedip = new_allowedip; peer->first_allowedip = new_allowedip;
allowedip = new_allowedip; allowedip = new_allowedip;
allowedip->family = AF_UNSPEC; allowedip->family = AF_UNSPEC;
if (strchr(ip, ':')) { if (strchr(ip, ':'))
{
if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1) if (inet_pton(AF_INET6, ip, &allowedip->ip6) == 1)
allowedip->family = AF_INET6; allowedip->family = AF_INET6;
} else { }
else
{
if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1) if (inet_pton(AF_INET, ip, &allowedip->ip4) == 1)
allowedip->family = AF_INET; allowedip->family = AF_INET;
} }
allowedip->cidr = strtoul(mask, &end, 10); allowedip->cidr = strtoul(mask, &end, 10);
if (*end || allowedip->family == AF_UNSPEC || (allowedip->family == AF_INET6 && allowedip->cidr > 128) || (allowedip->family == AF_INET && allowedip->cidr > 32)) if (*end || allowedip->family == AF_UNSPEC ||
(allowedip->family == AF_INET6 && allowedip->cidr > 128) ||
(allowedip->family == AF_INET && allowedip->cidr > 32))
break; break;
} else if (peer && !strcmp(key, "last_handshake_time_sec")) }
else if (peer && !strcmp(key, "last_handshake_time_sec"))
peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL); peer->last_handshake_time.tv_sec = NUM(0x7fffffffffffffffULL);
else if (peer && !strcmp(key, "last_handshake_time_nsec")) else if (peer && !strcmp(key, "last_handshake_time_nsec"))
peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL); peer->last_handshake_time.tv_nsec = NUM(0x7fffffffffffffffULL);
@ -334,13 +472,13 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
ret = -EPROTO; ret = -EPROTO;
err: err:
free(key); free(key);
if (ret) { if (ret)
{
free_wgdevice(dev); free_wgdevice(dev);
*out = NULL; *out = NULL;
} }
fclose(f); fclose(f);
errno = -ret; errno = -ret;
return ret; return ret;
} }
#undef NUM #undef NUM

View file

@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
int ret = 1; int ret = 1;
if (argc < 3) { 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; return 1;
} }

View file

@ -202,7 +202,7 @@ static char *bytes(uint64_t b)
static const char *COMMAND_NAME; static const char *COMMAND_NAME;
static void show_usage(void) 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) 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); terminal_printf(" " TERMINAL_BOLD "h3" TERMINAL_RESET ": %u\n", device->underload_packet_magic_header);
if (device->transport_packet_magic_header) if (device->transport_packet_magic_header)
terminal_printf(" " TERMINAL_BOLD "h4" TERMINAL_RESET ": %u\n", 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) { if (device->first_peer) {
sort_peers(device); sort_peers(device);
terminal_printf("\n"); 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->response_packet_magic_header);
printf("%u\t", device->underload_packet_magic_header); printf("%u\t", device->underload_packet_magic_header);
printf("%u\t", device->transport_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) if (device->fwmark)
printf("0x%x\n", device->fwmark); printf("0x%x\n", device->fwmark);
else else
@ -374,6 +403,42 @@ static bool ugly_print(struct wgdevice *device, const char *param, bool with_int
if (with_interface) if (with_interface)
printf("%s\t", device->name); printf("%s\t", device->name);
printf("%u\n", device->transport_packet_magic_header); 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")) { } else if (!strcmp(param, "endpoints")) {
for_each_wgpeer(device, peer) { for_each_wgpeer(device, peer) {
if (with_interface) if (with_interface)

View file

@ -64,7 +64,6 @@ int showconf_main(int argc, const char *argv[])
printf("H3 = %u\n", device->underload_packet_magic_header); printf("H3 = %u\n", device->underload_packet_magic_header);
if (device->flags & WGDEVICE_HAS_H4) if (device->flags & WGDEVICE_HAS_H4)
printf("H4 = %u\n", device->transport_packet_magic_header); printf("H4 = %u\n", device->transport_packet_magic_header);
if (device->flags & WGDEVICE_HAS_I1) if (device->flags & WGDEVICE_HAS_I1)
printf("I1 = %s\n", device->i1); printf("I1 = %s\n", device->i1);
if (device->flags & WGDEVICE_HAS_I2) if (device->flags & WGDEVICE_HAS_I2)
@ -82,7 +81,7 @@ int showconf_main(int argc, const char *argv[])
if (device->flags & WGDEVICE_HAS_J3) if (device->flags & WGDEVICE_HAS_J3)
printf("J3 = %s\n", device->j3); printf("J3 = %s\n", device->j3);
if (device->flags & WGDEVICE_HAS_ITIME) if (device->flags & WGDEVICE_HAS_ITIME)
printf("Itime = %s\n", device->itime); printf("Itime = %d\n", device->itime);
printf("\n"); printf("\n");
for_each_wgpeer(device, peer) { for_each_wgpeer(device, peer) {

View file

@ -1278,6 +1278,24 @@ static void parse_options(char **iface, char **config, unsigned int *mtu, char *
is_asecurity_on = true; is_asecurity_on = true;
} else if (!strncasecmp(clean, "H4=", 3) && j > 4) { } else if (!strncasecmp(clean, "H4=", 3) && j > 4) {
is_asecurity_on = true; 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); *config = concat_and_free(*config, "", line);