about summary refs log tree commit diff
path: root/src/devices/nm-device-ip-tunnel.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2021-02-11 18:12:43 +0100
committerMichael Biebl <biebl@debian.org>2021-02-11 18:12:43 +0100
commit8f0db010e71e252ac290d51bd2a5b0a078f1d279 (patch)
tree2caa344fefcd9bb4218583c5aa2e0f92f4b2aa8c /src/devices/nm-device-ip-tunnel.c
parentf54032b30e1ddd84f10a339e0caf493772e049a7 (diff)
parent80ec1decc49c72efec2a8b87c06245c92c0ab807 (diff)
Update upstream source from tag 'upstream/1.29.90'
Update to upstream version '1.29.90'
with Debian dir 90df6d97476cc3200c410f3f3603b87396175c7a
Diffstat (limited to 'src/devices/nm-device-ip-tunnel.c')
-rw-r--r--src/devices/nm-device-ip-tunnel.c1298
1 files changed, 0 insertions, 1298 deletions
diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c
deleted file mode 100644
index e01cc7ff..00000000
--- a/src/devices/nm-device-ip-tunnel.c
+++ /dev/null
@@ -1,1298 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-device-ip-tunnel.h"
-
-#include <netinet/in.h>
-#include <linux/if.h>
-#include <linux/ip.h>
-#include <linux/if_tunnel.h>
-#include <linux/ip6_tunnel.h>
-
-#include "nm-device-private.h"
-#include "nm-manager.h"
-#include "platform/nm-platform.h"
-#include "nm-device-factory.h"
-#include "nm-core-internal.h"
-#include "settings/nm-settings.h"
-#include "nm-act-request.h"
-#include "nm-ip4-config.h"
-
-#include "nm-device-logging.h"
-_LOG_DECLARE_SELF(NMDeviceIPTunnel);
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMDeviceIPTunnel,
-                             PROP_MODE,
-                             PROP_LOCAL,
-                             PROP_REMOTE,
-                             PROP_TTL,
-                             PROP_TOS,
-                             PROP_PATH_MTU_DISCOVERY,
-                             PROP_INPUT_KEY,
-                             PROP_OUTPUT_KEY,
-                             PROP_ENCAPSULATION_LIMIT,
-                             PROP_FLOW_LABEL,
-                             PROP_FLAGS, );
-
-typedef struct {
-    NMIPTunnelMode  mode;
-    char *          local;
-    char *          remote;
-    guint8          ttl;
-    guint8          tos;
-    gboolean        path_mtu_discovery;
-    int             addr_family;
-    char *          input_key;
-    char *          output_key;
-    guint8          encap_limit;
-    guint32         flow_label;
-    NMIPTunnelFlags flags;
-} NMDeviceIPTunnelPrivate;
-
-struct _NMDeviceIPTunnel {
-    NMDevice                parent;
-    NMDeviceIPTunnelPrivate _priv;
-};
-
-struct _NMDeviceIPTunnelClass {
-    NMDeviceClass parent;
-};
-
-G_DEFINE_TYPE(NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE)
-
-#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self) \
-    _NM_GET_PRIVATE(self, NMDeviceIPTunnel, NM_IS_DEVICE_IP_TUNNEL, NMDevice)
-
-/*****************************************************************************/
-
-static guint32
-ip6tnl_flags_setting_to_plat(NMIPTunnelFlags flags)
-{
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_IGN_ENCAP_LIMIT == IP6_TNL_F_IGN_ENCAP_LIMIT);
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_TCLASS == IP6_TNL_F_USE_ORIG_TCLASS);
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FLOWLABEL == IP6_TNL_F_USE_ORIG_FLOWLABEL);
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_MIP6_DEV == IP6_TNL_F_MIP6_DEV);
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_RCV_DSCP_COPY == IP6_TNL_F_RCV_DSCP_COPY);
-    G_STATIC_ASSERT(NM_IP_TUNNEL_FLAG_IP6_USE_ORIG_FWMARK == IP6_TNL_F_USE_ORIG_FWMARK);
-
-    /* NOTE: "accidentally", the numeric values correspond.
-     *       For flags added in the future, that might no longer
-     *       be the case. */
-    return flags & _NM_IP_TUNNEL_FLAG_ALL_IP6TNL;
-}
-
-static NMIPTunnelFlags
-ip6tnl_flags_plat_to_setting(guint32 flags)
-{
-    return flags & ((guint32) _NM_IP_TUNNEL_FLAG_ALL_IP6TNL);
-}
-
-/*****************************************************************************/
-
-static gboolean
-address_equal_pp(int addr_family, const char *a, const char *b)
-{
-    const NMIPAddr *addr_a = &nm_ip_addr_zero;
-    const NMIPAddr *addr_b = &nm_ip_addr_zero;
-    NMIPAddr        addr_a_val;
-    NMIPAddr        addr_b_val;
-
-    nm_assert_addr_family(addr_family);
-
-    if (a) {
-        if (!nm_utils_parse_inaddr_bin(addr_family, a, NULL, &addr_a_val))
-            nm_assert_not_reached();
-        addr_a = &addr_a_val;
-    }
-    if (b) {
-        if (!nm_utils_parse_inaddr_bin(addr_family, b, NULL, &addr_b_val))
-            nm_assert_not_reached();
-        addr_b = &addr_b_val;
-    }
-
-    return nm_ip_addr_equal(addr_family, addr_a, addr_b);
-}
-
-static gboolean
-address_set(int addr_family, char **p_addr, const NMIPAddr *addr_new)
-{
-    nm_assert_addr_family(addr_family);
-    nm_assert(p_addr);
-    nm_assert(!*p_addr || nm_utils_ipaddr_is_normalized(addr_family, *p_addr));
-
-    if (!addr_new || nm_ip_addr_is_null(addr_family, addr_new)) {
-        if (nm_clear_g_free(p_addr))
-            return TRUE;
-        return FALSE;
-    }
-
-    if (*p_addr) {
-        NMIPAddr addr_val;
-
-        if (!nm_utils_parse_inaddr_bin(addr_family, *p_addr, NULL, &addr_val))
-            nm_assert_not_reached();
-
-        if (nm_ip_addr_equal(addr_family, &addr_val, addr_new))
-            return FALSE;
-
-        g_free(*p_addr);
-    }
-
-    *p_addr = nm_utils_inet_ntop_dup(addr_family, addr_new);
-    return TRUE;
-}
-
-static void
-update_properties_from_ifindex(NMDevice *device, int ifindex)
-{
-    NMDeviceIPTunnel *       self           = NM_DEVICE_IP_TUNNEL(device);
-    NMDeviceIPTunnelPrivate *priv           = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self);
-    int                      parent_ifindex = 0;
-    NMIPAddr                 local          = NM_IP_ADDR_INIT;
-    NMIPAddr                 remote         = NM_IP_ADDR_INIT;
-    guint8                   ttl            = 0;
-    guint8                   tos            = 0;
-    guint8                   encap_limit    = 0;
-    gboolean                 pmtud          = FALSE;
-    guint32                  flow_label     = 0;
-    NMIPTunnelFlags          flags          = NM_IP_TUNNEL_FLAG_NONE;
-    char *                   key;
-
-    if (ifindex <= 0) {
-clear:
-        nm_device_parent_set_ifindex(device, 0);
-        if (priv->local) {
-            nm_clear_g_free(&priv->local);
-            _notify(self, PROP_LOCAL);
-        }
-        if (priv->remote) {
-            nm_clear_g_free(&priv->remote);
-            _notify(self, PROP_REMOTE);
-        }
-        if (priv->input_key) {
-            nm_clear_g_free(&priv->input_key);
-            _notify(self, PROP_INPUT_KEY);
-        }
-        if (priv->output_key) {
-            nm_clear_g_free(&priv->output_key);
-            _notify(self, PROP_OUTPUT_KEY);
-        }
-
-        goto out;
-    }
-
-    if (NM_IN_SET(priv->mode, NM_IP_TUNNEL_MODE_GRE, NM_IP_TUNNEL_MODE_GRETAP)) {
-        const NMPlatformLnkGre *lnk;
-
-        if (priv->mode == NM_IP_TUNNEL_MODE_GRE)
-            lnk = nm_platform_link_get_lnk_gre(nm_device_get_platform(device), ifindex, NULL);
-        else
-            lnk = nm_platform_link_get_lnk_gretap(nm_device_get_platform(device), ifindex, NULL);
-        if (!lnk) {
-            _LOGW(LOGD_PLATFORM, "could not read %s properties", "gre");
-            goto clear;
-        }
-
-        parent_ifindex = lnk->parent_ifindex;
-        local.addr4    = lnk->local;
-        remote.addr4   = lnk->remote;
-        ttl            = lnk->ttl;
-        tos            = lnk->tos;
-        pmtud          = lnk->path_mtu_discovery;
-
-        if (NM_FLAGS_HAS(lnk->input_flags, NM_GRE_KEY)) {
-            key = g_strdup_printf("%u", lnk->input_key);
-            if (g_strcmp0(priv->input_key, key)) {
-                g_free(priv->input_key);
-                priv->input_key = key;
-                _notify(self, PROP_INPUT_KEY);
-            } else
-                g_free(key);
-        } else {
-            if (priv->input_key) {
-                nm_clear_g_free(&priv->input_key);
-                _notify(self, PROP_INPUT_KEY);
-            }
-        }
-
-        if (NM_FLAGS_HAS(lnk->output_flags, NM_GRE_KEY)) {
-            key = g_strdup_printf("%u", lnk->output_key);
-            if (g_strcmp0(priv->output_key, key)) {
-                g_free(priv->output_key);
-                priv->output_key = key;
-                _notify(self, PROP_OUTPUT_KEY);
-            } else
-                g_free(key);
-        } else {
-            if (priv->output_key) {
-                nm_clear_g_free(&priv->output_key);
-                _notify(self, PROP_OUTPUT_KEY);
-            }
-        }
-    } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) {
-        const NMPlatformLnkSit *lnk;
-
-        lnk = nm_platform_link_get_lnk_sit(nm_device_get_platform(device), ifindex, NULL);
-        if (!lnk) {
-            _LOGW(LOGD_PLATFORM, "could not read %s properties", "sit");
-            goto clear;
-        }
-
-        parent_ifindex = lnk->parent_ifindex;
-        local.addr4    = lnk->local;
-        remote.addr4   = lnk->remote;
-        ttl            = lnk->ttl;
-        tos            = lnk->tos;
-        pmtud          = lnk->path_mtu_discovery;
-    } else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) {
-        const NMPlatformLnkIpIp *lnk;
-
-        lnk = nm_platform_link_get_lnk_ipip(nm_device_get_platform(device), ifindex, NULL);
-        if (!lnk) {
-            _LOGW(LOGD_PLATFORM, "could not read %s properties", "ipip");
-            goto clear;
-        }
-
-        parent_ifindex = lnk->parent_ifindex;
-        local.addr4    = lnk->local;
-        remote.addr4   = lnk->remote;
-        ttl            = lnk->ttl;
-        tos            = lnk->tos;
-        pmtud          = lnk->path_mtu_discovery;
-    } else if (NM_IN_SET(priv->mode,
-                         NM_IP_TUNNEL_MODE_IPIP6,
-                         NM_IP_TUNNEL_MODE_IP6IP6,
-                         NM_IP_TUNNEL_MODE_IP6GRE,
-                         NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-        const NMPlatformLnkIp6Tnl *lnk;
-        NMPlatform *               plat = nm_device_get_platform(device);
-
-        if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRE)
-            lnk = nm_platform_link_get_lnk_ip6gre(plat, ifindex, NULL);
-        else if (priv->mode == NM_IP_TUNNEL_MODE_IP6GRETAP)
-            lnk = nm_platform_link_get_lnk_ip6gretap(plat, ifindex, NULL);
-        else
-            lnk = nm_platform_link_get_lnk_ip6tnl(plat, ifindex, NULL);
-
-        if (!lnk) {
-            _LOGW(LOGD_PLATFORM, "could not read %s properties", "ip6tnl");
-            goto clear;
-        }
-
-        parent_ifindex = lnk->parent_ifindex;
-        local.addr6    = lnk->local;
-        remote.addr6   = lnk->remote;
-        ttl            = lnk->ttl;
-        tos            = lnk->tclass;
-        encap_limit    = lnk->encap_limit;
-        flow_label     = lnk->flow_label;
-        flags          = ip6tnl_flags_plat_to_setting(lnk->flags);
-
-        if (NM_IN_SET(priv->mode, NM_IP_TUNNEL_MODE_IP6GRE, NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-            if (NM_FLAGS_HAS(lnk->input_flags, NM_GRE_KEY)) {
-                key = g_strdup_printf("%u", lnk->input_key);
-                if (g_strcmp0(priv->input_key, key)) {
-                    g_free(priv->input_key);
-                    priv->input_key = key;
-                    _notify(self, PROP_INPUT_KEY);
-                } else
-                    g_free(key);
-            } else {
-                if (priv->input_key) {
-                    nm_clear_g_free(&priv->input_key);
-                    _notify(self, PROP_INPUT_KEY);
-                }
-            }
-
-            if (NM_FLAGS_HAS(lnk->output_flags, NM_GRE_KEY)) {
-                key = g_strdup_printf("%u", lnk->output_key);
-                if (g_strcmp0(priv->output_key, key)) {
-                    g_free(priv->output_key);
-                    priv->output_key = key;
-                    _notify(self, PROP_OUTPUT_KEY);
-                } else
-                    g_free(key);
-            } else {
-                if (priv->output_key) {
-                    nm_clear_g_free(&priv->output_key);
-                    _notify(self, PROP_OUTPUT_KEY);
-                }
-            }
-        }
-    } else
-        g_return_if_reached();
-
-    nm_device_parent_set_ifindex(device, parent_ifindex);
-
-    if (address_set(priv->addr_family, &priv->local, &local))
-        _notify(self, PROP_LOCAL);
-    if (address_set(priv->addr_family, &priv->remote, &remote))
-        _notify(self, PROP_REMOTE);
-
-out:
-
-    if (priv->ttl != ttl) {
-        priv->ttl = ttl;
-        _notify(self, PROP_TTL);
-    }
-
-    if (priv->tos != tos) {
-        priv->tos = tos;
-        _notify(self, PROP_TOS);
-    }
-
-    if (priv->path_mtu_discovery != pmtud) {
-        priv->path_mtu_discovery = pmtud;
-        _notify(self, PROP_PATH_MTU_DISCOVERY);
-    }
-
-    if (priv->encap_limit != encap_limit) {
-        priv->encap_limit = encap_limit;
-        _notify(self, PROP_ENCAPSULATION_LIMIT);
-    }
-
-    if (priv->flow_label != flow_label) {
-        priv->flow_label = flow_label;
-        _notify(self, PROP_FLOW_LABEL);
-    }
-
-    if (priv->flags != flags) {
-        priv->flags = flags;
-        _notify(self, PROP_FLAGS);
-    }
-}
-
-static void
-update_properties(NMDevice *device)
-{
-    update_properties_from_ifindex(device, nm_device_get_ifindex(device));
-}
-
-static void
-link_changed(NMDevice *device, const NMPlatformLink *pllink)
-{
-    NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class)->link_changed(device, pllink);
-    update_properties(device);
-}
-
-static gboolean
-complete_connection(NMDevice *           device,
-                    NMConnection *       connection,
-                    const char *         specific_object,
-                    NMConnection *const *existing_connections,
-                    GError **            error)
-{
-    NMSettingIPTunnel *s_ip_tunnel;
-
-    nm_utils_complete_generic(nm_device_get_platform(device),
-                              connection,
-                              NM_SETTING_IP_TUNNEL_SETTING_NAME,
-                              existing_connections,
-                              NULL,
-                              _("IP tunnel connection"),
-                              NULL,
-                              NULL,
-                              TRUE);
-
-    s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-    if (!s_ip_tunnel) {
-        g_set_error_literal(error,
-                            NM_DEVICE_ERROR,
-                            NM_DEVICE_ERROR_INVALID_CONNECTION,
-                            "A 'tunnel' setting is required.");
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static void
-update_connection(NMDevice *device, NMConnection *connection)
-{
-    NMDeviceIPTunnel *       self        = NM_DEVICE_IP_TUNNEL(device);
-    NMDeviceIPTunnelPrivate *priv        = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self);
-    NMSettingIPTunnel *      s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-
-    if (!s_ip_tunnel) {
-        s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new();
-        nm_connection_add_setting(connection, (NMSetting *) s_ip_tunnel);
-    }
-
-    if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) != priv->mode)
-        g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL);
-
-    g_object_set(
-        s_ip_tunnel,
-        NM_SETTING_IP_TUNNEL_PARENT,
-        nm_device_parent_find_for_connection(device, nm_setting_ip_tunnel_get_parent(s_ip_tunnel)),
-        NULL);
-
-    if (!address_equal_pp(priv->addr_family,
-                          nm_setting_ip_tunnel_get_local(s_ip_tunnel),
-                          priv->local))
-        g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_LOCAL, priv->local, NULL);
-
-    if (!address_equal_pp(priv->addr_family,
-                          nm_setting_ip_tunnel_get_remote(s_ip_tunnel),
-                          priv->remote))
-        g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_REMOTE, priv->remote, NULL);
-
-    if (nm_setting_ip_tunnel_get_ttl(s_ip_tunnel) != priv->ttl)
-        g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_TTL, priv->ttl, NULL);
-
-    if (nm_setting_ip_tunnel_get_tos(s_ip_tunnel) != priv->tos)
-        g_object_set(G_OBJECT(s_ip_tunnel), NM_SETTING_IP_TUNNEL_TOS, priv->tos, NULL);
-
-    if (nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel) != priv->path_mtu_discovery) {
-        g_object_set(G_OBJECT(s_ip_tunnel),
-                     NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY,
-                     priv->path_mtu_discovery,
-                     NULL);
-    }
-
-    if (nm_setting_ip_tunnel_get_encapsulation_limit(s_ip_tunnel) != priv->encap_limit) {
-        g_object_set(G_OBJECT(s_ip_tunnel),
-                     NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT,
-                     priv->encap_limit,
-                     NULL);
-    }
-
-    if (nm_setting_ip_tunnel_get_flow_label(s_ip_tunnel) != priv->flow_label) {
-        g_object_set(G_OBJECT(s_ip_tunnel),
-                     NM_SETTING_IP_TUNNEL_FLOW_LABEL,
-                     priv->flow_label,
-                     NULL);
-    }
-
-    if (NM_IN_SET(priv->mode,
-                  NM_IP_TUNNEL_MODE_GRE,
-                  NM_IP_TUNNEL_MODE_GRETAP,
-                  NM_IP_TUNNEL_MODE_IP6GRE,
-                  NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-        if (g_strcmp0(nm_setting_ip_tunnel_get_input_key(s_ip_tunnel), priv->input_key)) {
-            g_object_set(G_OBJECT(s_ip_tunnel),
-                         NM_SETTING_IP_TUNNEL_INPUT_KEY,
-                         priv->input_key,
-                         NULL);
-        }
-        if (g_strcmp0(nm_setting_ip_tunnel_get_output_key(s_ip_tunnel), priv->output_key)) {
-            g_object_set(G_OBJECT(s_ip_tunnel),
-                         NM_SETTING_IP_TUNNEL_OUTPUT_KEY,
-                         priv->output_key,
-                         NULL);
-        }
-    }
-}
-
-static gboolean
-check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error)
-{
-    NMDeviceIPTunnel *       self = NM_DEVICE_IP_TUNNEL(device);
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self);
-    NMSettingIPTunnel *      s_ip_tunnel;
-    const char *             parent;
-
-    if (!NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class)
-             ->check_connection_compatible(device, connection, error))
-        return FALSE;
-
-    s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-
-    if (nm_setting_ip_tunnel_get_mode(s_ip_tunnel) != priv->mode) {
-        nm_utils_error_set_literal(error,
-                                   NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                   "incompatible IP tunnel mode");
-        return FALSE;
-    }
-
-    if (nm_device_is_real(device)) {
-        /* Check parent interface; could be an interface name or a UUID */
-        parent = nm_setting_ip_tunnel_get_parent(s_ip_tunnel);
-        if (parent && !nm_device_match_parent(device, parent)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "IP tunnel parent mismatches");
-            return FALSE;
-        }
-
-        if (!address_equal_pp(priv->addr_family,
-                              nm_setting_ip_tunnel_get_local(s_ip_tunnel),
-                              priv->local)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "local IP tunnel address mismatches");
-            return FALSE;
-        }
-
-        if (!address_equal_pp(priv->addr_family,
-                              nm_setting_ip_tunnel_get_remote(s_ip_tunnel),
-                              priv->remote)) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "remote IP tunnel address mismatches");
-            return FALSE;
-        }
-
-        if (nm_setting_ip_tunnel_get_ttl(s_ip_tunnel) != priv->ttl) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "TTL of IP tunnel mismatches");
-            return FALSE;
-        }
-
-        if (nm_setting_ip_tunnel_get_tos(s_ip_tunnel) != priv->tos) {
-            nm_utils_error_set_literal(error,
-                                       NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                       "TOS of IP tunnel mismatches");
-            return FALSE;
-        }
-
-        if (priv->addr_family == AF_INET) {
-            if (nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel)
-                != priv->path_mtu_discovery) {
-                nm_utils_error_set_literal(error,
-                                           NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                           "MTU discovery setting of IP tunnel mismatches");
-                return FALSE;
-            }
-        } else {
-            if (nm_setting_ip_tunnel_get_encapsulation_limit(s_ip_tunnel) != priv->encap_limit) {
-                nm_utils_error_set_literal(error,
-                                           NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                           "encapsulation limit of IP tunnel mismatches");
-                return FALSE;
-            }
-
-            if (nm_setting_ip_tunnel_get_flow_label(s_ip_tunnel) != priv->flow_label) {
-                nm_utils_error_set_literal(error,
-                                           NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-                                           "flow-label of IP tunnel mismatches");
-                return FALSE;
-            }
-        }
-    }
-
-    return TRUE;
-}
-
-static NMIPTunnelMode
-platform_link_to_tunnel_mode(const NMPlatformLink *link)
-{
-    const NMPlatformLnkIp6Tnl *lnk;
-
-    switch (link->type) {
-    case NM_LINK_TYPE_GRE:
-        return NM_IP_TUNNEL_MODE_GRE;
-    case NM_LINK_TYPE_GRETAP:
-        return NM_IP_TUNNEL_MODE_GRETAP;
-    case NM_LINK_TYPE_IP6TNL:
-        lnk = nm_platform_link_get_lnk_ip6tnl(NM_PLATFORM_GET, link->ifindex, NULL);
-        if (lnk) {
-            if (lnk->proto == IPPROTO_IPIP)
-                return NM_IP_TUNNEL_MODE_IPIP6;
-            if (lnk->proto == IPPROTO_IPV6)
-                return NM_IP_TUNNEL_MODE_IP6IP6;
-        }
-        return NM_IP_TUNNEL_MODE_UNKNOWN;
-    case NM_LINK_TYPE_IP6GRE:
-        return NM_IP_TUNNEL_MODE_IP6GRE;
-    case NM_LINK_TYPE_IP6GRETAP:
-        return NM_IP_TUNNEL_MODE_IP6GRETAP;
-    case NM_LINK_TYPE_IPIP:
-        return NM_IP_TUNNEL_MODE_IPIP;
-    case NM_LINK_TYPE_SIT:
-        return NM_IP_TUNNEL_MODE_SIT;
-    default:
-        g_return_val_if_reached(NM_IP_TUNNEL_MODE_UNKNOWN);
-    }
-}
-
-static NMLinkType
-tunnel_mode_to_link_type(NMIPTunnelMode tunnel_mode)
-{
-    switch (tunnel_mode) {
-    case NM_IP_TUNNEL_MODE_GRE:
-        return NM_LINK_TYPE_GRE;
-    case NM_IP_TUNNEL_MODE_GRETAP:
-        return NM_LINK_TYPE_GRETAP;
-    case NM_IP_TUNNEL_MODE_IPIP6:
-    case NM_IP_TUNNEL_MODE_IP6IP6:
-        return NM_LINK_TYPE_IP6TNL;
-    case NM_IP_TUNNEL_MODE_IP6GRE:
-        return NM_LINK_TYPE_IP6GRE;
-    case NM_IP_TUNNEL_MODE_IP6GRETAP:
-        return NM_LINK_TYPE_IP6GRETAP;
-    case NM_IP_TUNNEL_MODE_IPIP:
-        return NM_LINK_TYPE_IPIP;
-    case NM_IP_TUNNEL_MODE_SIT:
-        return NM_LINK_TYPE_SIT;
-    case NM_IP_TUNNEL_MODE_VTI:
-    case NM_IP_TUNNEL_MODE_VTI6:
-    case NM_IP_TUNNEL_MODE_ISATAP:
-        return NM_LINK_TYPE_UNKNOWN;
-    case NM_IP_TUNNEL_MODE_UNKNOWN:
-        break;
-    }
-    g_return_val_if_reached(NM_LINK_TYPE_UNKNOWN);
-}
-
-/*****************************************************************************/
-
-static gboolean
-create_and_realize(NMDevice *             device,
-                   NMConnection *         connection,
-                   NMDevice *             parent,
-                   const NMPlatformLink **out_plink,
-                   GError **              error)
-{
-    const char *        iface = nm_device_get_iface(device);
-    NMSettingIPTunnel * s_ip_tunnel;
-    NMPlatformLnkGre    lnk_gre    = {};
-    NMPlatformLnkSit    lnk_sit    = {};
-    NMPlatformLnkIpIp   lnk_ipip   = {};
-    NMPlatformLnkIp6Tnl lnk_ip6tnl = {};
-    const char *        str;
-    gint64              val;
-    NMIPTunnelMode      mode;
-    int                 r;
-    gs_free char *      hwaddr = NULL;
-    guint8              mac_address[ETH_ALEN];
-    gboolean            mac_address_valid = FALSE;
-
-    s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-    nm_assert(NM_IS_SETTING_IP_TUNNEL(s_ip_tunnel));
-
-    mode = nm_setting_ip_tunnel_get_mode(s_ip_tunnel);
-
-    if (_nm_ip_tunnel_mode_is_layer2(mode)
-        && nm_device_hw_addr_get_cloned(device, connection, FALSE, &hwaddr, NULL, NULL) && hwaddr) {
-        /* FIXME: we set the MAC address when creating the interface, while the
-         * NMDevice is still unrealized. As we afterwards realize the device, it
-         * forgets the parameters for the cloned MAC address, and in stage 1
-         * it might create a different MAC address. That should be fixed by
-         * better handling device realization. */
-        if (!nm_utils_hwaddr_aton(hwaddr, mac_address, ETH_ALEN)) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_FAILED,
-                        "Invalid hardware address '%s'",
-                        hwaddr);
-            g_return_val_if_reached(FALSE);
-        }
-
-        mac_address_valid = TRUE;
-    }
-
-    switch (mode) {
-    case NM_IP_TUNNEL_MODE_GRETAP:
-        lnk_gre.is_tap = TRUE;
-        /* fall-through */
-    case NM_IP_TUNNEL_MODE_GRE:
-        if (parent)
-            lnk_gre.parent_ifindex = nm_device_get_ifindex(parent);
-
-        str = nm_setting_ip_tunnel_get_local(s_ip_tunnel);
-        if (str)
-            inet_pton(AF_INET, str, &lnk_gre.local);
-
-        str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel);
-        g_assert(str);
-        inet_pton(AF_INET, str, &lnk_gre.remote);
-
-        lnk_gre.ttl                = nm_setting_ip_tunnel_get_ttl(s_ip_tunnel);
-        lnk_gre.tos                = nm_setting_ip_tunnel_get_tos(s_ip_tunnel);
-        lnk_gre.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel);
-
-        val = _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_input_key(s_ip_tunnel),
-                                           10,
-                                           0,
-                                           G_MAXUINT32,
-                                           -1);
-        if (val != -1) {
-            lnk_gre.input_key   = val;
-            lnk_gre.input_flags = NM_GRE_KEY;
-        }
-
-        val = _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_output_key(s_ip_tunnel),
-                                           10,
-                                           0,
-                                           G_MAXUINT32,
-                                           -1);
-        if (val != -1) {
-            lnk_gre.output_key   = val;
-            lnk_gre.output_flags = NM_GRE_KEY;
-        }
-
-        r = nm_platform_link_gre_add(nm_device_get_platform(device),
-                                     iface,
-                                     mac_address_valid ? mac_address : NULL,
-                                     mac_address_valid ? ETH_ALEN : 0,
-                                     &lnk_gre,
-                                     out_plink);
-        if (r < 0) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_CREATION_FAILED,
-                        "Failed to create GRE interface '%s' for '%s': %s",
-                        iface,
-                        nm_connection_get_id(connection),
-                        nm_strerror(r));
-            return FALSE;
-        }
-        break;
-    case NM_IP_TUNNEL_MODE_SIT:
-        if (parent)
-            lnk_sit.parent_ifindex = nm_device_get_ifindex(parent);
-
-        str = nm_setting_ip_tunnel_get_local(s_ip_tunnel);
-        if (str)
-            inet_pton(AF_INET, str, &lnk_sit.local);
-
-        str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel);
-        g_assert(str);
-        inet_pton(AF_INET, str, &lnk_sit.remote);
-
-        lnk_sit.ttl                = nm_setting_ip_tunnel_get_ttl(s_ip_tunnel);
-        lnk_sit.tos                = nm_setting_ip_tunnel_get_tos(s_ip_tunnel);
-        lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel);
-
-        r = nm_platform_link_sit_add(nm_device_get_platform(device), iface, &lnk_sit, out_plink);
-        if (r < 0) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_CREATION_FAILED,
-                        "Failed to create SIT interface '%s' for '%s': %s",
-                        iface,
-                        nm_connection_get_id(connection),
-                        nm_strerror(r));
-            return FALSE;
-        }
-        break;
-    case NM_IP_TUNNEL_MODE_IPIP:
-        if (parent)
-            lnk_ipip.parent_ifindex = nm_device_get_ifindex(parent);
-
-        str = nm_setting_ip_tunnel_get_local(s_ip_tunnel);
-        if (str)
-            inet_pton(AF_INET, str, &lnk_ipip.local);
-
-        str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel);
-        g_assert(str);
-        inet_pton(AF_INET, str, &lnk_ipip.remote);
-
-        lnk_ipip.ttl                = nm_setting_ip_tunnel_get_ttl(s_ip_tunnel);
-        lnk_ipip.tos                = nm_setting_ip_tunnel_get_tos(s_ip_tunnel);
-        lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery(s_ip_tunnel);
-
-        r = nm_platform_link_ipip_add(nm_device_get_platform(device), iface, &lnk_ipip, out_plink);
-        if (r < 0) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_CREATION_FAILED,
-                        "Failed to create IPIP interface '%s' for '%s': %s",
-                        iface,
-                        nm_connection_get_id(connection),
-                        nm_strerror(r));
-            return FALSE;
-        }
-        break;
-    case NM_IP_TUNNEL_MODE_IPIP6:
-    case NM_IP_TUNNEL_MODE_IP6IP6:
-    case NM_IP_TUNNEL_MODE_IP6GRE:
-    case NM_IP_TUNNEL_MODE_IP6GRETAP:
-        if (parent)
-            lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex(parent);
-
-        str = nm_setting_ip_tunnel_get_local(s_ip_tunnel);
-        if (str)
-            inet_pton(AF_INET6, str, &lnk_ip6tnl.local);
-
-        str = nm_setting_ip_tunnel_get_remote(s_ip_tunnel);
-        g_assert(str);
-        inet_pton(AF_INET6, str, &lnk_ip6tnl.remote);
-
-        lnk_ip6tnl.ttl         = nm_setting_ip_tunnel_get_ttl(s_ip_tunnel);
-        lnk_ip6tnl.tclass      = nm_setting_ip_tunnel_get_tos(s_ip_tunnel);
-        lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit(s_ip_tunnel);
-        lnk_ip6tnl.flow_label  = nm_setting_ip_tunnel_get_flow_label(s_ip_tunnel);
-        lnk_ip6tnl.flags =
-            ip6tnl_flags_setting_to_plat(nm_setting_ip_tunnel_get_flags(s_ip_tunnel));
-
-        if (NM_IN_SET(mode, NM_IP_TUNNEL_MODE_IP6GRE, NM_IP_TUNNEL_MODE_IP6GRETAP)) {
-            val = _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_input_key(s_ip_tunnel),
-                                               10,
-                                               0,
-                                               G_MAXUINT32,
-                                               -1);
-            if (val != -1) {
-                lnk_ip6tnl.input_key   = val;
-                lnk_ip6tnl.input_flags = NM_GRE_KEY;
-            }
-
-            val = _nm_utils_ascii_str_to_int64(nm_setting_ip_tunnel_get_output_key(s_ip_tunnel),
-                                               10,
-                                               0,
-                                               G_MAXUINT32,
-                                               -1);
-            if (val != -1) {
-                lnk_ip6tnl.output_key   = val;
-                lnk_ip6tnl.output_flags = NM_GRE_KEY;
-            }
-
-            lnk_ip6tnl.is_gre = TRUE;
-            lnk_ip6tnl.is_tap = (mode == NM_IP_TUNNEL_MODE_IP6GRETAP);
-
-            r = nm_platform_link_ip6gre_add(nm_device_get_platform(device),
-                                            iface,
-                                            mac_address_valid ? mac_address : NULL,
-                                            mac_address_valid ? ETH_ALEN : 0,
-                                            &lnk_ip6tnl,
-                                            out_plink);
-        } else {
-            lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode(s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6
-                                   ? IPPROTO_IPIP
-                                   : IPPROTO_IPV6;
-            r                = nm_platform_link_ip6tnl_add(nm_device_get_platform(device),
-                                            iface,
-                                            &lnk_ip6tnl,
-                                            out_plink);
-        }
-        if (r < 0) {
-            g_set_error(error,
-                        NM_DEVICE_ERROR,
-                        NM_DEVICE_ERROR_CREATION_FAILED,
-                        "Failed to create IPv6 tunnel interface '%s' for '%s': %s",
-                        iface,
-                        nm_connection_get_id(connection),
-                        nm_strerror(r));
-            return FALSE;
-        }
-        break;
-    default:
-        g_set_error(error,
-                    NM_DEVICE_ERROR,
-                    NM_DEVICE_ERROR_CREATION_FAILED,
-                    "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported",
-                    iface,
-                    nm_connection_get_id(connection),
-                    (int) nm_setting_ip_tunnel_get_mode(s_ip_tunnel));
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-static guint32
-get_configured_mtu(NMDevice *device, NMDeviceMtuSource *out_source, gboolean *out_force)
-{
-    return nm_device_get_configured_mtu_from_connection(device,
-                                                        NM_TYPE_SETTING_IP_TUNNEL,
-                                                        out_source);
-}
-
-static NMDeviceCapabilities
-get_generic_capabilities(NMDevice *device)
-{
-    return NM_DEVICE_CAP_IS_SOFTWARE;
-}
-
-static void
-unrealize_notify(NMDevice *device)
-{
-    NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class)->unrealize_notify(device);
-
-    update_properties_from_ifindex(device, 0);
-}
-
-static gboolean
-can_reapply_change(NMDevice *  device,
-                   const char *setting_name,
-                   NMSetting * s_old,
-                   NMSetting * s_new,
-                   GHashTable *diffs,
-                   GError **   error)
-{
-    NMDeviceClass *device_class;
-
-    /* Only handle ip-tunnel setting here, delegate other settings to parent class */
-    if (nm_streq(setting_name, NM_SETTING_IP_TUNNEL_SETTING_NAME)) {
-        return nm_device_hash_check_invalid_keys(
-            diffs,
-            NM_SETTING_IP_TUNNEL_SETTING_NAME,
-            error,
-            NM_SETTING_IP_TUNNEL_MTU); /* reapplied with IP config */
-    }
-
-    device_class = NM_DEVICE_CLASS(nm_device_ip_tunnel_parent_class);
-    return device_class->can_reapply_change(device, setting_name, s_old, s_new, diffs, error);
-}
-
-static NMActStageReturn
-act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason)
-{
-    NMDeviceIPTunnel *       self = NM_DEVICE_IP_TUNNEL(device);
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self);
-
-    if (_nm_ip_tunnel_mode_is_layer2(priv->mode)
-        && !nm_device_hw_addr_set_cloned(device, nm_device_get_applied_connection(device), FALSE)) {
-        *out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
-        return NM_ACT_STAGE_RETURN_FAILURE;
-    }
-
-    return NM_ACT_STAGE_RETURN_SUCCESS;
-}
-
-/*****************************************************************************/
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(object);
-
-    switch (prop_id) {
-    case PROP_MODE:
-        g_value_set_uint(value, priv->mode);
-        break;
-    case PROP_LOCAL:
-        g_value_set_string(value, priv->local);
-        break;
-    case PROP_REMOTE:
-        g_value_set_string(value, priv->remote);
-        break;
-    case PROP_TTL:
-        g_value_set_uchar(value, priv->ttl);
-        break;
-    case PROP_TOS:
-        g_value_set_uchar(value, priv->tos);
-        break;
-    case PROP_PATH_MTU_DISCOVERY:
-        g_value_set_boolean(value, priv->path_mtu_discovery);
-        break;
-    case PROP_INPUT_KEY:
-        g_value_set_string(value, priv->input_key);
-        break;
-    case PROP_OUTPUT_KEY:
-        g_value_set_string(value, priv->output_key);
-        break;
-    case PROP_ENCAPSULATION_LIMIT:
-        g_value_set_uchar(value, priv->encap_limit);
-        break;
-    case PROP_FLOW_LABEL:
-        g_value_set_uint(value, priv->flow_label);
-        break;
-    case PROP_FLAGS:
-        g_value_set_uint(value, priv->flags);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-        break;
-    }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(object);
-
-    switch (prop_id) {
-    case PROP_MODE:
-        priv->mode = g_value_get_uint(value);
-        break;
-    default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
-    }
-}
-
-/*****************************************************************************/
-
-static void
-nm_device_ip_tunnel_init(NMDeviceIPTunnel *self)
-{}
-
-static void
-constructed(GObject *object)
-{
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(object);
-
-    if (NM_IN_SET(priv->mode,
-                  NM_IP_TUNNEL_MODE_IPIP6,
-                  NM_IP_TUNNEL_MODE_IP6IP6,
-                  NM_IP_TUNNEL_MODE_IP6GRE,
-                  NM_IP_TUNNEL_MODE_IP6GRETAP))
-        priv->addr_family = AF_INET6;
-    else
-        priv->addr_family = AF_INET;
-
-    G_OBJECT_CLASS(nm_device_ip_tunnel_parent_class)->constructed(object);
-}
-
-static void
-dispose(GObject *object)
-{
-    NMDeviceIPTunnel *       self = NM_DEVICE_IP_TUNNEL(object);
-    NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE(self);
-
-    nm_clear_g_free(&priv->local);
-    nm_clear_g_free(&priv->remote);
-    nm_clear_g_free(&priv->input_key);
-    nm_clear_g_free(&priv->output_key);
-
-    G_OBJECT_CLASS(nm_device_ip_tunnel_parent_class)->dispose(object);
-}
-
-static const NMDBusInterfaceInfoExtended interface_info_device_ip_tunnel = {
-    .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
-        NM_DBUS_INTERFACE_DEVICE_IP_TUNNEL,
-        .signals    = NM_DEFINE_GDBUS_SIGNAL_INFOS(&nm_signal_info_property_changed_legacy, ),
-        .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Mode", "u", NM_DEVICE_IP_TUNNEL_MODE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Parent", "o", NM_DEVICE_PARENT),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Local",
-                                                             "s",
-                                                             NM_DEVICE_IP_TUNNEL_LOCAL),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Remote",
-                                                             "s",
-                                                             NM_DEVICE_IP_TUNNEL_REMOTE),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Ttl", "y", NM_DEVICE_IP_TUNNEL_TTL),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Tos", "y", NM_DEVICE_IP_TUNNEL_TOS),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L(
-                "PathMtuDiscovery",
-                "b",
-                NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("InputKey",
-                                                             "s",
-                                                             NM_DEVICE_IP_TUNNEL_INPUT_KEY),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("OutputKey",
-                                                             "s",
-                                                             NM_DEVICE_IP_TUNNEL_OUTPUT_KEY),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L(
-                "EncapsulationLimit",
-                "y",
-                NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("FlowLabel",
-                                                             "u",
-                                                             NM_DEVICE_IP_TUNNEL_FLOW_LABEL),
-            NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L("Flags",
-                                                             "u",
-                                                             NM_DEVICE_IP_TUNNEL_FLAGS), ), ),
-    .legacy_property_changed = TRUE,
-};
-
-static void
-nm_device_ip_tunnel_class_init(NMDeviceIPTunnelClass *klass)
-{
-    GObjectClass *     object_class      = G_OBJECT_CLASS(klass);
-    NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
-    NMDeviceClass *    device_class      = NM_DEVICE_CLASS(klass);
-
-    object_class->constructed  = constructed;
-    object_class->dispose      = dispose;
-    object_class->get_property = get_property;
-    object_class->set_property = set_property;
-
-    dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ip_tunnel);
-
-    device_class->connection_type_supported        = NM_SETTING_IP_TUNNEL_SETTING_NAME;
-    device_class->connection_type_check_compatible = NM_SETTING_IP_TUNNEL_SETTING_NAME;
-    device_class->link_types                       = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_GRE,
-                                                           NM_LINK_TYPE_GRETAP,
-                                                           NM_LINK_TYPE_IP6TNL,
-                                                           NM_LINK_TYPE_IP6GRE,
-                                                           NM_LINK_TYPE_IP6GRETAP,
-                                                           NM_LINK_TYPE_IPIP,
-                                                           NM_LINK_TYPE_SIT);
-
-    device_class->act_stage1_prepare          = act_stage1_prepare;
-    device_class->link_changed                = link_changed;
-    device_class->can_reapply_change          = can_reapply_change;
-    device_class->complete_connection         = complete_connection;
-    device_class->update_connection           = update_connection;
-    device_class->check_connection_compatible = check_connection_compatible;
-    device_class->create_and_realize          = create_and_realize;
-    device_class->get_generic_capabilities    = get_generic_capabilities;
-    device_class->get_configured_mtu          = get_configured_mtu;
-    device_class->unrealize_notify            = unrealize_notify;
-
-    obj_properties[PROP_MODE] =
-        g_param_spec_uint(NM_DEVICE_IP_TUNNEL_MODE,
-                          "",
-                          "",
-                          0,
-                          G_MAXUINT,
-                          0,
-                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_LOCAL] = g_param_spec_string(NM_DEVICE_IP_TUNNEL_LOCAL,
-                                                     "",
-                                                     "",
-                                                     NULL,
-                                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_REMOTE] = g_param_spec_string(NM_DEVICE_IP_TUNNEL_REMOTE,
-                                                      "",
-                                                      "",
-                                                      NULL,
-                                                      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_TTL] = g_param_spec_uchar(NM_DEVICE_IP_TUNNEL_TTL,
-                                                  "",
-                                                  "",
-                                                  0,
-                                                  255,
-                                                  0,
-                                                  G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_TOS] = g_param_spec_uchar(NM_DEVICE_IP_TUNNEL_TOS,
-                                                  "",
-                                                  "",
-                                                  0,
-                                                  255,
-                                                  0,
-                                                  G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_PATH_MTU_DISCOVERY] =
-        g_param_spec_boolean(NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY,
-                             "",
-                             "",
-                             FALSE,
-                             G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_INPUT_KEY] = g_param_spec_string(NM_DEVICE_IP_TUNNEL_INPUT_KEY,
-                                                         "",
-                                                         "",
-                                                         NULL,
-                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_OUTPUT_KEY] =
-        g_param_spec_string(NM_DEVICE_IP_TUNNEL_OUTPUT_KEY,
-                            "",
-                            "",
-                            NULL,
-                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_ENCAPSULATION_LIMIT] =
-        g_param_spec_uchar(NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT,
-                           "",
-                           "",
-                           0,
-                           255,
-                           0,
-                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_FLOW_LABEL] = g_param_spec_uint(NM_DEVICE_IP_TUNNEL_FLOW_LABEL,
-                                                        "",
-                                                        "",
-                                                        0,
-                                                        (1 << 20) - 1,
-                                                        0,
-                                                        G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
-    obj_properties[PROP_FLAGS] = g_param_spec_uint(NM_DEVICE_IP_TUNNEL_FLAGS,
-                                                   "",
-                                                   "",
-                                                   0,
-                                                   G_MAXUINT32,
-                                                   0,
-                                                   G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
-    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}
-
-/*****************************************************************************/
-
-#define NM_TYPE_IP_TUNNEL_DEVICE_FACTORY (nm_ip_tunnel_device_factory_get_type())
-#define NM_IP_TUNNEL_DEVICE_FACTORY(obj) \
-    (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP_TUNNEL_DEVICE_FACTORY, NMIPTunnelDeviceFactory))
-
-static NMDevice *
-create_device(NMDeviceFactory *     factory,
-              const char *          iface,
-              const NMPlatformLink *plink,
-              NMConnection *        connection,
-              gboolean *            out_ignore)
-{
-    NMSettingIPTunnel *s_ip_tunnel;
-    NMIPTunnelMode     mode;
-    NMLinkType         link_type;
-
-    if (connection) {
-        s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-        mode        = nm_setting_ip_tunnel_get_mode(s_ip_tunnel);
-        link_type   = tunnel_mode_to_link_type(mode);
-    } else {
-        link_type = plink->type;
-        mode      = platform_link_to_tunnel_mode(plink);
-    }
-
-    if (mode == NM_IP_TUNNEL_MODE_UNKNOWN || link_type == NM_LINK_TYPE_UNKNOWN)
-        return NULL;
-
-    return (NMDevice *) g_object_new(NM_TYPE_DEVICE_IP_TUNNEL,
-                                     NM_DEVICE_IFACE,
-                                     iface,
-                                     NM_DEVICE_TYPE_DESC,
-                                     "IPTunnel",
-                                     NM_DEVICE_DEVICE_TYPE,
-                                     NM_DEVICE_TYPE_IP_TUNNEL,
-                                     NM_DEVICE_LINK_TYPE,
-                                     link_type,
-                                     NM_DEVICE_IP_TUNNEL_MODE,
-                                     mode,
-                                     NULL);
-}
-
-static const char *
-get_connection_parent(NMDeviceFactory *factory, NMConnection *connection)
-{
-    NMSettingIPTunnel *s_ip_tunnel;
-
-    g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_IP_TUNNEL_SETTING_NAME),
-                         NULL);
-
-    s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-    g_assert(s_ip_tunnel);
-
-    return nm_setting_ip_tunnel_get_parent(s_ip_tunnel);
-}
-
-static char *
-get_connection_iface(NMDeviceFactory *factory, NMConnection *connection, const char *parent_iface)
-{
-    const char *       ifname;
-    NMSettingIPTunnel *s_ip_tunnel;
-
-    g_return_val_if_fail(nm_connection_is_type(connection, NM_SETTING_IP_TUNNEL_SETTING_NAME),
-                         NULL);
-
-    s_ip_tunnel = nm_connection_get_setting_ip_tunnel(connection);
-    g_assert(s_ip_tunnel);
-
-    if (nm_setting_ip_tunnel_get_parent(s_ip_tunnel) && !parent_iface)
-        return NULL;
-
-    ifname = nm_connection_get_interface_name(connection);
-
-    return g_strdup(ifname);
-}
-
-NM_DEVICE_FACTORY_DEFINE_INTERNAL(
-    IP_TUNNEL,
-    IPTunnel,
-    ip_tunnel,
-    NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_GRE,
-                                         NM_LINK_TYPE_GRETAP,
-                                         NM_LINK_TYPE_SIT,
-                                         NM_LINK_TYPE_IPIP,
-                                         NM_LINK_TYPE_IP6TNL,
-                                         NM_LINK_TYPE_IP6GRE,
-                                         NM_LINK_TYPE_IP6GRETAP)
-        NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_IP_TUNNEL_SETTING_NAME),
-    factory_class->create_device         = create_device;
-    factory_class->get_connection_parent = get_connection_parent;
-    factory_class->get_connection_iface  = get_connection_iface;);