summary refs log tree commit diff
path: root/src/platform/nmp-object.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-10-20 01:30:31 +0200
committerMichael Biebl <biebl@debian.org>2018-10-20 01:30:31 +0200
commit6518e361171f64bcaaa4bf868139362ed95cc2e0 (patch)
treed2d5b53faf80646a40ec2c0c7f2a42b3959612f5 /src/platform/nmp-object.c
parente126f3e804c35480c4f075777430419d6ece23da (diff)
New upstream version 1.14.2 upstream/1.14.2
Diffstat (limited to 'src/platform/nmp-object.c')
-rw-r--r--src/platform/nmp-object.c351
1 files changed, 316 insertions, 35 deletions
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 50e6825b..fdc27440 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2015 - 2017 Red Hat, Inc.
+ * Copyright (C) 2015 - 2018 Red Hat, Inc.
  */
 
 #include "nm-default.h"
@@ -27,10 +27,14 @@
 #include <libudev.h>
 
 #include "nm-utils.h"
+#include "nm-utils/nm-secret-utils.h"
 
 #include "nm-core-utils.h"
 #include "nm-platform-utils.h"
 
+#include "wifi/nm-wifi-utils.h"
+#include "wpan/nm-wpan-utils.h"
+
 /*****************************************************************************/
 
 #define _NMLOG_DOMAIN LOGD_PLATFORM
@@ -337,12 +341,103 @@ _vlan_xgress_qos_mappings_cpy (guint *dst_n_map,
 		g_clear_pointer (dst_map, g_free);
 		*dst_n_map = src_n_map;
 		if (src_n_map > 0)
-			*dst_map = g_memdup (src_map, sizeof (*src_map) * src_n_map);
+			*dst_map = nm_memdup (src_map, sizeof (*src_map) * src_n_map);
 	}
 }
 
 /*****************************************************************************/
 
+static void
+_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_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_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;
+}
+
+/*****************************************************************************/
+
 static const char *
 _link_get_driver (struct udev_device *udevice, const char *kind, int ifindex)
 {
@@ -456,6 +551,7 @@ _vt_cmd_obj_dispose_link (NMPObject *obj)
 		udev_device_unref (obj->_link.udev.device);
 		obj->_link.udev.device = NULL;
 	}
+	g_clear_object (&obj->_link.ext_data);
 	nmp_object_unref (obj->_link.netlink.lnk);
 }
 
@@ -466,6 +562,28 @@ _vt_cmd_obj_dispose_lnk_vlan (NMPObject *obj)
 	g_free ((gpointer) obj->_lnk_vlan.egress_qos_map);
 }
 
+static void
+_wireguard_clear (NMPObjectLnkWireGuard *lnk)
+{
+	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);
+}
+
+static void
+_vt_cmd_obj_dispose_lnk_wireguard (NMPObject *obj)
+{
+	_wireguard_clear (&obj->_lnk_wireguard);
+}
+
 static NMPObject *
 _nmp_object_new_from_class (const NMPClass *klass)
 {
@@ -631,31 +749,35 @@ static const char *
 _vt_cmd_obj_to_string_link (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size)
 {
 	const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
-	char buf2[sizeof (_nm_utils_to_string_buffer)];
-	char buf3[sizeof (_nm_utils_to_string_buffer)];
+	char *b = buf;
 
 	switch (to_string_mode) {
 	case NMP_OBJECT_TO_STRING_ID:
 		return klass->cmd_plobj_to_string_id (&obj->object, buf, buf_size);
 	case NMP_OBJECT_TO_STRING_ALL:
-		g_snprintf (buf, buf_size,
-		            "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; %s]",
-		            klass->obj_type_name, obj, obj->parent._ref_count,
-		            nmp_object_is_alive (obj) ? '+' : '-',
-		            nmp_object_is_visible (obj) ? '+' : '-',
-		            obj->_link.netlink.is_in_netlink ? '+' : '-',
-		            obj->_link.udev.device,
-		            nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_PUBLIC, buf2, sizeof (buf2)));
+		nm_utils_strbuf_append (&b, &buf_size,
+		                        "[%s,%p,%u,%calive,%cvisible,%cin-nl,%p; ",
+		                        klass->obj_type_name, obj, obj->parent._ref_count,
+		                        nmp_object_is_alive (obj) ? '+' : '-',
+		                        nmp_object_is_visible (obj) ? '+' : '-',
+		                        obj->_link.netlink.is_in_netlink ? '+' : '-',
+		                        obj->_link.udev.device);
+		NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size);
+		nm_utils_strbuf_seek_end (&b, &buf_size);
+		if (obj->_link.netlink.lnk) {
+			nm_utils_strbuf_append_str (&b, &buf_size, "; ");
+			nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_ALL, b, buf_size);
+			nm_utils_strbuf_seek_end (&b, &buf_size);
+		}
+		nm_utils_strbuf_append_c (&b, &buf_size, ']');
 		return buf;
 	case NMP_OBJECT_TO_STRING_PUBLIC:
+		NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, b, buf_size);
 		if (obj->_link.netlink.lnk) {
-			NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf2, sizeof (buf2));
-			nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, buf3, sizeof (buf3));
-			g_snprintf (buf, buf_size,
-			            "%s; %s",
-			            buf2, buf3);
-		} else
-			NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size);
+			nm_utils_strbuf_seek_end (&b, &buf_size);
+			nm_utils_strbuf_append_str (&b, &buf_size, "; ");
+			nmp_object_to_string (obj->_link.netlink.lnk, NMP_OBJECT_TO_STRING_PUBLIC, b, buf_size);
+		}
 		return buf;
 	default:
 		g_return_val_if_reached ("ERROR");
@@ -720,6 +842,55 @@ _vt_cmd_obj_to_string_lnk_vlan (const NMPObject *obj, NMPObjectToStringMode to_s
 	}
 }
 
+static const char *
+_vt_cmd_obj_to_string_lnk_wireguard (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size)
+{
+	const NMPClass *klass;
+	char buf2[sizeof (_nm_utils_to_string_buffer)];
+	char *b;
+	guint i;
+
+	klass = NMP_OBJECT_GET_CLASS (obj);
+
+	switch (to_string_mode) {
+	case NMP_OBJECT_TO_STRING_ID:
+		g_snprintf (buf, buf_size, "%p", obj);
+		return buf;
+	case NMP_OBJECT_TO_STRING_ALL:
+		b = buf;
+
+		nm_utils_strbuf_append (&b, &buf_size,
+		                        "[%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 > 0
+		                          ? " peers {"
+		                          : "");
+
+		for (i = 0; i < obj->_lnk_wireguard.peers_len; 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_utils_strbuf_seek_end (&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:
+		NMP_OBJECT_GET_CLASS (obj)->cmd_plobj_to_string (&obj->object, buf, buf_size);
+
+		return buf;
+	default:
+		g_return_val_if_reached ("ERROR");
+	}
+}
+
 #define _vt_cmd_plobj_to_string_id(type, plat_type, ...) \
 static const char * \
 _vt_cmd_plobj_to_string_id_##type (const NMPlatformObject *_obj, char *buf, gsize buf_len) \
@@ -768,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);
@@ -787,17 +959,26 @@ _vt_cmd_obj_hash_update_lnk_vlan (const NMPObject *obj, NMHashState *h)
 	                                       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);
+
+	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
 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);
@@ -818,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;
@@ -840,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;
 }
 
@@ -865,6 +1042,21 @@ _vt_cmd_obj_cmp_lnk_vlan (const NMPObject *obj1, const NMPObject *obj2)
 	return c;
 }
 
+static int
+_vt_cmd_obj_cmp_lnk_wireguard (const NMPObject *obj1, const NMPObject *obj2)
+{
+	guint i;
+
+	NM_CMP_RETURN (nm_platform_lnk_wireguard_cmp (&obj1->lnk_wireguard, &obj2->lnk_wireguard));
+
+	NM_CMP_FIELD (obj1, obj2, _lnk_wireguard.peers_len);
+
+	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 0;
+}
+
 /* @src is a const object, which is not entirely correct for link types, where
  * we increase the ref count for src->_link.udev.device.
  * Hence, nmp_object_copy() can violate the const promise of @src.
@@ -908,6 +1100,12 @@ _vt_cmd_obj_copy_link (NMPObject *dst, const NMPObject *src)
 			nmp_object_unref (dst->_link.netlink.lnk);
 		dst->_link.netlink.lnk = src->_link.netlink.lnk;
 	}
+	if (dst->_link.ext_data != src->_link.ext_data) {
+		if (dst->_link.ext_data)
+			g_clear_object (&dst->_link.ext_data);
+		if (src->_link.ext_data)
+			dst->_link.ext_data = g_object_ref (src->_link.ext_data);
+	}
 	dst->_link = src->_link;
 }
 
@@ -925,6 +1123,41 @@ _vt_cmd_obj_copy_lnk_vlan (NMPObject *dst, const NMPObject *src)
 	                               src->_lnk_vlan.egress_qos_map);
 }
 
+static void
+_vt_cmd_obj_copy_lnk_wireguard (NMPObject *dst, const NMPObject *src)
+{
+	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) \
 static void \
 _vt_cmd_plobj_id_copy_##type (NMPlatformObject *_dst, const NMPlatformObject *_src) \
@@ -2702,6 +2935,17 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update,
 		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
 	},
+	[NMP_OBJECT_TYPE_LNK_GRETAP - 1] = {
+		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
+		.obj_type                           = NMP_OBJECT_TYPE_LNK_GRETAP,
+		.sizeof_data                        = sizeof (NMPObjectLnkGre),
+		.sizeof_public                      = sizeof (NMPlatformLnkGre),
+		.obj_type_name                      = "gretap",
+		.lnk_link_type                      = NM_LINK_TYPE_GRETAP,
+		.cmd_plobj_to_string                = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_gre_to_string,
+		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_gre_hash_update,
+		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_gre_cmp,
+	},
 	[NMP_OBJECT_TYPE_LNK_INFINIBAND - 1] = {
 		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
 		.obj_type                           = NMP_OBJECT_TYPE_LNK_INFINIBAND,
@@ -2724,6 +2968,28 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update,
 		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp,
 	},
+	[NMP_OBJECT_TYPE_LNK_IP6GRE - 1] = {
+		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
+		.obj_type                           = NMP_OBJECT_TYPE_LNK_IP6GRE,
+		.sizeof_data                        = sizeof (NMPObjectLnkIp6Tnl),
+		.sizeof_public                      = sizeof (NMPlatformLnkIp6Tnl),
+		.obj_type_name                      = "ip6gre",
+		.lnk_link_type                      = NM_LINK_TYPE_IP6GRE,
+		.cmd_plobj_to_string                = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string,
+		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update,
+		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp,
+	},
+	[NMP_OBJECT_TYPE_LNK_IP6GRETAP - 1] = {
+		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
+		.obj_type                           = NMP_OBJECT_TYPE_LNK_IP6GRETAP,
+		.sizeof_data                        = sizeof (NMPObjectLnkIp6Tnl),
+		.sizeof_public                      = sizeof (NMPlatformLnkIp6Tnl),
+		.obj_type_name                      = "ip6gretap",
+		.lnk_link_type                      = NM_LINK_TYPE_IP6GRETAP,
+		.cmd_plobj_to_string                = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_ip6tnl_to_string,
+		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_ip6tnl_hash_update,
+		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_ip6tnl_cmp,
+	},
 	[NMP_OBJECT_TYPE_LNK_IPIP - 1] = {
 		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
 		.obj_type                           = NMP_OBJECT_TYPE_LNK_IPIP,
@@ -2817,5 +3083,20 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
 		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vxlan_hash_update,
 		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vxlan_cmp,
 	},
+	[NMP_OBJECT_TYPE_LNK_WIREGUARD - 1] = {
+		.parent                             = DEDUP_MULTI_OBJ_CLASS_INIT(),
+		.obj_type                           = NMP_OBJECT_TYPE_LNK_WIREGUARD,
+		.sizeof_data                        = sizeof (NMPObjectLnkWireGuard),
+		.sizeof_public                      = sizeof (NMPlatformLnkWireGuard),
+		.obj_type_name                      = "wireguard",
+		.lnk_link_type                      = NM_LINK_TYPE_WIREGUARD,
+		.cmd_obj_hash_update                = _vt_cmd_obj_hash_update_lnk_wireguard,
+		.cmd_obj_cmp                        = _vt_cmd_obj_cmp_lnk_wireguard,
+		.cmd_obj_copy                       = _vt_cmd_obj_copy_lnk_wireguard,
+		.cmd_obj_dispose                    = _vt_cmd_obj_dispose_lnk_wireguard,
+		.cmd_obj_to_string                  = _vt_cmd_obj_to_string_lnk_wireguard,
+		.cmd_plobj_to_string                = (const char *(*) (const NMPlatformObject *obj, char *buf, gsize len)) nm_platform_lnk_wireguard_to_string,
+		.cmd_plobj_hash_update              = (void (*) (const NMPlatformObject *obj, NMHashState *h)) nm_platform_lnk_vlan_hash_update,
+		.cmd_plobj_cmp                      = (int (*) (const NMPlatformObject *obj1, const NMPlatformObject *obj2)) nm_platform_lnk_vlan_cmp,
+	},
 };
-