Blame src/core/devices/nm-device-ip-tunnel.c

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