Commit 62d14e18 authored by Thomas Haller's avatar Thomas Haller

platform/wireguard: rework parsing wireguard links in platform

- previously, parsing wireguard genl data resulted in memory corruption:

  - _wireguard_update_from_allowedips_nla() takes pointers to

      allowedip = &g_array_index (buf->allowedips, NMWireGuardAllowedIP, buf->allowedips->len - 1);

    but resizing the GArray will invalidate this pointer. This happens
    when there are multiple allowed-ips to parse.

  - there was some confusion who owned the allowedips pointers.
    _wireguard_peers_cpy() and _vt_cmd_obj_dispose_lnk_wireguard()
    assumed each peer owned their own chunk, but _wireguard_get_link_properties()
    would not duplicate the memory properly.

- rework memory handling for allowed_ips. Now, the NMPObjectLnkWireGuard
  keeps a pointer _allowed_ips_buf. This buffer contains the instances for
  all peers.
  The parsing of the netlink message is the complicated part, because
  we don't know upfront how many peers/allowed-ips we receive. During
  construction, the tracking of peers/allowed-ips is complicated,
  via a CList/GArray. At the end of that, we prettify the data
  representation and put everything into two buffers. That is more
  efficient and simpler for user afterwards. This moves complexity
  to the way how the object is created, vs. how it is used later.

- ensure that we nm_explicit_bzero() private-key and preshared-key. However,
  that only works to a certain point, because our netlink library does not
  ensure that no data is leaked.

- don't use a "struct sockaddr" union for the peer's endpoint. Instead,
  use a combintation of endpoint_family, endpoint_port, and
  endpoint_addr.

- a lot of refactoring.
parent cb23779e
......@@ -31,31 +31,6 @@ typedef struct {
guint32 to;
} NMVlanQosMapping;
typedef struct {
NMIPAddr ip;
guint8 family;
guint8 mask;
} NMWireGuardAllowedIP;
#define NM_WG_PUBLIC_KEY_LEN 32
#define NM_WG_SYMMETRIC_KEY_LEN 32
typedef struct {
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
guint8 preshared_key[NM_WG_SYMMETRIC_KEY_LEN];
union {
struct sockaddr addr;
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
} endpoint;
guint16 persistent_keepalive_interval;
struct timespec last_handshake_time;
guint64 rx_bytes, tx_bytes;
gsize allowedips_len;
NMWireGuardAllowedIP *allowedips;
} NMWireGuardPeer;
#define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \
( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \
......
......@@ -57,6 +57,11 @@ nm_hash_update (NMHashState *state, const void *ptr, gsize n)
nm_assert (ptr);
nm_assert (n > 0);
/* Note: the data passed in here might be sensitive data (secrets),
* that we should nm_explicty_zero() afterwards. However, since
* we are using siphash24 with a random key, that is not really
* necessary. Something to keep in mind, if we ever move away from
* this hash implementation. */
c_siphash_append (&state->_state, ptr, n);
}
......
This diff is collapsed.
......@@ -5532,67 +5532,57 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize
}
const char *
nm_platform_wireguard_peer_to_string (const NMWireGuardPeer *peer, char *buf, gsize len)
nm_platform_wireguard_peer_to_string (const NMPWireGuardPeer *peer, char *buf, gsize len)
{
gs_free char *public_b64 = NULL;
char s_address[INET6_ADDRSTRLEN] = {0};
char s_endpoint[INET6_ADDRSTRLEN + NI_MAXSERV + sizeof("endpoint []:") + 1] = {0};
guint8 nonzero_key = 0;
gsize i;
gs_free char *public_key_b64 = NULL;
char s_endpoint[NM_UTILS_INET_ADDRSTRLEN + 100];
char s_addr[NM_UTILS_INET_ADDRSTRLEN];
guint i;
nm_utils_to_string_buffer_init (&buf, &len);
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) {
char s_service[NI_MAXSERV];
socklen_t 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, s_address, sizeof(s_address), s_service, sizeof(s_service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) {
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr (s_address, ':'))
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint [%s]:%s ", s_address, s_service);
else
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint %s:%s ", s_address, s_service);
}
}
for (i = 0; i < sizeof (peer->preshared_key); i++)
nonzero_key |= peer->preshared_key[i];
if (peer->endpoint_family == AF_INET) {
nm_sprintf_buf (s_endpoint,
" endpoint %s:%u",
nm_utils_inet4_ntop (peer->endpoint_addr.addr4, s_addr),
(guint) peer->endpoint_port);
} else if (peer->endpoint_family == AF_INET6) {
nm_sprintf_buf (s_endpoint,
" endpoint [%s]:%u",
nm_utils_inet6_ntop (&peer->endpoint_addr.addr6, s_addr),
(guint) peer->endpoint_port);
} else
s_endpoint[0] = '\0';
public_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
public_key_b64 = g_base64_encode (peer->public_key, sizeof (peer->public_key));
nm_utils_strbuf_append (&buf, &len,
"{ "
"public_key %s "
"%s" /* preshared key indicator */
"public-key %s"
"%s" /* preshared-key */
"%s" /* endpoint */
"rx %"G_GUINT64_FORMAT" "
"tx %"G_GUINT64_FORMAT" "
"allowedips (%"G_GSIZE_FORMAT") {",
public_b64,
nonzero_key ? "preshared_key (hidden) " : "",
" rx %"G_GUINT64_FORMAT
" tx %"G_GUINT64_FORMAT
"%s", /* allowed-ips */
public_key_b64,
nm_utils_mem_all_zero (peer->preshared_key, sizeof (peer->preshared_key))
? ""
: " preshared-key (hidden)",
s_endpoint,
peer->rx_bytes,
peer->tx_bytes,
peer->allowedips_len);
for (i = 0; i < peer->allowedips_len; i++) {
NMWireGuardAllowedIP *allowedip = &peer->allowedips[i];
const char *ret;
peer->allowed_ips_len > 0
? " allowed-ips"
: "");
ret = inet_ntop (allowedip->family, &allowedip->ip, s_address, sizeof(s_address));
for (i = 0; i < peer->allowed_ips_len; i++) {
const NMPWireGuardAllowedIP *allowed_ip = &peer->allowed_ips[i];
nm_utils_strbuf_append (&buf, &len,
" %s/%u",
ret ? s_address : "<EAFNOSUPPORT>",
allowedip->mask);
nm_utils_inet_ntop (allowed_ip->family, &allowed_ip->addr, s_addr),
allowed_ip->mask);
}
nm_utils_strbuf_append_str (&buf, &len, " } }");
return buf;
}
......@@ -5600,25 +5590,26 @@ const char *
nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len)
{
gs_free char *public_b64 = NULL;
guint8 nonzero_key = 0;
gsize i;
if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len))
return buf;
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key));
for (i = 0; i < sizeof (lnk->private_key); i++)
nonzero_key |= lnk->private_key[i];
if (!nm_utils_mem_all_zero (lnk->public_key, sizeof (lnk->public_key)))
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key));
g_snprintf (buf, len,
"wireguard "
"public_key %s "
"%s" /* private key indicator */
"listen_port %u "
"fwmark 0x%x",
public_b64,
nonzero_key ? "private_key (hidden) " : "",
"wireguard"
"%s%s" /* public-key */
"%s" /* private-key */
" listen-port %u"
" fwmark 0x%x",
public_b64
? " public-key "
: "",
public_b64 ?: "",
nm_utils_mem_all_zero (lnk->private_key, sizeof (lnk->private_key))
? ""
: " private-key (hidden)",
lnk->listen_port,
lnk->fwmark);
......
......@@ -752,11 +752,14 @@ typedef struct {
bool l3miss:1;
} NMPlatformLnkVxlan;
#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32
#define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32
typedef struct {
guint8 private_key[NM_WG_PUBLIC_KEY_LEN];
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
guint16 listen_port;
guint32 fwmark;
guint16 listen_port;
guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
} NMPlatformLnkWireGuard;
typedef enum {
......@@ -1463,7 +1466,8 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
char *buf,
gsize len);
const char *nm_platform_wireguard_peer_to_string (const NMWireGuardPeer *peer,
struct _NMPWireGuardPeer;
const char *nm_platform_wireguard_peer_to_string (const struct _NMPWireGuardPeer *peer,
char *buf,
gsize len);
......
......@@ -27,6 +27,7 @@
#include <libudev.h>
#include "nm-utils.h"
#include "nm-utils/nm-secret-utils.h"
#include "nm-core-utils.h"
#include "nm-platform-utils.h"
......@@ -347,117 +348,92 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
/*****************************************************************************/
static void
_wireguard_peers_hash_update (gsize n_peers,
const NMWireGuardPeer *peers,
NMHashState *h)
{
gsize i, j;
nm_hash_update_val (h, n_peers);
for (i = 0; i < n_peers; i++) {
const NMWireGuardPeer *p = &peers[i];
nm_hash_update (h, p->public_key, sizeof (p->public_key));
nm_hash_update (h, p->preshared_key, sizeof (p->preshared_key));
nm_hash_update_vals (h,
p->persistent_keepalive_interval,
p->allowedips_len,
p->rx_bytes,
p->tx_bytes,
p->last_handshake_time.tv_sec,
p->last_handshake_time.tv_nsec,
p->endpoint.addr.sa_family);
if (p->endpoint.addr.sa_family == AF_INET)
nm_hash_update_val (h, p->endpoint.addr4);
else if (p->endpoint.addr.sa_family == AF_INET6)
nm_hash_update_val (h, p->endpoint.addr6);
else if (p->endpoint.addr.sa_family != AF_UNSPEC)
g_assert_not_reached ();
for (j = 0; j < p->allowedips_len; j++) {
const NMWireGuardAllowedIP *ip = &p->allowedips[j];
nm_hash_update_vals (h, ip->family, ip->mask);
if (ip->family == AF_INET)
nm_hash_update_val (h, ip->ip.addr4);
else if (ip->family == AF_INET6)
nm_hash_update_val (h, ip->ip.addr6);
else if (ip->family != AF_UNSPEC)
g_assert_not_reached ();
}
}
_wireguard_allowed_ip_hash_update (const NMPWireGuardAllowedIP *ip,
NMHashState *h)
{
nm_hash_update_vals (h, ip->family,
ip->mask);
if (ip->family == AF_INET)
nm_hash_update_val (h, ip->addr.addr4);
else if (ip->family == AF_INET6)
nm_hash_update_val (h, ip->addr.addr6);
}
static int
_wireguard_peers_cmp (gsize n_peers,
const NMWireGuardPeer *p1,
const NMWireGuardPeer *p2)
{
gsize i, j;
for (i = 0; i < n_peers; i++) {
const NMWireGuardPeer *a = &p1[i];
const NMWireGuardPeer *b = &p2[i];
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec);
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec);
NM_CMP_FIELD (a, b, rx_bytes);
NM_CMP_FIELD (a, b, tx_bytes);
NM_CMP_FIELD (a, b, allowedips_len);
NM_CMP_FIELD (a, b, persistent_keepalive_interval);
NM_CMP_FIELD (a, b, endpoint.addr.sa_family);
NM_CMP_FIELD_MEMCMP (a, b, public_key);
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
if (a->endpoint.addr.sa_family == AF_INET)
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr4);
else if (a->endpoint.addr.sa_family == AF_INET6)
NM_CMP_FIELD_MEMCMP (a, b, endpoint.addr6);
else if (a->endpoint.addr.sa_family != AF_UNSPEC)
g_assert_not_reached ();
for (j = 0; j < a->allowedips_len; j++) {
const NMWireGuardAllowedIP *aip = &a->allowedips[j];
const NMWireGuardAllowedIP *bip = &b->allowedips[j];
NM_CMP_FIELD (aip, bip, family);
NM_CMP_FIELD (aip, bip, mask);
if (aip->family == AF_INET)
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr4);
else if (aip->family == AF_INET6)
NM_CMP_FIELD_MEMCMP (&aip->ip, &bip->ip, addr6);
else if (aip->family != AF_UNSPEC)
g_assert_not_reached ();
}
}
_wireguard_allowed_ip_cmp (const NMPWireGuardAllowedIP *a,
const NMPWireGuardAllowedIP *b)
{
NM_CMP_SELF (a, b);
NM_CMP_FIELD (a, b, family);
NM_CMP_FIELD (a, b, mask);
if (a->family == AF_INET)
NM_CMP_FIELD (a, b, addr.addr4);
else if (a->family == AF_INET6)
NM_CMP_FIELD_IN6ADDR (a, b, addr.addr6);
return 0;
}
static void
_wireguard_peers_cpy (gsize *dst_n_peers,
NMWireGuardPeer **dst_peers,
gsize src_n_peers,
const NMWireGuardPeer *src_peers)
{
if (src_n_peers == 0) {
g_clear_pointer (dst_peers, g_free);
*dst_n_peers = 0;
} else if ( src_n_peers != *dst_n_peers
|| _wireguard_peers_cmp (src_n_peers, *dst_peers, src_peers) != 0) {
gsize i;
g_clear_pointer (dst_peers, g_free);
*dst_n_peers = src_n_peers;
if (src_n_peers > 0)
*dst_peers = nm_memdup (src_peers, sizeof (*src_peers) * src_n_peers);
for (i = 0; i < src_n_peers; i++) {
dst_peers[i]->allowedips = nm_memdup (src_peers[i].allowedips, sizeof (src_peers[i].allowedips) * src_peers[i].allowedips_len);
dst_peers[i]->allowedips_len = src_peers[i].allowedips_len;
}
_wireguard_peer_hash_update (const NMPWireGuardPeer *peer,
NMHashState *h)
{
guint i;
nm_hash_update (h, peer->public_key, sizeof (peer->public_key));
nm_hash_update (h, peer->preshared_key, sizeof (peer->preshared_key));
nm_hash_update_vals (h,
peer->persistent_keepalive_interval,
peer->allowed_ips_len,
peer->rx_bytes,
peer->tx_bytes,
peer->last_handshake_time.tv_sec,
peer->last_handshake_time.tv_nsec,
peer->endpoint_port,
peer->endpoint_family);
if (peer->endpoint_family == AF_INET)
nm_hash_update_val (h, peer->endpoint_addr.addr4);
else if (peer->endpoint_family == AF_INET6)
nm_hash_update_val (h, peer->endpoint_addr.addr6);
for (i = 0; i < peer->allowed_ips_len; i++)
_wireguard_allowed_ip_hash_update (&peer->allowed_ips[i], h);
}
static int
_wireguard_peer_cmp (const NMPWireGuardPeer *a,
const NMPWireGuardPeer *b)
{
guint i;
NM_CMP_SELF (a, b);
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec);
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec);
NM_CMP_FIELD (a, b, rx_bytes);
NM_CMP_FIELD (a, b, tx_bytes);
NM_CMP_FIELD (a, b, allowed_ips_len);
NM_CMP_FIELD (a, b, persistent_keepalive_interval);
NM_CMP_FIELD (a, b, endpoint_port);
NM_CMP_FIELD (a, b, endpoint_family);
NM_CMP_FIELD_MEMCMP (a, b, public_key);
NM_CMP_FIELD_MEMCMP (a, b, preshared_key);
if (a->endpoint_family == AF_INET)
NM_CMP_FIELD (a, b, endpoint_addr.addr4);
else if (a->endpoint_family == AF_INET6)
NM_CMP_FIELD_IN6ADDR (a, b, endpoint_addr.addr6);
for (i = 0; i < a->allowed_ips_len; i++) {
NM_CMP_RETURN (_wireguard_allowed_ip_cmp (&a->allowed_ips[i],
&b->allowed_ips[i]));
}
return 0;
}
/*****************************************************************************/
......@@ -587,12 +563,25 @@ _vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj)
}
static void
_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj)
_wireguard_clear (NMPObjectLnkWireGuard *lnk)
{
if (obj->_lnk_wireguard.peers_len)
g_free (obj->_lnk_wireguard.peers[0].allowedips);
guint i;
nm_explicit_bzero (lnk->_public.private_key,
sizeof (lnk->_public.private_key));
for (i = 0; i < lnk->peers_len; i++) {
NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &lnk->peers[i];
nm_explicit_bzero (peer->preshared_key, sizeof (peer->preshared_key));
}
g_free ((gpointer) lnk->peers);
g_free ((gpointer) lnk->_allowed_ips_buf);
}
g_free (obj->_lnk_wireguard.peers);
static void
_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj)
{
_wireguard_clear (&obj->_lnk_wireguard);
}
static NMPObject *
......@@ -859,7 +848,7 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
const NMPClass *klass;
char buf2[sizeof (_nm_utils_to_string_buffer)];
char *b;
gsize i, l;
guint i;
klass = NMP_OBJECT_GET_CLASS (obj);
......@@ -871,23 +860,26 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
b = buf;
nm_utils_strbuf_append (&b, &buf_size,
"[%s,%p,%u,%calive,%cvisible; %s "
"peers (%" G_GSIZE_FORMAT ") {",
"[%s,%p,%u,%calive,%cvisible; %s"
"%s",
klass->obj_type_name, obj, obj->parent._ref_count,
nmp_object_is_alive (obj) ? '+' : '-',
nmp_object_is_visible (obj) ? '+' : '-',
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)),
obj->_lnk_wireguard.peers_len);
obj->_lnk_wireguard.peers_len > 0
? " peers {"
: "");
for (i = 0; i < obj->_lnk_wireguard.peers_len; i++) {
const NMWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i];
const NMPWireGuardPeer *peer = &obj->_lnk_wireguard.peers[i];
nm_utils_strbuf_append_str (&b, &buf_size, " { ");
nm_platform_wireguard_peer_to_string (peer, b, buf_size);
l = strlen (b);
b += l;
buf_size -= l;
nm_utils_strbuf_seek_end (&b, &buf_size);
nm_utils_strbuf_append_str (&b, &buf_size, " }");
}
nm_utils_strbuf_append_str (&b, &buf_size, " }");
if (obj->_lnk_wireguard.peers_len)
nm_utils_strbuf_append_str (&b, &buf_size, " }");
return buf;
case NMP_OBJECT_TO_STRING_PUBLIC:
......@@ -947,6 +939,7 @@ _vt_cmd_obj_hash_update_link (const NMPObject *obj, NMHashState *h)
nm_platform_link_hash_update (&obj->link, h);
nm_hash_update_vals (h,
obj->_link.netlink.is_in_netlink,
obj->_link.wireguard_family_id,
obj->_link.udev.device);
if (obj->_link.netlink.lnk)
nmp_object_hash_update (obj->_link.netlink.lnk, h);
......@@ -969,10 +962,15 @@ _vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h)
static void
_vt_cmd_obj_hash_update_lnk_wireguard (const NMPObject *obj, NMHashState *h)
{
guint i;
nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD);
nm_platform_lnk_wireguard_hash_update (&obj->lnk_wireguard, h);
_wireguard_peers_hash_update (obj->_lnk_wireguard.peers_len, obj->_lnk_wireguard.peers, h);
nm_hash_update_val (h, obj->_lnk_wireguard.peers_len);
for (i = 0; i < obj->_lnk_wireguard.peers_len; i++)
_wireguard_peer_hash_update (&obj->_lnk_wireguard.peers[i], h);
}
int
......@@ -980,12 +978,7 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
{
const NMPClass *klass1, *klass2;
if (obj1 == obj2)
return 0;
if (!obj1)
return -1;
if (!obj2)
return 1;
NM_CMP_SELF (obj1, obj2);
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), -1);
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj2), 1);
......@@ -1006,16 +999,11 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
static int
_vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2)
{
int i;
NM_CMP_RETURN (nm_platform_link_cmp (&obj1->link, &obj2->link));
NM_CMP_DIRECT (obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink);
NM_CMP_RETURN (nmp_object_cmp (obj1->_link.netlink.lnk, obj2->_link.netlink.lnk));
NM_CMP_DIRECT (obj1->_link.wireguard_family_id, obj2->_link.wireguard_family_id);
i = nm_platform_link_cmp (&obj1->link, &obj2->link);
if (i)
return i;
if (obj1->_link.netlink.is_in_netlink != obj2->_link.netlink.is_in_netlink)
return obj1->_link.netlink.is_in_netlink ? -1 : 1;
i = nmp_object_cmp (obj1->_link.netlink.lnk, obj2->_link.netlink.lnk);
if (i)
return i;
if (obj1->_link.udev.device != obj2->_link.udev.device) {
if (!obj1->_link.udev.device)
return -1;
......@@ -1028,6 +1016,7 @@ _vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2)
* Have this check as very last. */
return (obj1->_link.udev.device < obj2->_link.udev.device) ? -1 : 1;
}
return 0;
}
......@@ -1056,16 +1045,16 @@ _vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2)
static int
_vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2)
{
int c;
guint i;
c = nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard);
if (c)
return c;
NM_CMP_RETURN (nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard));
NM_CMP_FIELD (obj1, obj2, _lnk_wireguard.peers_len);
if (obj1->_lnk_wireguard.peers_len != obj2->_lnk_wireguard.peers_len)
return obj1->_lnk_wireguard.peers_len < obj2->_lnk_wireguard.peers_len ? -1 : 1;
for (i = 0; i < obj1->_lnk_wireguard.peers_len; i++)
NM_CMP_RETURN (_wireguard_peer_cmp (&obj1->_lnk_wireguard.peers[i], &obj2->_lnk_wireguard.peers[i]));
return _wireguard_peers_cmp(obj1->_lnk_wireguard.peers_len, obj1->_lnk_wireguard.peers, obj2->_lnk_wireguard.peers);
return 0;
}
/* @src is a const object, which is not entirely correct for link types, where
......@@ -1137,9 +1126,36 @@ _vt_cmd_obj_copy_lnk_vlan (NMPObject *dst, const NMPObject *src)
static void
_vt_cmd_obj_copy_lnk_wireguard (NMPObject *dst, const NMPObject *src)
{
dst->lnk_wireguard = src->lnk_wireguard;
_wireguard_peers_cpy (&dst->_lnk_wireguard.peers_len, &dst->_lnk_wireguard.peers,
src->_lnk_wireguard.peers_len, src->_lnk_wireguard.peers);
guint i;
nm_assert (dst != src);
_wireguard_clear (&dst->_lnk_wireguard);
dst->_lnk_wireguard = src->_lnk_wireguard;
dst->_lnk_wireguard.peers = nm_memdup (dst->_lnk_wireguard.peers,
sizeof (NMPWireGuardPeer) * dst->_lnk_wireguard.peers_len);
dst->_lnk_wireguard._allowed_ips_buf = nm_memdup (dst->_lnk_wireguard._allowed_ips_buf,
sizeof (NMPWireGuardAllowedIP) * dst->_lnk_wireguard._allowed_ips_buf_len);
/* all the peers' pointers point into the buffer. They need to be readjusted. */
for (i = 0; i < dst->_lnk_wireguard.peers_len; i++) {
NMPWireGuardPeer *peer = (NMPWireGuardPeer *) &dst->_lnk_wireguard.peers[i];
if (peer->allowed_ips_len == 0) {
nm_assert (!peer->allowed_ips);
continue;
}
nm_assert (dst->_lnk_wireguard._allowed_ips_buf_len > 0);
nm_assert (src->_lnk_wireguard._allowed_ips_buf);
nm_assert (peer->allowed_ips >= src->_lnk_wireguard._allowed_ips_buf);
nm_assert (&peer->allowed_ips[peer->allowed_ips_len] <= &src->_lnk_wireguard._allowed_ips_buf[src->_lnk_wireguard._allowed_ips_buf_len]);
peer->allowed_ips = &dst->_lnk_wireguard._allowed_ips_buf[peer->allowed_ips - src->_lnk_wireguard._allowed_ips_buf];
}
nm_assert (nmp_object_equal (src, dst));
}
#define _vt_cmd_plobj_id_copy(type, plat_type, cmd) \
...