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 { ...@@ -31,31 +31,6 @@ typedef struct {
guint32 to; guint32 to;
} NMVlanQosMapping; } 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 \ #define _NM_IP_TUNNEL_FLAG_ALL_IP6TNL \
( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \ ( NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT \
| NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \ | NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS \
......
...@@ -57,6 +57,11 @@ nm_hash_update (NMHashState *state, const void *ptr, gsize n) ...@@ -57,6 +57,11 @@ nm_hash_update (NMHashState *state, const void *ptr, gsize n)
nm_assert (ptr); nm_assert (ptr);
nm_assert (n > 0); 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); 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 ...@@ -5532,67 +5532,57 @@ nm_platform_lnk_vxlan_to_string (const NMPlatformLnkVxlan *lnk, char *buf, gsize
} }
const char * 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; gs_free char *public_key_b64 = NULL;
char s_address[INET6_ADDRSTRLEN] = {0}; char s_endpoint[NM_UTILS_INET_ADDRSTRLEN + 100];
char s_endpoint[INET6_ADDRSTRLEN + NI_MAXSERV + sizeof("endpoint []:") + 1] = {0}; char s_addr[NM_UTILS_INET_ADDRSTRLEN];
guint8 nonzero_key = 0; guint i;
gsize i;
nm_utils_to_string_buffer_init (&buf, &len); nm_utils_to_string_buffer_init (&buf, &len);
if (peer->endpoint.addr.sa_family == AF_INET || peer->endpoint.addr.sa_family == AF_INET6) { if (peer->endpoint_family == AF_INET) {
char s_service[NI_MAXSERV]; nm_sprintf_buf (s_endpoint,
socklen_t addr_len = 0; " endpoint %s:%u",
nm_utils_inet4_ntop (peer->endpoint_addr.addr4, s_addr),
if (peer->endpoint.addr.sa_family == AF_INET) (guint) peer->endpoint_port);
addr_len = sizeof (struct sockaddr_in); } else if (peer->endpoint_family == AF_INET6) {
else if (peer->endpoint.addr.sa_family == AF_INET6) nm_sprintf_buf (s_endpoint,
addr_len = sizeof (struct sockaddr_in6); " endpoint [%s]:%u",
if (!getnameinfo (&peer->endpoint.addr, addr_len, s_address, sizeof(s_address), s_service, sizeof(s_service), NI_DGRAM | NI_NUMERICSERV | NI_NUMERICHOST)) { nm_utils_inet6_ntop (&peer->endpoint_addr.addr6, s_addr),
if (peer->endpoint.addr.sa_family == AF_INET6 && strchr (s_address, ':')) (guint) peer->endpoint_port);
g_snprintf(s_endpoint, sizeof (s_endpoint), "endpoint [%s]:%s ", s_address, s_service); } else
else s_endpoint[0] = '\0';
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];
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, nm_utils_strbuf_append (&buf, &len,
"{ " "public-key %s"
"public_key %s " "%s" /* preshared-key */
"%s" /* preshared key indicator */
"%s" /* endpoint */ "%s" /* endpoint */
"rx %"G_GUINT64_FORMAT" " " rx %"G_GUINT64_FORMAT
"tx %"G_GUINT64_FORMAT" " " tx %"G_GUINT64_FORMAT
"allowedips (%"G_GSIZE_FORMAT") {", "%s", /* allowed-ips */
public_b64, public_key_b64,
nonzero_key ? "preshared_key (hidden) " : "", nm_utils_mem_all_zero (peer->preshared_key, sizeof (peer->preshared_key))
? ""
: " preshared-key (hidden)",
s_endpoint, s_endpoint,
peer->rx_bytes, peer->rx_bytes,
peer->tx_bytes, peer->tx_bytes,
peer->allowedips_len); peer->allowed_ips_len > 0
? " allowed-ips"
: "");
for (i = 0; i < peer->allowedips_len; i++) {
NMWireGuardAllowedIP *allowedip = &peer->allowedips[i];
const char *ret;
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, nm_utils_strbuf_append (&buf, &len,
" %s/%u", " %s/%u",
ret ? s_address : "<EAFNOSUPPORT>", nm_utils_inet_ntop (allowed_ip->family, &allowed_ip->addr, s_addr),
allowedip->mask); allowed_ip->mask);
} }
nm_utils_strbuf_append_str (&buf, &len, " } }");
return buf; return buf;
} }
...@@ -5600,25 +5590,26 @@ const char * ...@@ -5600,25 +5590,26 @@ const char *
nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len) nm_platform_lnk_wireguard_to_string (const NMPlatformLnkWireGuard *lnk, char *buf, gsize len)
{ {
gs_free char *public_b64 = NULL; gs_free char *public_b64 = NULL;
guint8 nonzero_key = 0;
gsize i;
if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len)) if (!nm_utils_to_string_buffer_init_null (lnk, &buf, &len))
return buf; return buf;
public_b64 = g_base64_encode (lnk->public_key, sizeof (lnk->public_key)); 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));
for (i = 0; i < sizeof (lnk->private_key); i++)
nonzero_key |= lnk->private_key[i];
g_snprintf (buf, len, g_snprintf (buf, len,
"wireguard " "wireguard"
"public_key %s " "%s%s" /* public-key */
"%s" /* private key indicator */ "%s" /* private-key */
"listen_port %u " " listen-port %u"
"fwmark 0x%x", " fwmark 0x%x",
public_b64, public_b64
nonzero_key ? "private_key (hidden) " : "", ? " public-key "
: "",
public_b64 ?: "",
nm_utils_mem_all_zero (lnk->private_key, sizeof (lnk->private_key))
? ""
: " private-key (hidden)",
lnk->listen_port, lnk->listen_port,
lnk->fwmark); lnk->fwmark);
......
...@@ -752,11 +752,14 @@ typedef struct { ...@@ -752,11 +752,14 @@ typedef struct {
bool l3miss:1; bool l3miss:1;
} NMPlatformLnkVxlan; } NMPlatformLnkVxlan;
#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32
#define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32
typedef struct { typedef struct {
guint8 private_key[NM_WG_PUBLIC_KEY_LEN];
guint8 public_key[NM_WG_PUBLIC_KEY_LEN];
guint16 listen_port;
guint32 fwmark; guint32 fwmark;
guint16 listen_port;
guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
} NMPlatformLnkWireGuard; } NMPlatformLnkWireGuard;
typedef enum { typedef enum {
...@@ -1463,7 +1466,8 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name, ...@@ -1463,7 +1466,8 @@ const char *nm_platform_vlan_qos_mapping_to_string (const char *name,
char *buf, char *buf,
gsize len); 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, char *buf,
gsize len); gsize len);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <libudev.h> #include <libudev.h>
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-utils/nm-secret-utils.h"
#include "nm-core-utils.h" #include "nm-core-utils.h"
#include "nm-platform-utils.h" #include "nm-platform-utils.h"
...@@ -347,117 +348,92 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map, ...@@ -347,117 +348,92 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
/*****************************************************************************/ /*****************************************************************************/
static void static void
_wireguard_peers_hash_update (gsize n_peers, _wireguard_allowed_ip_hash_update (const NMPWireGuardAllowedIP *ip,
const NMWireGuardPeer *peers, NMHashState *h)
NMHashState *h) {
{ nm_hash_update_vals (h, ip->family,
gsize i, j; ip->mask);
nm_hash_update_val (h, n_peers); if (ip->family == AF_INET)
for (i = 0; i < n_peers; i++) { nm_hash_update_val (h, ip->addr.addr4);
const NMWireGuardPeer *p = &peers[i]; else if (ip->family == AF_INET6)
nm_hash_update_val (h, ip->addr.addr6);
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 ();
}
}
} }
static int static int
_wireguard_peers_cmp (gsize n_peers, _wireguard_allowed_ip_cmp (const NMPWireGuardAllowedIP *a,
const NMWireGuardPeer *p1, const NMPWireGuardAllowedIP *b)
const NMWireGuardPeer *p2) {
{ NM_CMP_SELF (a, b);
gsize i, j;
NM_CMP_FIELD (a, b, family);
for (i = 0; i < n_peers; i++) { NM_CMP_FIELD (a, b, mask);
const NMWireGuardPeer *a = &p1[i];
const NMWireGuardPeer *b = &p2[i]; if (a->family == AF_INET)
NM_CMP_FIELD (a, b, addr.addr4);
NM_CMP_FIELD (a, b, last_handshake_time.tv_sec); else if (a->family == AF_INET6)
NM_CMP_FIELD (a, b, last_handshake_time.tv_nsec); NM_CMP_FIELD_IN6ADDR (a, b, addr.addr6);
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 ();
}
}
return 0; return 0;
} }
static void static void
_wireguard_peers_cpy (gsize *dst_n_peers, _wireguard_peer_hash_update (const NMPWireGuardPeer *peer,
NMWireGuardPeer **dst_peers, NMHashState *h)
gsize src_n_peers, {
const NMWireGuardPeer *src_peers) guint i;
{
if (src_n_peers == 0) { nm_hash_update (h, peer->public_key, sizeof (peer->public_key));
g_clear_pointer (dst_peers, g_free); nm_hash_update (h, peer->preshared_key, sizeof (peer->preshared_key));
*dst_n_peers = 0; nm_hash_update_vals (h,
} else if ( src_n_peers != *dst_n_peers peer->persistent_keepalive_interval,
|| _wireguard_peers_cmp (src_n_peers, *dst_peers, src_peers) != 0) { peer->allowed_ips_len,
gsize i; peer->rx_bytes,
g_clear_pointer (dst_peers, g_free); peer->tx_bytes,
*dst_n_peers = src_n_peers; peer->last_handshake_time.tv_sec,
if (src_n_peers > 0) peer->last_handshake_time.tv_nsec,
*dst_peers = nm_memdup (src_peers, sizeof (*src_peers) * src_n_peers); peer->endpoint_port,
for (i = 0; i < src_n_peers; i++) { peer->endpoint_family);
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; 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) ...@@ -587,12 +563,25 @@ _vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj)
} }
static void static void
_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj) _wireguard_clear (NMPObjectLnkWireGuard *lnk)
{ {
if (obj->_lnk_wireguard.peers_len) guint i;
g_free (obj->_lnk_wireguard.peers[0].allowedips);
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 * static NMPObject *
...@@ -859,7 +848,7 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode ...@@ -859,7 +848,7 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
const NMPClass *klass; const NMPClass *klass;
char buf2[sizeof (_nm_utils_to_string_buffer)]; char buf2[sizeof (_nm_utils_to_string_buffer)];
char *b; char *b;
gsize i, l; guint i;
klass = NMP_OBJECT_GET_CLASS (obj); klass = NMP_OBJECT_GET_CLASS (obj);
...@@ -871,23 +860,26 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode ...@@ -871,23 +860,26 @@ _vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode
b = buf; b = buf;
nm_utils_strbuf_append (&b, &buf_size, nm_utils_strbuf_append (&b, &buf_size,
"[%s,%p,%u,%calive,%cvisible; %s " "[%s,%p,%u,%calive,%cvisible; %s"
"peers (%" G_GSIZE_FORMAT ") {", "%s",
klass->obj_type_name, obj, obj->parent._ref_count, klass->obj_type_name, obj, obj->parent._ref_count,
nmp_object_is_alive (obj) ? '+' : '-', nmp_object_is_alive (obj) ? '+' : '-',
nmp_object_is_visible (obj) ? '+' : '-', nmp_object_is_visible (obj) ? '+' : '-',
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)), 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++) { 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); nm_platform_wireguard_peer_to_string (peer, b, buf_size);
l = strlen (b); nm_utils_strbuf_seek_end (&b, &buf_size);
b += l; nm_utils_strbuf_append_str (&b, &buf_size, " }");
buf_size -= l;
} }
if (obj->_lnk_wireguard.peers_len)
nm_utils_strbuf_append_str (&b, &buf_size, " }"); nm_utils_strbuf_append_str (&b, &buf_size, " }");
return buf; return buf;
case NMP_OBJECT_TO_STRING_PUBLIC: case NMP_OBJECT_TO_STRING_PUBLIC:
...@@ -947,6 +939,7 @@ _vt_cmd_obj_hash_update_link (const NMPObject *obj, NMHashState *h) ...@@ -947,6 +939,7 @@ _vt_cmd_obj_hash_update_link (const NMPObject *obj, NMHashState *h)
nm_platform_link_hash_update (&obj->link, h); nm_platform_link_hash_update (&obj->link, h);
nm_hash_update_vals (h, nm_hash_update_vals (h,
obj->_link.netlink.is_in_netlink, obj->_link.netlink.is_in_netlink,
obj->_link.wireguard_family_id,
obj->_link.udev.device); obj->_link.udev.device);
if (obj->_link.netlink.lnk) if (obj->_link.netlink.lnk)
nmp_object_hash_update (obj->_link.netlink.lnk, h); 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) ...@@ -969,10 +962,15 @@ _vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h)
static void static void
_vt_cmd_obj_hash_update_lnk_wireguard (const NMPObject *obj, NMHashState *h) _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_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD);
nm_platform_lnk_wireguard_hash_update (&obj->lnk_wireguard, h); 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 int
...@@ -980,12 +978,7 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2) ...@@ -980,12 +978,7 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
{ {
const NMPClass *klass1, *klass2; const NMPClass *klass1, *klass2;
if (obj1 == obj2) NM_CMP_SELF (obj1, obj2);
return 0;
if (!obj1)
return -1;
if (!obj2)
return 1;
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), -1); g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj1), -1);
g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj2), 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) ...@@ -1006,16 +999,11 @@ nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2)
static int static int
_vt_cmd_obj_cmp_link (const NMPObject *obj1, const NMPObject *obj2) _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));