Blame src/platform/nm-fake-platform.c

Packit Service a1bd4f
/* SPDX-License-Identifier: GPL-2.0+ */
Packit 5756e2
/*
Packit 5756e2
 * Copyright (C) 2012 - 2017 Red Hat, Inc.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
#include "nm-default.h"
Packit 5756e2
Packit 5756e2
#include "nm-fake-platform.h"
Packit 5756e2
Packit 5756e2
#include <unistd.h>
Packit 5756e2
#include <netinet/icmp6.h>
Packit 5756e2
#include <netinet/in.h>
Packit 5756e2
#include <linux/if.h>
Packit 5756e2
#include <linux/rtnetlink.h>
Packit 5756e2
Packit 5756e2
#include "nm-utils.h"
Packit 5756e2
Packit 5756e2
#include "nm-core-utils.h"
Packit 5756e2
#include "nm-platform-utils.h"
Packit 5756e2
#include "nm-platform-private.h"
Packit 5756e2
#include "nmp-object.h"
Packit 5756e2
Packit 5756e2
#include "nm-test-utils-core.h"
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    const NMPObject *obj;
Packit Service a1bd4f
    char *           udi;
Packit Service a1bd4f
    struct in6_addr  ip6_lladdr;
Packit 5756e2
} NMFakePlatformLink;
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    GHashTable *options;
Packit Service a1bd4f
    GArray *    links;
Packit 5756e2
} NMFakePlatformPrivate;
Packit 5756e2
Packit 5756e2
struct _NMFakePlatform {
Packit Service a1bd4f
    NMPlatform            parent;
Packit Service a1bd4f
    NMFakePlatformPrivate _priv;
Packit 5756e2
};
Packit 5756e2
Packit 5756e2
struct _NMFakePlatformClass {
Packit Service a1bd4f
    NMPlatformClass parent;
Packit 5756e2
};
Packit 5756e2
Packit Service a1bd4f
G_DEFINE_TYPE(NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
Packit 5756e2
Packit Service a1bd4f
#define NM_FAKE_PLATFORM_GET_PRIVATE(self) \
Packit Service a1bd4f
    _NM_GET_PRIVATE(self, NMFakePlatform, NM_IS_FAKE_PLATFORM, NMPlatform)
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit Service a1bd4f
#define _NMLOG_PREFIX_NAME "platform-fake"
Packit Service a1bd4f
#define _NMLOG_DOMAIN      LOGD_PLATFORM
Packit Service a1bd4f
#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, platform, __VA_ARGS__)
Packit Service a1bd4f
Packit Service a1bd4f
#define _LOG(level, domain, self, ...)                                                        \
Packit Service a1bd4f
    G_STMT_START                                                                              \
Packit Service a1bd4f
    {                                                                                         \
Packit Service a1bd4f
        const NMLogLevel  __level  = (level);                                                 \
Packit Service a1bd4f
        const NMLogDomain __domain = (domain);                                                \
Packit Service a1bd4f
                                                                                              \
Packit Service a1bd4f
        if (nm_logging_enabled(__level, __domain)) {                                          \
Packit Service a1bd4f
            char              __prefix[32];                                                   \
Packit Service a1bd4f
            const char *      __p_prefix = _NMLOG_PREFIX_NAME;                                \
Packit Service a1bd4f
            NMPlatform *const __self     = (self);                                            \
Packit Service a1bd4f
                                                                                              \
Packit Service a1bd4f
            if (__self && nm_platform_get_log_with_ptr(self)) {                               \
Packit Service a1bd4f
                g_snprintf(__prefix, sizeof(__prefix), "%s[%p]", _NMLOG_PREFIX_NAME, __self); \
Packit Service a1bd4f
                __p_prefix = __prefix;                                                        \
Packit Service a1bd4f
            }                                                                                 \
Packit Service a1bd4f
            _nm_log(__level,                                                                  \
Packit Service a1bd4f
                    __domain,                                                                 \
Packit Service a1bd4f
                    0,                                                                        \
Packit Service a1bd4f
                    NULL,                                                                     \
Packit Service a1bd4f
                    NULL,                                                                     \
Packit Service a1bd4f
                    "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__),                                \
Packit Service a1bd4f
                    __p_prefix _NM_UTILS_MACRO_REST(__VA_ARGS__));                            \
Packit Service a1bd4f
        }                                                                                     \
Packit Service a1bd4f
    }                                                                                         \
Packit Service a1bd4f
    G_STMT_END
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit Service a1bd4f
static void link_changed(NMPlatform *        platform,
Packit Service a1bd4f
                         NMFakePlatformLink *device,
Packit Service a1bd4f
                         NMPCacheOpsType     cache_op,
Packit Service a1bd4f
                         const NMPObject *   obj_old);
Packit Service a1bd4f
Packit Service a1bd4f
static gboolean ipx_address_delete(NMPlatform *  platform,
Packit Service a1bd4f
                                   int           addr_family,
Packit Service a1bd4f
                                   int           ifindex,
Packit Service a1bd4f
                                   gconstpointer addr,
Packit Service a1bd4f
                                   const guint8 *plen,
Packit Service a1bd4f
                                   gconstpointer peer_addr);
Packit Service a1bd4f
Packit Service a1bd4f
static gboolean
Packit Service a1bd4f
ipx_route_delete(NMPlatform *platform, int addr_family, int ifindex, const NMPObject *obj);
Packit Service a1bd4f
Packit Service a1bd4f
static gboolean ip6_address_add(NMPlatform *    platform,
Packit Service a1bd4f
                                int             ifindex,
Packit Service a1bd4f
                                struct in6_addr addr,
Packit Service a1bd4f
                                guint8          plen,
Packit Service a1bd4f
                                struct in6_addr peer_addr,
Packit Service a1bd4f
                                guint32         lifetime,
Packit Service a1bd4f
                                guint32         preferred,
Packit Service a1bd4f
                                guint           flags);
Packit Service a1bd4f
static gboolean
Packit Service a1bd4f
ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen);
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit Service a1bd4f
#define ASSERT_SYSCTL_ARGS(pathid, dirfd, path)                                                  \
Packit Service a1bd4f
    G_STMT_START                                                                                 \
Packit Service a1bd4f
    {                                                                                            \
Packit Service a1bd4f
        const char *const _pathid = (pathid);                                                    \
Packit Service a1bd4f
        const int         _dirfd  = (dirfd);                                                     \
Packit Service a1bd4f
        const char *const _path   = (path);                                                      \
Packit Service a1bd4f
                                                                                                 \
Packit Service a1bd4f
        g_assert(_path &&_path[0]);                                                              \
Packit Service a1bd4f
        g_assert(!strstr(_path, "/../"));                                                        \
Packit Service a1bd4f
        if (_dirfd < 0) {                                                                        \
Packit Service a1bd4f
            g_assert(!_pathid);                                                                  \
Packit Service a1bd4f
            g_assert(_path[0] == '/');                                                           \
Packit Service a1bd4f
            g_assert(g_str_has_prefix(_path, "/proc/sys/") || g_str_has_prefix(_path, "/sys/")); \
Packit Service a1bd4f
        } else {                                                                                 \
Packit Service a1bd4f
            g_assert_not_reached();                                                              \
Packit Service a1bd4f
        }                                                                                        \
Packit Service a1bd4f
    }                                                                                            \
Packit Service a1bd4f
    G_STMT_END
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
sysctl_set(NMPlatform *platform, const char *pathid, int dirfd, const char *path, const char *value)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform);
Packit 5756e2
Packit Service a1bd4f
    ASSERT_SYSCTL_ARGS(pathid, dirfd, path);
Packit 5756e2
Packit Service a1bd4f
    g_hash_table_insert(priv->options, g_strdup(path), g_strdup(value));
Packit 5756e2
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static char *
Packit Service a1bd4f
sysctl_get(NMPlatform *platform, const char *pathid, int dirfd, const char *path)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform);
Packit Service a1bd4f
    const char *           v;
Packit 5756e2
Packit Service a1bd4f
    ASSERT_SYSCTL_ARGS(pathid, dirfd, path);
Packit 5756e2
Packit Service a1bd4f
    v = g_hash_table_lookup(priv->options, path);
Packit Service a1bd4f
    if (!v) {
Packit Service a1bd4f
        errno = ENOENT;
Packit Service a1bd4f
        return NULL;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return g_strdup(v);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMFakePlatformLink *
Packit Service a1bd4f
link_get(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform);
Packit Service a1bd4f
    NMFakePlatformLink *   device;
Packit Service a1bd4f
    int                    idx;
Packit 5756e2
Packit Service a1bd4f
    if (ifindex <= 0)
Packit Service a1bd4f
        g_return_val_if_reached(NULL);
Packit 5756e2
Packit Service a1bd4f
    idx = ifindex - 1;
Packit Service a1bd4f
    if (idx >= priv->links->len)
Packit Service a1bd4f
        goto not_found;
Packit 5756e2
Packit Service a1bd4f
    device = &g_array_index(priv->links, NMFakePlatformLink, idx);
Packit Service a1bd4f
    if (!device->obj)
Packit Service a1bd4f
        goto not_found;
Packit 5756e2
Packit Service a1bd4f
    g_assert(ifindex == NMP_OBJECT_CAST_LINK(device->obj)->ifindex);
Packit Service a1bd4f
    g_assert(device->obj == nm_platform_link_get_obj(platform, ifindex, FALSE));
Packit 5756e2
Packit Service a1bd4f
    return device;
Packit 5756e2
not_found:
Packit Service a1bd4f
    _LOGD("link not found: %d", ifindex);
Packit Service a1bd4f
    return NULL;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
link_add_prepare(NMPlatform *platform, NMFakePlatformLink *device, NMPObject *obj_tmp)
Packit 5756e2
{
Packit Service a1bd4f
    gboolean connected;
Packit Service a1bd4f
Packit Service a1bd4f
    /* we must clear the driver, because platform cache wants to set it */
Packit Service a1bd4f
    g_assert(obj_tmp->link.driver == g_intern_string(obj_tmp->link.driver));
Packit Service a1bd4f
    obj_tmp->link.driver = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    if (NM_IN_SET(obj_tmp->link.type, NM_LINK_TYPE_BRIDGE, NM_LINK_TYPE_BOND)) {
Packit Service a1bd4f
        connected = FALSE;
Packit Service a1bd4f
        if (NM_FLAGS_HAS(obj_tmp->link.n_ifi_flags, IFF_UP)) {
Packit Service a1bd4f
            NMPLookup        lookup;
Packit Service a1bd4f
            NMDedupMultiIter iter;
Packit Service a1bd4f
            const NMPObject *slave_candidate = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
            nmp_cache_iter_for_each (
Packit Service a1bd4f
                &iter,
Packit Service a1bd4f
                nmp_cache_lookup(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                 nmp_lookup_init_obj_type(&lookup, NMP_OBJECT_TYPE_LINK)),
Packit Service a1bd4f
                &slave_candidate) {
Packit Service a1bd4f
                if (nmp_cache_link_connected_for_slave(obj_tmp->link.ifindex, slave_candidate)) {
Packit Service a1bd4f
                    connected = TRUE;
Packit Service a1bd4f
                    break;
Packit Service a1bd4f
                }
Packit Service a1bd4f
            }
Packit Service a1bd4f
        }
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        connected = NM_FLAGS_HAS(obj_tmp->link.n_ifi_flags, IFF_UP);
Packit Service a1bd4f
Packit Service a1bd4f
    obj_tmp->link.n_ifi_flags = NM_FLAGS_ASSIGN(obj_tmp->link.n_ifi_flags, IFF_LOWER_UP, connected);
Packit Service a1bd4f
    obj_tmp->link.connected   = connected;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMFakePlatformLink *
Packit Service a1bd4f
link_add_pre(NMPlatform *platform,
Packit Service a1bd4f
             const char *name,
Packit Service a1bd4f
             NMLinkType  type,
Packit Service a1bd4f
             const void *address,
Packit Service a1bd4f
             size_t      address_len,
Packit Service a1bd4f
             guint32     mtu)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(platform);
Packit Service a1bd4f
    NMFakePlatformLink *   device;
Packit Service a1bd4f
    int                    ifindex;
Packit Service a1bd4f
    NMPObject *            o;
Packit Service a1bd4f
    NMPlatformLink *       link;
Packit Service a1bd4f
    gs_free char *         ip6_lladdr = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(!name || strlen(name) < IFNAMSIZ);
Packit Service a1bd4f
Packit Service a1bd4f
    g_array_set_size(priv->links, priv->links->len + 1);
Packit Service a1bd4f
    device  = &g_array_index(priv->links, NMFakePlatformLink, priv->links->len - 1);
Packit Service a1bd4f
    ifindex = priv->links->len;
Packit Service a1bd4f
Packit Service a1bd4f
    memset(device, 0, sizeof(*device));
Packit Service a1bd4f
Packit Service a1bd4f
    o    = nmp_object_new_link(ifindex);
Packit Service a1bd4f
    link = NMP_OBJECT_CAST_LINK(o);
Packit Service a1bd4f
Packit Service a1bd4f
    ip6_lladdr =
Packit Service a1bd4f
        ifindex > 0 ? g_strdup_printf("fe80::fa1e:%0x:%0x", ifindex / 256, ifindex % 256) : NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    link->ifindex     = name ? ifindex : 0;
Packit Service a1bd4f
    link->type        = type;
Packit Service a1bd4f
    link->kind        = g_intern_string(nm_link_type_to_string(type));
Packit Service a1bd4f
    link->mtu         = mtu;
Packit Service a1bd4f
    link->initialized = TRUE;
Packit Service a1bd4f
    if (name)
Packit Service a1bd4f
        strcpy(link->name, name);
Packit Service a1bd4f
    switch (link->type) {
Packit Service a1bd4f
    case NM_LINK_TYPE_DUMMY:
Packit Service a1bd4f
        link->n_ifi_flags = NM_FLAGS_SET(link->n_ifi_flags, IFF_NOARP);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        link->n_ifi_flags = NM_FLAGS_UNSET(link->n_ifi_flags, IFF_NOARP);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    o->_link.netlink.is_in_netlink = TRUE;
Packit Service a1bd4f
Packit Service a1bd4f
    if (address) {
Packit Service a1bd4f
        g_assert(address_len > 0 && address_len <= sizeof(link->l_address.data));
Packit Service a1bd4f
        memcpy(link->l_address.data, address, address_len);
Packit Service a1bd4f
        link->l_address.len = address_len;
Packit Service a1bd4f
    } else
Packit Service a1bd4f
        g_assert(address_len == 0);
Packit Service a1bd4f
Packit Service a1bd4f
    device->obj        = o;
Packit Service a1bd4f
    device->ip6_lladdr = *nmtst_inet6_from_string(ip6_lladdr);
Packit Service a1bd4f
Packit Service a1bd4f
    return device;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
link_add(NMPlatform *           platform,
Packit Service a1bd4f
         NMLinkType             type,
Packit Service a1bd4f
         const char *           name,
Packit Service a1bd4f
         int                    parent,
Packit Service a1bd4f
         const void *           address,
Packit Service a1bd4f
         size_t                 address_len,
Packit Service a1bd4f
         guint32                mtu,
Packit Service a1bd4f
         gconstpointer          extra_data,
Packit Service a1bd4f
         const NMPlatformLink **out_link)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink * device;
Packit Service a1bd4f
    NMFakePlatformLink * device_veth             = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old      = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new      = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old_veth = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new_veth = NULL;
Packit Service a1bd4f
    NMPCacheOpsType                 cache_op;
Packit Service a1bd4f
    NMPCacheOpsType                 cache_op_veth = NMP_CACHE_OPS_UNCHANGED;
Packit Service a1bd4f
    const char *                    veth_peer     = NULL;
Packit Service a1bd4f
    NMPObject *                     dev_obj;
Packit Service a1bd4f
    NMPObject *                     dev_lnk = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    device = link_add_pre(platform, name, type, address, address_len, mtu);
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(device);
Packit Service a1bd4f
Packit Service a1bd4f
    dev_obj = (NMPObject *) device->obj;
Packit Service a1bd4f
Packit Service a1bd4f
    if (parent > 0)
Packit Service a1bd4f
        dev_obj->link.parent = parent;
Packit Service a1bd4f
    else
Packit Service a1bd4f
        g_assert(parent == 0);
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert((parent != 0) == NM_IN_SET(type, NM_LINK_TYPE_VLAN));
Packit Service a1bd4f
Packit Service a1bd4f
    switch (type) {
Packit Service a1bd4f
    case NM_LINK_TYPE_BRIDGE:
Packit Service a1bd4f
    {
Packit Service a1bd4f
        const NMPlatformLnkBridge *props = extra_data;
Packit Service a1bd4f
Packit Service a1bd4f
        g_assert(props);
Packit Service a1bd4f
Packit Service a1bd4f
        dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_BRIDGE, props);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    }
Packit Service a1bd4f
    case NM_LINK_TYPE_VETH:
Packit Service a1bd4f
        veth_peer = extra_data;
Packit Service a1bd4f
        g_assert(veth_peer);
Packit Service a1bd4f
        device_veth = link_add_pre(platform, veth_peer, type, NULL, 0, 0);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    case NM_LINK_TYPE_VLAN:
Packit Service a1bd4f
    {
Packit Service a1bd4f
        const NMPlatformLnkVlan *props = extra_data;
Packit Service a1bd4f
Packit Service a1bd4f
        g_assert(props);
Packit Service a1bd4f
Packit Service a1bd4f
        dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_VLAN, props);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    }
Packit Service a1bd4f
    case NM_LINK_TYPE_VXLAN:
Packit Service a1bd4f
    {
Packit Service a1bd4f
        const NMPlatformLnkVxlan *props = extra_data;
Packit Service a1bd4f
Packit Service a1bd4f
        g_assert(props);
Packit Service a1bd4f
Packit Service a1bd4f
        dev_lnk = nmp_object_new(NMP_OBJECT_TYPE_LNK_VXLAN, props);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    }
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        g_assert(!extra_data);
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (dev_lnk)
Packit Service a1bd4f
        dev_obj->_link.netlink.lnk = dev_lnk;
Packit Service a1bd4f
Packit Service a1bd4f
    link_add_prepare(platform, device, (NMPObject *) device->obj);
Packit Service a1bd4f
    cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                        (NMPObject *) device->obj,
Packit Service a1bd4f
                                        FALSE,
Packit Service a1bd4f
                                        &obj_old,
Packit Service a1bd4f
                                        &obj_new);
Packit Service a1bd4f
    g_assert(cache_op == NMP_CACHE_OPS_ADDED);
Packit Service a1bd4f
    nmp_object_unref(device->obj);
Packit Service a1bd4f
    device->obj = nmp_object_ref(obj_new);
Packit Service a1bd4f
    if (veth_peer) {
Packit Service a1bd4f
        link_add_prepare(platform, device_veth, (NMPObject *) device_veth->obj);
Packit Service a1bd4f
        cache_op_veth = nmp_cache_update_netlink(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                                 (NMPObject *) device_veth->obj,
Packit Service a1bd4f
                                                 FALSE,
Packit Service a1bd4f
                                                 &obj_old_veth,
Packit Service a1bd4f
                                                 &obj_new_veth);
Packit Service a1bd4f
        g_assert(cache_op == NMP_CACHE_OPS_ADDED);
Packit Service a1bd4f
        nmp_object_unref(device->obj);
Packit Service a1bd4f
        device->obj = nmp_object_ref(obj_new);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (out_link)
Packit Service a1bd4f
        *out_link = NMP_OBJECT_CAST_LINK(device->obj);
Packit Service a1bd4f
Packit Service a1bd4f
    link_changed(platform, device, cache_op, NULL);
Packit Service a1bd4f
    if (veth_peer)
Packit Service a1bd4f
        link_changed(platform, device_veth, cache_op_veth, NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMFakePlatformLink *
Packit Service a1bd4f
link_add_one(NMPlatform *platform,
Packit Service a1bd4f
             const char *name,
Packit Service a1bd4f
             NMLinkType  link_type,
Packit Service a1bd4f
             void (*prepare_fcn)(NMPlatform *        platform,
Packit Service a1bd4f
                                 NMFakePlatformLink *device,
Packit Service a1bd4f
                                 gconstpointer       user_data),
Packit Service a1bd4f
             gconstpointer          user_data,
Packit Service a1bd4f
             const NMPlatformLink **out_link)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink * device;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new = NULL;
Packit Service a1bd4f
    NMPCacheOpsType                 cache_op;
Packit Service a1bd4f
    int                             ifindex;
Packit 5756e2
Packit Service a1bd4f
    device = link_add_pre(platform, name, NM_LINK_TYPE_VLAN, NULL, 0, 0);
Packit 5756e2
Packit Service a1bd4f
    ifindex = NMP_OBJECT_CAST_LINK(device->obj)->ifindex;
Packit 5756e2
Packit Service a1bd4f
    if (prepare_fcn)
Packit Service a1bd4f
        prepare_fcn(platform, device, user_data);
Packit 5756e2
Packit Service a1bd4f
    link_add_prepare(platform, device, (NMPObject *) device->obj);
Packit Service a1bd4f
    cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                        (NMPObject *) device->obj,
Packit Service a1bd4f
                                        FALSE,
Packit Service a1bd4f
                                        &obj_old,
Packit Service a1bd4f
                                        &obj_new);
Packit Service a1bd4f
    g_assert(cache_op == NMP_CACHE_OPS_ADDED);
Packit Service a1bd4f
    nmp_object_unref(device->obj);
Packit Service a1bd4f
    device->obj = nmp_object_ref(obj_new);
Packit 5756e2
Packit Service a1bd4f
    link_changed(platform, device, cache_op, obj_old);
Packit 5756e2
Packit Service a1bd4f
    device = link_get(platform, ifindex);
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        g_assert_not_reached();
Packit 5756e2
Packit Service a1bd4f
    NM_SET_OUT(out_link, NMP_OBJECT_CAST_LINK(device->obj));
Packit Service a1bd4f
    return device;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_delete(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink * device              = link_get(platform, ifindex);
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old  = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old2 = NULL;
Packit Service a1bd4f
    NMPCacheOpsType                 cache_op;
Packit Service a1bd4f
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    obj_old = g_steal_pointer(&device->obj);
Packit Service a1bd4f
Packit Service a1bd4f
    cache_op = nmp_cache_remove(nm_platform_get_cache(platform), obj_old, FALSE, FALSE, &obj_old2);
Packit Service a1bd4f
    g_assert(cache_op == NMP_CACHE_OPS_REMOVED);
Packit Service a1bd4f
    g_assert(obj_old2);
Packit Service a1bd4f
    g_assert(obj_old == obj_old2);
Packit Service a1bd4f
Packit Service a1bd4f
    /* Remove addresses and routes which belong to the deleted interface */
Packit Service a1bd4f
    ipx_address_delete(platform, AF_INET, ifindex, NULL, NULL, NULL);
Packit Service a1bd4f
    ipx_address_delete(platform, AF_INET6, ifindex, NULL, NULL, NULL);
Packit Service a1bd4f
    ipx_route_delete(platform, AF_INET, ifindex, NULL);
Packit Service a1bd4f
    ipx_route_delete(platform, AF_INET6, ifindex, NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    nm_platform_cache_update_emit_signal(platform, cache_op, obj_old2, NULL);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
link_set_obj(NMPlatform *platform, NMFakePlatformLink *device, NMPObject *obj_tmp)
Packit 5756e2
{
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj_tmp_tmp   = NULL;
Packit Service a1bd4f
    NMPCacheOpsType           cache_op;
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(device);
Packit Service a1bd4f
    g_assert(NMP_OBJECT_GET_TYPE(device->obj) == NMP_OBJECT_TYPE_LINK);
Packit Service a1bd4f
Packit Service a1bd4f
    if (!obj_tmp) {
Packit Service a1bd4f
        obj_tmp_tmp = nmp_object_clone(device->obj, FALSE);
Packit Service a1bd4f
        obj_tmp     = obj_tmp_tmp;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(NMP_OBJECT_GET_TYPE(obj_tmp) == NMP_OBJECT_TYPE_LINK);
Packit Service a1bd4f
Packit Service a1bd4f
    link_add_prepare(platform, device, obj_tmp);
Packit Service a1bd4f
    cache_op = nmp_cache_update_netlink(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                        obj_tmp,
Packit Service a1bd4f
                                        FALSE,
Packit Service a1bd4f
                                        &obj_old,
Packit Service a1bd4f
                                        &obj_new);
Packit Service a1bd4f
    g_assert(NM_IN_SET(cache_op, NMP_CACHE_OPS_UNCHANGED, NMP_CACHE_OPS_UPDATED));
Packit Service a1bd4f
    g_assert(obj_old == device->obj);
Packit Service a1bd4f
    g_assert(obj_new);
Packit Service a1bd4f
Packit Service a1bd4f
    nmp_object_unref(device->obj);
Packit Service a1bd4f
    device->obj = nmp_object_ref(obj_new);
Packit Service a1bd4f
Packit Service a1bd4f
    link_changed(platform, device, cache_op, obj_old);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
link_set_flags(NMPlatform *platform, NMFakePlatformLink *device, guint n_ifi_flags)
Packit 5756e2
{
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj_tmp = NULL;
Packit 5756e2
Packit Service a1bd4f
    g_assert(device);
Packit Service a1bd4f
    g_assert(NMP_OBJECT_GET_TYPE(device->obj) == NMP_OBJECT_TYPE_LINK);
Packit 5756e2
Packit Service a1bd4f
    obj_tmp                   = nmp_object_clone(device->obj, FALSE);
Packit Service a1bd4f
    obj_tmp->link.n_ifi_flags = n_ifi_flags;
Packit Service a1bd4f
    link_set_obj(platform, device, obj_tmp);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
link_changed(NMPlatform *        platform,
Packit Service a1bd4f
             NMFakePlatformLink *device,
Packit Service a1bd4f
             NMPCacheOpsType     cache_op,
Packit Service a1bd4f
             const NMPObject *   obj_old)
Packit 5756e2
{
Packit Service a1bd4f
    g_assert(device->obj);
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(!nmp_cache_link_connected_needs_toggle(nm_platform_get_cache(platform),
Packit Service a1bd4f
                                                    device->obj,
Packit Service a1bd4f
                                                    NULL,
Packit Service a1bd4f
                                                    NULL));
Packit Service a1bd4f
Packit Service a1bd4f
    nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, device->obj);
Packit Service a1bd4f
Packit Service a1bd4f
    if (!IN6_IS_ADDR_UNSPECIFIED(&device->ip6_lladdr)) {
Packit Service a1bd4f
        if (device->obj->link.connected)
Packit Service a1bd4f
            ip6_address_add(platform,
Packit Service a1bd4f
                            device->obj->link.ifindex,
Packit Service a1bd4f
                            device->ip6_lladdr,
Packit Service a1bd4f
                            64,
Packit Service a1bd4f
                            in6addr_any,
Packit Service a1bd4f
                            NM_PLATFORM_LIFETIME_PERMANENT,
Packit Service a1bd4f
                            NM_PLATFORM_LIFETIME_PERMANENT,
Packit Service a1bd4f
                            0);
Packit Service a1bd4f
        else
Packit Service a1bd4f
            ip6_address_delete(platform, device->obj->link.ifindex, device->ip6_lladdr, 64);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (device->obj->link.master) {
Packit Service a1bd4f
        NMFakePlatformLink *master;
Packit Service a1bd4f
Packit Service a1bd4f
        master = link_get(platform, device->obj->link.master);
Packit Service a1bd4f
        link_set_obj(platform, master, NULL);
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_set_up(NMPlatform *platform, int ifindex, gboolean *out_no_firmware)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (out_no_firmware)
Packit Service a1bd4f
        *out_no_firmware = FALSE;
Packit 5756e2
Packit Service a1bd4f
    if (!device) {
Packit Service a1bd4f
        _LOGE("failure changing link: netlink error (No such device)");
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    link_set_flags(platform, device, NM_FLAGS_ASSIGN(device->obj->link.n_ifi_flags, IFF_UP, TRUE));
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_set_down(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device) {
Packit Service a1bd4f
        _LOGE("failure changing link: netlink error (No such device)");
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_UP));
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_set_arp(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device) {
Packit Service a1bd4f
        _LOGE("failure changing link: netlink error (No such device)");
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    link_set_flags(platform, device, NM_FLAGS_UNSET(device->obj->link.n_ifi_flags, IFF_NOARP));
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_set_noarp(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device) {
Packit Service a1bd4f
        _LOGE("failure changing link: netlink error (No such device)");
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    link_set_flags(platform, device, NM_FLAGS_SET(device->obj->link.n_ifi_flags, IFF_NOARP));
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
link_set_address(NMPlatform *platform, int ifindex, gconstpointer addr, size_t len)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device        = link_get(platform, ifindex);
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj_tmp = NULL;
Packit 5756e2
Packit Service a1bd4f
    if (len == 0 || len > NM_UTILS_HWADDR_LEN_MAX || !addr)
Packit Service a1bd4f
        g_return_val_if_reached(-NME_BUG);
Packit 5756e2
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        return -NME_PL_EXISTS;
Packit 5756e2
Packit Service a1bd4f
    obj_tmp                     = nmp_object_clone(device->obj, FALSE);
Packit Service a1bd4f
    obj_tmp->link.l_address.len = len;
Packit Service a1bd4f
    memset(obj_tmp->link.l_address.data, 0, sizeof(obj_tmp->link.l_address.data));
Packit Service a1bd4f
    memcpy(obj_tmp->link.l_address.data, addr, len);
Packit 5756e2
Packit Service a1bd4f
    link_set_obj(platform, device, obj_tmp);
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
link_set_mtu(NMPlatform *platform, int ifindex, guint32 mtu)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device        = link_get(platform, ifindex);
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj_tmp = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    if (!device) {
Packit Service a1bd4f
        _LOGE("failure changing link: netlink error (No such device)");
Packit Service a1bd4f
        return -NME_PL_EXISTS;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    obj_tmp           = nmp_object_clone(device->obj, FALSE);
Packit Service a1bd4f
    obj_tmp->link.mtu = mtu;
Packit Service a1bd4f
    link_set_obj(platform, device, obj_tmp);
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_get_driver_info(NMPlatform *platform,
Packit Service a1bd4f
                     int         ifindex,
Packit Service a1bd4f
                     char **     out_driver_name,
Packit Service a1bd4f
                     char **     out_driver_version,
Packit Service a1bd4f
                     char **     out_fw_version)
Packit 5756e2
{
Packit Service a1bd4f
    if (out_driver_name)
Packit Service a1bd4f
        *out_driver_name = NULL;
Packit Service a1bd4f
    if (out_driver_version)
Packit Service a1bd4f
        *out_driver_version = NULL;
Packit Service a1bd4f
    if (out_fw_version)
Packit Service a1bd4f
        *out_fw_version = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_supports_carrier_detect(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    switch (device->obj->link.type) {
Packit Service a1bd4f
    case NM_LINK_TYPE_DUMMY:
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_supports_vlans(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    switch (device->obj->link.type) {
Packit Service a1bd4f
    case NM_LINK_TYPE_LOOPBACK:
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_supports_sriov(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit 5756e2
Packit Service a1bd4f
    if (!device)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    switch (device->obj->link.type) {
Packit Service a1bd4f
    case NM_LINK_TYPE_LOOPBACK:
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        return TRUE;
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_enslave(NMPlatform *platform, int master, int slave)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device        = link_get(platform, slave);
Packit Service a1bd4f
    NMFakePlatformLink *master_device = link_get(platform, master);
Packit 5756e2
Packit Service a1bd4f
    g_return_val_if_fail(device, FALSE);
Packit Service a1bd4f
    g_return_val_if_fail(master_device, FALSE);
Packit 5756e2
Packit Service a1bd4f
    if (device->obj->link.master != master) {
Packit Service a1bd4f
        nm_auto_nmpobj NMPObject *obj_tmp = NULL;
Packit 5756e2
Packit Service a1bd4f
        obj_tmp              = nmp_object_clone(device->obj, FALSE);
Packit Service a1bd4f
        obj_tmp->link.master = master;
Packit Service a1bd4f
        if (NM_IN_SET(master_device->obj->link.type, NM_LINK_TYPE_BOND, NM_LINK_TYPE_TEAM))
Packit Service a1bd4f
            obj_tmp->link.n_ifi_flags = NM_FLAGS_SET(device->obj->link.n_ifi_flags, IFF_UP);
Packit Service a1bd4f
        link_set_obj(platform, device, obj_tmp);
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_release(NMPlatform *platform, int master_idx, int slave_idx)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *master        = link_get(platform, master_idx);
Packit Service a1bd4f
    NMFakePlatformLink *slave         = link_get(platform, slave_idx);
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj_tmp = NULL;
Packit 5756e2
Packit Service a1bd4f
    g_return_val_if_fail(master, FALSE);
Packit Service a1bd4f
    g_return_val_if_fail(slave, FALSE);
Packit 5756e2
Packit Service a1bd4f
    if (slave->obj->link.master != master->obj->link.ifindex)
Packit Service a1bd4f
        return FALSE;
Packit 5756e2
Packit Service a1bd4f
    obj_tmp              = nmp_object_clone(slave->obj, FALSE);
Packit Service a1bd4f
    obj_tmp->link.master = 0;
Packit Service a1bd4f
    link_set_obj(platform, slave, obj_tmp);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
link_vlan_change(NMPlatform *            platform,
Packit Service a1bd4f
                 int                     ifindex,
Packit Service a1bd4f
                 NMVlanFlags             flags_mask,
Packit Service a1bd4f
                 NMVlanFlags             flags_set,
Packit Service a1bd4f
                 gboolean                ingress_reset_all,
Packit Service a1bd4f
                 const NMVlanQosMapping *ingress_map,
Packit Service a1bd4f
                 gsize                   n_ingress_map,
Packit Service a1bd4f
                 gboolean                egress_reset_all,
Packit Service a1bd4f
                 const NMVlanQosMapping *egress_map,
Packit Service a1bd4f
                 gsize                   n_egress_map)
Packit 5756e2
{
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
struct infiniband_add_data {
Packit Service a1bd4f
    int parent;
Packit Service a1bd4f
    int p_key;
Packit 5756e2
};
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
_infiniband_add_prepare(NMPlatform *platform, NMFakePlatformLink *device, gconstpointer user_data)
Packit 5756e2
{
Packit Service a1bd4f
    const struct infiniband_add_data *d = user_data;
Packit Service a1bd4f
    NMPObject *                       obj_tmp;
Packit Service a1bd4f
    NMPObject *                       lnk;
Packit 5756e2
Packit Service a1bd4f
    obj_tmp = (NMPObject *) device->obj;
Packit 5756e2
Packit Service a1bd4f
    lnk                       = nmp_object_new(NMP_OBJECT_TYPE_LNK_INFINIBAND, NULL);
Packit Service a1bd4f
    lnk->lnk_infiniband.p_key = d->p_key;
Packit Service a1bd4f
    lnk->lnk_infiniband.mode  = "datagram";
Packit 5756e2
Packit Service a1bd4f
    obj_tmp->link.parent       = d->parent;
Packit Service a1bd4f
    obj_tmp->_link.netlink.lnk = lnk;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
infiniband_partition_add(NMPlatform *           platform,
Packit Service a1bd4f
                         int                    parent,
Packit Service a1bd4f
                         int                    p_key,
Packit Service a1bd4f
                         const NMPlatformLink **out_link)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *             parent_device;
Packit Service a1bd4f
    char                             name[IFNAMSIZ];
Packit Service a1bd4f
    const struct infiniband_add_data d = {
Packit Service a1bd4f
        .parent = parent,
Packit Service a1bd4f
        .p_key  = p_key,
Packit Service a1bd4f
    };
Packit 5756e2
Packit Service a1bd4f
    parent_device = link_get(platform, parent);
Packit Service a1bd4f
    g_return_val_if_fail(parent_device != NULL, FALSE);
Packit 5756e2
Packit Service a1bd4f
    nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key);
Packit 5756e2
Packit Service a1bd4f
    link_add_one(platform, name, NM_LINK_TYPE_INFINIBAND, _infiniband_add_prepare, &d, out_link);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
infiniband_partition_delete(NMPlatform *platform, int parent, int p_key)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *parent_device;
Packit Service a1bd4f
    gs_free char *      name = NULL;
Packit 5756e2
Packit Service a1bd4f
    parent_device = link_get(platform, parent);
Packit Service a1bd4f
    g_return_val_if_fail(parent_device != NULL, FALSE);
Packit 5756e2
Packit Service a1bd4f
    nm_utils_new_infiniband_name(name, parent_device->obj->link.name, p_key);
Packit Service a1bd4f
    return link_delete(platform, nm_platform_link_get_ifindex(platform, name));
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilities *caps)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformLink *device = link_get(platform, ifindex);
Packit Service a1bd4f
Packit Service a1bd4f
    g_return_val_if_fail(device, FALSE);
Packit Service a1bd4f
Packit Service a1bd4f
    if (device->obj->link.type != NM_LINK_TYPE_WIFI)
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    if (caps) {
Packit Service a1bd4f
        *caps = (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104
Packit Service a1bd4f
                 | NM_WIFI_DEVICE_CAP_CIPHER_TKIP | NM_WIFI_DEVICE_CAP_CIPHER_CCMP
Packit Service a1bd4f
                 | NM_WIFI_DEVICE_CAP_WPA | NM_WIFI_DEVICE_CAP_RSN | NM_WIFI_DEVICE_CAP_AP
Packit Service a1bd4f
                 | NM_WIFI_DEVICE_CAP_ADHOC);
Packit Service a1bd4f
    }
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
wifi_get_bssid(NMPlatform *platform, int ifindex, guint8 *bssid)
Packit 5756e2
{
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static guint32
Packit Service a1bd4f
wifi_get_frequency(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
wifi_get_quality(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static guint32
Packit Service a1bd4f
wifi_get_rate(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NM80211Mode
Packit Service a1bd4f
wifi_get_mode(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    return NM_802_11_MODE_UNKNOWN;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wifi_set_mode(NMPlatform *platform, int ifindex, NM80211Mode mode)
Packit 5756e2
{
Packit Service a1bd4f
    ;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static guint32
Packit Service a1bd4f
wifi_find_frequency(NMPlatform *platform, int ifindex, const guint32 *freqs)
Packit 5756e2
{
Packit Service a1bd4f
    return freqs[0];
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
wifi_indicate_addressing_running(NMPlatform *platform, int ifindex, gboolean running)
Packit Service a1bd4f
{}
Packit 5756e2
Packit 5756e2
static guint32
Packit Service a1bd4f
mesh_get_channel(NMPlatform *platform, int ifindex)
Packit 5756e2
{
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
mesh_set_channel(NMPlatform *platform, int ifindex, guint32 channel)
Packit 5756e2
{
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
mesh_set_ssid(NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len)
Packit 5756e2
{
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ipx_address_add(NMPlatform *platform, int addr_family, const NMPlatformObject *address)
Packit 5756e2
{
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj = NULL;
Packit Service a1bd4f
    NMPCacheOpsType           cache_op;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new = NULL;
Packit Service a1bd4f
    NMPCache *                      cache   = nm_platform_get_cache(platform);
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service a1bd4f
Packit Service a1bd4f
    obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ADDRESS
Packit Service a1bd4f
                                                : NMP_OBJECT_TYPE_IP6_ADDRESS,
Packit Service a1bd4f
                         address);
Packit Service a1bd4f
Packit Service a1bd4f
    cache_op = nmp_cache_update_netlink(cache, obj, FALSE, &obj_old, &obj_new);
Packit Service a1bd4f
    nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new);
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip4_address_add(NMPlatform *platform,
Packit Service a1bd4f
                int         ifindex,
Packit Service a1bd4f
                in_addr_t   addr,
Packit Service a1bd4f
                guint8      plen,
Packit Service a1bd4f
                in_addr_t   peer_addr,
Packit Service a1bd4f
                in_addr_t   broadcast_address,
Packit Service a1bd4f
                guint32     lifetime,
Packit Service a1bd4f
                guint32     preferred,
Packit Service a1bd4f
                guint32     flags,
Packit Service a1bd4f
                const char *label)
Packit 5756e2
{
Packit Service a1bd4f
    NMPlatformIP4Address address;
Packit Service a1bd4f
Packit Service a1bd4f
    address = (NMPlatformIP4Address){
Packit Service a1bd4f
        .addr_source               = NM_IP_CONFIG_SOURCE_KERNEL,
Packit Service a1bd4f
        .ifindex                   = ifindex,
Packit Service a1bd4f
        .address                   = addr,
Packit Service a1bd4f
        .plen                      = plen,
Packit Service a1bd4f
        .peer_address              = peer_addr,
Packit Service a1bd4f
        .broadcast_address         = broadcast_address,
Packit Service a1bd4f
        .use_ip4_broadcast_address = TRUE,
Packit Service a1bd4f
        .timestamp                 = nm_utils_get_monotonic_timestamp_sec(),
Packit Service a1bd4f
        .lifetime                  = lifetime,
Packit Service a1bd4f
        .preferred                 = preferred,
Packit Service a1bd4f
        .n_ifa_flags               = flags,
Packit Service a1bd4f
    };
Packit Service a1bd4f
    if (label)
Packit Service a1bd4f
        g_strlcpy(address.label, label, sizeof(address.label));
Packit Service a1bd4f
Packit Service a1bd4f
    return ipx_address_add(platform, AF_INET, (const NMPlatformObject *) &address);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip6_address_add(NMPlatform *    platform,
Packit Service a1bd4f
                int             ifindex,
Packit Service a1bd4f
                struct in6_addr addr,
Packit Service a1bd4f
                guint8          plen,
Packit Service a1bd4f
                struct in6_addr peer_addr,
Packit Service a1bd4f
                guint32         lifetime,
Packit Service a1bd4f
                guint32         preferred,
Packit Service a1bd4f
                guint32         flags)
Packit 5756e2
{
Packit Service a1bd4f
    NMPlatformIP6Address address;
Packit Service a1bd4f
Packit Service a1bd4f
    memset(&address, 0, sizeof(address));
Packit Service a1bd4f
    address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
Packit Service a1bd4f
    address.ifindex     = ifindex;
Packit Service a1bd4f
    address.address     = addr;
Packit Service a1bd4f
    address.peer_address =
Packit Service a1bd4f
        (IN6_IS_ADDR_UNSPECIFIED(&peer_addr) || IN6_ARE_ADDR_EQUAL(&addr, &peer_addr)) ? in6addr_any
Packit Service a1bd4f
                                                                                       : peer_addr;
Packit Service a1bd4f
    address.plen        = plen;
Packit Service a1bd4f
    address.timestamp   = nm_utils_get_monotonic_timestamp_sec();
Packit Service a1bd4f
    address.lifetime    = lifetime;
Packit Service a1bd4f
    address.preferred   = preferred;
Packit Service a1bd4f
    address.n_ifa_flags = flags;
Packit Service a1bd4f
Packit Service a1bd4f
    return ipx_address_add(platform, AF_INET6, (const NMPlatformObject *) &address);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ipx_address_delete(NMPlatform *  platform,
Packit Service a1bd4f
                   int           addr_family,
Packit Service a1bd4f
                   int           ifindex,
Packit Service a1bd4f
                   gconstpointer addr,
Packit Service a1bd4f
                   const guint8 *plen,
Packit Service a1bd4f
                   gconstpointer peer_addr)
Packit 5756e2
{
Packit Service a1bd4f
    gs_unref_ptrarray GPtrArray *objs =
Packit Service a1bd4f
        g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
Packit Service a1bd4f
    NMDedupMultiIter iter;
Packit Service a1bd4f
    const NMPObject *o = NULL;
Packit Service a1bd4f
    guint            i;
Packit Service a1bd4f
    guint32          peer_addr_i;
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service a1bd4f
Packit Service a1bd4f
    peer_addr_i = peer_addr ? *((guint32 *) peer_addr) : 0;
Packit Service a1bd4f
Packit Service a1bd4f
    nmp_cache_iter_for_each (&iter,
Packit Service a1bd4f
                             nm_platform_lookup_object(platform,
Packit Service a1bd4f
                                                       addr_family == AF_INET
Packit Service a1bd4f
                                                           ? NMP_OBJECT_TYPE_IP4_ADDRESS
Packit Service a1bd4f
                                                           : NMP_OBJECT_TYPE_IP6_ADDRESS,
Packit Service a1bd4f
                                                       0),
Packit Service a1bd4f
                             &o) {
Packit Service a1bd4f
        const NMPObject *obj_old = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
        if (addr_family == AF_INET) {
Packit Service a1bd4f
            const NMPlatformIP4Address *address = NMP_OBJECT_CAST_IP4_ADDRESS(o);
Packit Service a1bd4f
Packit Service a1bd4f
            if (address->ifindex != ifindex || (addr && address->address != *((guint32 *) addr))
Packit Service a1bd4f
                || (plen && address->plen != *plen)
Packit Service a1bd4f
                || (peer_addr
Packit Service a1bd4f
                    && (((peer_addr_i ^ address->peer_address)
Packit Service a1bd4f
                         & _nm_utils_ip4_prefix_to_netmask(address->plen))
Packit Service a1bd4f
                        != 0)))
Packit Service a1bd4f
                continue;
Packit Service a1bd4f
        } else {
Packit Service a1bd4f
            const NMPlatformIP6Address *address = NMP_OBJECT_CAST_IP6_ADDRESS(o);
Packit Service a1bd4f
Packit Service a1bd4f
            g_assert(!peer_addr);
Packit Service a1bd4f
            if (address->ifindex != ifindex
Packit Service a1bd4f
                || (addr && !IN6_ARE_ADDR_EQUAL(&address->address, addr))
Packit Service a1bd4f
                || (plen && address->plen != *plen))
Packit Service a1bd4f
                continue;
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        if (nmp_cache_remove(nm_platform_get_cache(platform), o, TRUE, FALSE, &obj_old)
Packit Service a1bd4f
            != NMP_CACHE_OPS_REMOVED)
Packit Service a1bd4f
            g_assert_not_reached();
Packit Service a1bd4f
        g_assert(obj_old);
Packit Service a1bd4f
        g_ptr_array_add(objs, (gpointer) obj_old);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; i < objs->len; i++) {
Packit Service a1bd4f
        nm_platform_cache_update_emit_signal(platform, NMP_CACHE_OPS_REMOVED, objs->pdata[i], NULL);
Packit Service a1bd4f
    }
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip4_address_delete(NMPlatform *platform,
Packit Service a1bd4f
                   int         ifindex,
Packit Service a1bd4f
                   in_addr_t   addr,
Packit Service a1bd4f
                   guint8      plen,
Packit Service a1bd4f
                   in_addr_t   peer_address)
Packit 5756e2
{
Packit Service a1bd4f
    return ipx_address_delete(platform, AF_INET, ifindex, &addr, &plen, &peer_address);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ip6_address_delete(NMPlatform *platform, int ifindex, struct in6_addr addr, guint8 plen)
Packit 5756e2
{
Packit Service a1bd4f
    return ipx_address_delete(platform, AF_INET6, ifindex, &addr, &plen, NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
ipx_route_delete(NMPlatform *platform, int addr_family, int ifindex, const NMPObject *obj)
Packit 5756e2
{
Packit Service a1bd4f
    gs_unref_ptrarray GPtrArray *objs =
Packit Service a1bd4f
        g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
Packit Service a1bd4f
    NMDedupMultiIter iter;
Packit Service a1bd4f
    const NMPObject *o = NULL;
Packit Service a1bd4f
    guint            i;
Packit Service a1bd4f
    NMPObjectType    obj_type;
Packit Service a1bd4f
Packit Service a1bd4f
    if (addr_family == AF_UNSPEC) {
Packit Service a1bd4f
        g_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(obj),
Packit Service a1bd4f
                           NMP_OBJECT_TYPE_IP4_ROUTE,
Packit Service a1bd4f
                           NMP_OBJECT_TYPE_IP6_ROUTE));
Packit Service a1bd4f
        g_assert(ifindex == -1);
Packit Service a1bd4f
        ifindex  = NMP_OBJECT_CAST_IP_ROUTE(obj)->ifindex;
Packit Service a1bd4f
        obj_type = NMP_OBJECT_GET_TYPE(obj);
Packit Service a1bd4f
    } else {
Packit Service a1bd4f
        g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service a1bd4f
        g_assert(!obj);
Packit Service a1bd4f
        g_assert(ifindex > 0);
Packit Service a1bd4f
        obj_type = addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    nmp_cache_iter_for_each (&iter, nm_platform_lookup_object(platform, obj_type, ifindex), &o) {
Packit Service a1bd4f
        const NMPObject *obj_old = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
        if (obj) {
Packit Service a1bd4f
            if (obj_type == NMP_OBJECT_TYPE_IP4_ROUTE) {
Packit Service a1bd4f
                const NMPlatformIP4Route *route = NMP_OBJECT_CAST_IP4_ROUTE(o);
Packit Service a1bd4f
                const NMPlatformIP4Route *r     = NMP_OBJECT_CAST_IP4_ROUTE(obj);
Packit Service a1bd4f
Packit Service a1bd4f
                if (route->network != r->network || route->plen != r->plen
Packit Service a1bd4f
                    || route->metric != r->metric)
Packit Service a1bd4f
                    continue;
Packit Service a1bd4f
            } else {
Packit Service a1bd4f
                const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE(o);
Packit Service a1bd4f
                const NMPlatformIP6Route *r     = NMP_OBJECT_CAST_IP6_ROUTE(obj);
Packit Service a1bd4f
Packit Service a1bd4f
                if (!IN6_ARE_ADDR_EQUAL(&route->network, &r->network) || route->plen != r->plen
Packit Service a1bd4f
                    || route->metric != r->metric)
Packit Service a1bd4f
                    continue;
Packit Service a1bd4f
            }
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        if (nmp_cache_remove(nm_platform_get_cache(platform), o, TRUE, FALSE, &obj_old)
Packit Service a1bd4f
            != NMP_CACHE_OPS_REMOVED)
Packit Service a1bd4f
            g_assert_not_reached();
Packit Service a1bd4f
        g_assert(obj_old);
Packit Service a1bd4f
        g_ptr_array_add(objs, (gpointer) obj_old);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; i < objs->len; i++) {
Packit Service a1bd4f
        nm_platform_cache_update_emit_signal(platform, NMP_CACHE_OPS_REMOVED, objs->pdata[i], NULL);
Packit Service a1bd4f
    }
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static gboolean
Packit Service a1bd4f
object_delete(NMPlatform *platform, const NMPObject *obj)
Packit 5756e2
{
Packit Service a1bd4f
    g_assert(NM_IS_FAKE_PLATFORM(platform));
Packit Service a1bd4f
    g_assert(
Packit Service a1bd4f
        NM_IN_SET(NMP_OBJECT_GET_TYPE(obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
Packit 5756e2
Packit Service a1bd4f
    return ipx_route_delete(platform, AF_UNSPEC, -1, obj);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
ip_route_add(NMPlatform *             platform,
Packit Service a1bd4f
             NMPNlmFlags              flags,
Packit Service a1bd4f
             int                      addr_family,
Packit Service a1bd4f
             const NMPlatformIPRoute *route)
Packit 5756e2
{
Packit Service a1bd4f
    NMDedupMultiIter iter;
Packit Service a1bd4f
    nm_auto_nmpobj NMPObject *obj = NULL;
Packit Service a1bd4f
    NMPCacheOpsType           cache_op;
Packit Service a1bd4f
    const NMPObject *         o                 = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_old     = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_new     = NULL;
Packit Service a1bd4f
    nm_auto_nmpobj const NMPObject *obj_replace = NULL;
Packit Service a1bd4f
    NMPCache *                      cache       = nm_platform_get_cache(platform);
Packit Service a1bd4f
    gboolean                        has_gateway = FALSE;
Packit Service a1bd4f
    NMPlatformIPRoute *             r           = NULL;
Packit Service a1bd4f
    NMPlatformIP4Route *            r4          = NULL;
Packit Service a1bd4f
    NMPlatformIP6Route *            r6          = NULL;
Packit Service a1bd4f
    gboolean                        has_same_weak_id;
Packit Service a1bd4f
    gboolean                        only_dirty;
Packit Service a1bd4f
    guint16                         nlmsgflags;
Packit Service a1bd4f
Packit Service a1bd4f
    g_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service a1bd4f
Packit Service a1bd4f
    flags = NM_FLAGS_UNSET(flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE);
Packit Service a1bd4f
Packit Service a1bd4f
    /* currently, only replace is implemented. */
Packit Service a1bd4f
    g_assert(flags == NMP_NLM_FLAG_REPLACE);
Packit Service a1bd4f
Packit Service a1bd4f
    obj = nmp_object_new(addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE
Packit Service a1bd4f
                                                : NMP_OBJECT_TYPE_IP6_ROUTE,
Packit Service a1bd4f
                         (const NMPlatformObject *) route);
Packit Service a1bd4f
    r = NMP_OBJECT_CAST_IP_ROUTE(obj);
Packit Service a1bd4f
    nm_platform_ip_route_normalize(addr_family, r);
Packit Service a1bd4f
Packit Service a1bd4f
    switch (addr_family) {
Packit Service a1bd4f
    case AF_INET:
Packit Service a1bd4f
        r4 = NMP_OBJECT_CAST_IP4_ROUTE(obj);
Packit Service a1bd4f
        if (r4->gateway)
Packit Service a1bd4f
            has_gateway = TRUE;
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    case AF_INET6:
Packit Service a1bd4f
        r6 = NMP_OBJECT_CAST_IP6_ROUTE(obj);
Packit Service a1bd4f
        if (!IN6_IS_ADDR_UNSPECIFIED(&r6->gateway))
Packit Service a1bd4f
            has_gateway = TRUE;
Packit Service a1bd4f
        break;
Packit Service a1bd4f
    default:
Packit Service a1bd4f
        nm_assert_not_reached();
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (has_gateway) {
Packit Service a1bd4f
        gboolean has_route_to_gw = FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
        nmp_cache_iter_for_each (&iter,
Packit Service a1bd4f
                                 nm_platform_lookup_object(platform, NMP_OBJECT_GET_TYPE(obj), 0),
Packit Service a1bd4f
                                 &o) {
Packit Service a1bd4f
            if (addr_family == AF_INET) {
Packit Service a1bd4f
                const NMPlatformIP4Route *item = NMP_OBJECT_CAST_IP4_ROUTE(o);
Packit Service a1bd4f
                guint32 n = nm_utils_ip4_address_clear_host_address(item->network, item->plen);
Packit Service a1bd4f
                guint32 g = nm_utils_ip4_address_clear_host_address(r4->gateway, item->plen);
Packit Service a1bd4f
Packit Service a1bd4f
                if (r->ifindex == item->ifindex && n == g) {
Packit Service a1bd4f
                    has_route_to_gw = TRUE;
Packit Service a1bd4f
                    break;
Packit Service a1bd4f
                }
Packit Service a1bd4f
            } else {
Packit Service a1bd4f
                const NMPlatformIP6Route *item = NMP_OBJECT_CAST_IP6_ROUTE(o);
Packit Service a1bd4f
Packit Service a1bd4f
                if (r->ifindex == item->ifindex
Packit Service a1bd4f
                    && nm_utils_ip6_address_same_prefix(&r6->gateway, &item->network, item->plen)) {
Packit Service a1bd4f
                    has_route_to_gw = TRUE;
Packit Service a1bd4f
                    break;
Packit Service a1bd4f
                }
Packit Service a1bd4f
            }
Packit Service a1bd4f
        }
Packit Service a1bd4f
        if (!has_route_to_gw) {
Packit Service a1bd4f
            char sbuf[NM_UTILS_INET_ADDRSTRLEN];
Packit Service a1bd4f
Packit Service a1bd4f
            if (addr_family == AF_INET) {
Packit Service a1bd4f
                nm_log_warn(
Packit Service a1bd4f
                    LOGD_PLATFORM,
Packit Service a1bd4f
                    "Fake platform: failure adding ip4-route '%d: %s/%d %d': Network Unreachable",
Packit Service a1bd4f
                    r->ifindex,
Packit Service a1bd4f
                    _nm_utils_inet4_ntop(r4->network, sbuf),
Packit Service a1bd4f
                    r->plen,
Packit Service a1bd4f
                    r->metric);
Packit Service a1bd4f
            } else {
Packit Service a1bd4f
                nm_log_warn(
Packit Service a1bd4f
                    LOGD_PLATFORM,
Packit Service a1bd4f
                    "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
Packit Service a1bd4f
                    r->ifindex,
Packit Service a1bd4f
                    _nm_utils_inet6_ntop(&r6->network, sbuf),
Packit Service a1bd4f
                    r->plen,
Packit Service a1bd4f
                    r->metric);
Packit Service a1bd4f
            }
Packit Service a1bd4f
            return -NME_UNSPEC;
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    has_same_weak_id = FALSE;
Packit Service a1bd4f
    nmp_cache_iter_for_each (
Packit Service a1bd4f
        &iter,
Packit Service a1bd4f
        nm_platform_lookup_all(platform, NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, obj),
Packit Service a1bd4f
        &o) {
Packit Service a1bd4f
        if (addr_family == AF_INET) {
Packit Service a1bd4f
            if (nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(o),
Packit Service a1bd4f
                                          r4,
Packit Service a1bd4f
                                          NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)
Packit Service a1bd4f
                == 0)
Packit Service a1bd4f
                continue;
Packit Service a1bd4f
        } else {
Packit Service a1bd4f
            if (nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(o),
Packit Service a1bd4f
                                          r6,
Packit Service a1bd4f
                                          NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)
Packit Service a1bd4f
                == 0)
Packit Service a1bd4f
                continue;
Packit Service a1bd4f
        }
Packit Service a1bd4f
        has_same_weak_id = TRUE;
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    nlmsgflags = 0;
Packit Service a1bd4f
    if (has_same_weak_id) {
Packit Service a1bd4f
        switch (flags) {
Packit Service a1bd4f
        case NMP_NLM_FLAG_REPLACE:
Packit Service a1bd4f
            nlmsgflags = NLM_F_REPLACE;
Packit Service a1bd4f
            break;
Packit Service a1bd4f
        default:
Packit Service a1bd4f
            g_assert_not_reached();
Packit Service a1bd4f
            break;
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    /* we manipulate the cache the same was as NMLinuxPlatform does it. */
Packit Service a1bd4f
    cache_op   = nmp_cache_update_netlink_route(cache,
Packit Service a1bd4f
                                              obj,
Packit Service a1bd4f
                                              FALSE,
Packit Service a1bd4f
                                              nlmsgflags,
Packit Service a1bd4f
                                              &obj_old,
Packit Service a1bd4f
                                              &obj_new,
Packit Service a1bd4f
                                              &obj_replace,
Packit Service a1bd4f
                                              NULL);
Packit Service a1bd4f
    only_dirty = FALSE;
Packit Service a1bd4f
    if (cache_op != NMP_CACHE_OPS_UNCHANGED) {
Packit Service a1bd4f
        if (obj_replace) {
Packit Service a1bd4f
            const NMDedupMultiEntry *entry_replace;
Packit Service a1bd4f
Packit Service a1bd4f
            entry_replace = nmp_cache_lookup_entry(cache, obj_replace);
Packit Service a1bd4f
            nm_assert(entry_replace && entry_replace->obj == obj_replace);
Packit Service a1bd4f
            nm_dedup_multi_entry_set_dirty(entry_replace, TRUE);
Packit Service a1bd4f
            only_dirty = TRUE;
Packit Service a1bd4f
        }
Packit Service a1bd4f
        nm_platform_cache_update_emit_signal(platform, cache_op, obj_old, obj_new);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    if (obj_replace) {
Packit Service a1bd4f
        cache_op = nmp_cache_remove(cache, obj_replace, TRUE, only_dirty, NULL);
Packit Service a1bd4f
        if (cache_op != NMP_CACHE_OPS_UNCHANGED) {
Packit Service a1bd4f
            nm_assert(cache_op == NMP_CACHE_OPS_REMOVED);
Packit Service a1bd4f
            nm_platform_cache_update_emit_signal(platform, cache_op, obj_replace, NULL);
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    return 0;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/*****************************************************************************/
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nm_fake_platform_init(NMFakePlatform *fake_platform)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(fake_platform);
Packit 5756e2
Packit Service a1bd4f
    priv->options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
Packit Service a1bd4f
    priv->links   = g_array_new(TRUE, TRUE, sizeof(NMFakePlatformLink));
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
void
Packit Service a1bd4f
nm_fake_platform_setup(void)
Packit 5756e2
{
Packit Service a1bd4f
    NMPlatform *platform;
Packit 5756e2
Packit Service a1bd4f
    platform = g_object_new(NM_TYPE_FAKE_PLATFORM, NM_PLATFORM_LOG_WITH_PTR, FALSE, NULL);
Packit 5756e2
Packit Service a1bd4f
    nm_platform_setup(platform);
Packit 5756e2
Packit Service a1bd4f
    link_add(platform, NM_LINK_TYPE_LOOPBACK, "lo", 0, NULL, 0, 0, NULL, NULL);
Packit Service a1bd4f
    link_add(platform, NM_LINK_TYPE_ETHERNET, "eth0", 0, NULL, 0, 0, NULL, NULL);
Packit Service a1bd4f
    link_add(platform, NM_LINK_TYPE_ETHERNET, "eth1", 0, NULL, 0, 0, NULL, NULL);
Packit Service a1bd4f
    link_add(platform, NM_LINK_TYPE_ETHERNET, "eth2", 0, NULL, 0, 0, NULL, NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
finalize(GObject *object)
Packit 5756e2
{
Packit Service a1bd4f
    NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE(object);
Packit Service a1bd4f
    int                    i;
Packit 5756e2
Packit Service a1bd4f
    g_hash_table_unref(priv->options);
Packit Service a1bd4f
    for (i = 0; i < priv->links->len; i++) {
Packit Service a1bd4f
        NMFakePlatformLink *device = &g_array_index(priv->links, NMFakePlatformLink, i);
Packit 5756e2
Packit Service a1bd4f
        nm_clear_pointer(&device->obj, nmp_object_unref);
Packit Service a1bd4f
    }
Packit Service a1bd4f
    g_array_unref(priv->links);
Packit 5756e2
Packit Service a1bd4f
    G_OBJECT_CLASS(nm_fake_platform_parent_class)->finalize(object);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nm_fake_platform_class_init(NMFakePlatformClass *klass)
Packit 5756e2
{
Packit Service a1bd4f
    GObjectClass *              object_class   = G_OBJECT_CLASS(klass);
Packit Service a1bd4f
    NMPlatformClass *           platform_class = NM_PLATFORM_CLASS(klass);
Packit Service a1bd4f
    NMPlatformKernelSupportType kernel_support;
Packit 5756e2
Packit Service a1bd4f
    for (kernel_support = 0; kernel_support < _NM_PLATFORM_KERNEL_SUPPORT_NUM; kernel_support++)
Packit Service a1bd4f
        _nm_platform_kernel_support_init(kernel_support, -1);
Packit 5756e2
Packit Service a1bd4f
    object_class->finalize = finalize;
Packit 5756e2
Packit Service a1bd4f
    platform_class->sysctl_set = sysctl_set;
Packit Service a1bd4f
    platform_class->sysctl_get = sysctl_get;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_add    = link_add;
Packit Service a1bd4f
    platform_class->link_delete = link_delete;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_set_up    = link_set_up;
Packit Service a1bd4f
    platform_class->link_set_down  = link_set_down;
Packit Service a1bd4f
    platform_class->link_set_arp   = link_set_arp;
Packit Service a1bd4f
    platform_class->link_set_noarp = link_set_noarp;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_set_address = link_set_address;
Packit Service a1bd4f
    platform_class->link_set_mtu     = link_set_mtu;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_get_driver_info = link_get_driver_info;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
Packit Service a1bd4f
    platform_class->link_supports_vlans          = link_supports_vlans;
Packit Service a1bd4f
    platform_class->link_supports_sriov          = link_supports_sriov;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_enslave = link_enslave;
Packit Service a1bd4f
    platform_class->link_release = link_release;
Packit 5756e2
Packit Service a1bd4f
    platform_class->link_vlan_change = link_vlan_change;
Packit 5756e2
Packit Service a1bd4f
    platform_class->infiniband_partition_add    = infiniband_partition_add;
Packit Service a1bd4f
    platform_class->infiniband_partition_delete = infiniband_partition_delete;
Packit 5756e2
Packit Service a1bd4f
    platform_class->wifi_get_capabilities            = wifi_get_capabilities;
Packit Service a1bd4f
    platform_class->wifi_get_bssid                   = wifi_get_bssid;
Packit Service a1bd4f
    platform_class->wifi_get_frequency               = wifi_get_frequency;
Packit Service a1bd4f
    platform_class->wifi_get_quality                 = wifi_get_quality;
Packit Service a1bd4f
    platform_class->wifi_get_rate                    = wifi_get_rate;
Packit Service a1bd4f
    platform_class->wifi_get_mode                    = wifi_get_mode;
Packit Service a1bd4f
    platform_class->wifi_set_mode                    = wifi_set_mode;
Packit Service a1bd4f
    platform_class->wifi_find_frequency              = wifi_find_frequency;
Packit Service a1bd4f
    platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running;
Packit 5756e2
Packit Service a1bd4f
    platform_class->mesh_get_channel = mesh_get_channel;
Packit Service a1bd4f
    platform_class->mesh_set_channel = mesh_set_channel;
Packit Service a1bd4f
    platform_class->mesh_set_ssid    = mesh_set_ssid;
Packit 5756e2
Packit Service a1bd4f
    platform_class->ip4_address_add    = ip4_address_add;
Packit Service a1bd4f
    platform_class->ip6_address_add    = ip6_address_add;
Packit Service a1bd4f
    platform_class->ip4_address_delete = ip4_address_delete;
Packit Service a1bd4f
    platform_class->ip6_address_delete = ip6_address_delete;
Packit 5756e2
Packit Service a1bd4f
    platform_class->ip_route_add  = ip_route_add;
Packit Service a1bd4f
    platform_class->object_delete = object_delete;
Packit 5756e2
}