mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-02 11:10:16 +01:00
In the migration to NMPlatform, support for ptp/peer addresses was accidentally dropped. This broke OpenVPN configurations using 'p2p' topology, which send a different peer address than the local address for tunX, plus the server may also push routes that use the peer address as the next hop. NetworkManager was unable to add these routes, because the kernel had no idea how to talk to the peer, because the peer's address was not assigned to any interface or reachable over any routes. Partly based on a patch from Dan Williams.
1250 lines
34 KiB
C
1250 lines
34 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||
/* nm-platform-fake.c - Fake platform interaction code for testing NetworkManager
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation; either version 2, or (at your option)
|
||
* any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License along
|
||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
*
|
||
* Copyright (C) 2012–2013 Red Hat, Inc.
|
||
*/
|
||
|
||
#include <errno.h>
|
||
#include <unistd.h>
|
||
#include <netinet/icmp6.h>
|
||
#include <netinet/in.h>
|
||
|
||
#include "nm-fake-platform.h"
|
||
#include "nm-logging.h"
|
||
|
||
#define debug(format, ...) nm_log_dbg (LOGD_PLATFORM, format, __VA_ARGS__)
|
||
|
||
typedef struct {
|
||
GHashTable *options;
|
||
GArray *links;
|
||
GArray *ip4_addresses;
|
||
GArray *ip6_addresses;
|
||
GArray *ip4_routes;
|
||
GArray *ip6_routes;
|
||
|
||
GSList *link_added_ids;
|
||
} NMFakePlatformPrivate;
|
||
|
||
typedef struct {
|
||
NMPlatformLink link;
|
||
|
||
char *udi;
|
||
GBytes *address;
|
||
int vlan_id;
|
||
} NMFakePlatformLink;
|
||
|
||
#define NM_FAKE_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_FAKE_PLATFORM, NMFakePlatformPrivate))
|
||
|
||
G_DEFINE_TYPE (NMFakePlatform, nm_fake_platform, NM_TYPE_PLATFORM)
|
||
|
||
/******************************************************************/
|
||
|
||
void
|
||
nm_fake_platform_setup (void)
|
||
{
|
||
nm_platform_setup (NM_TYPE_FAKE_PLATFORM);
|
||
}
|
||
|
||
/******************************************************************/
|
||
|
||
static gboolean
|
||
sysctl_set (NMPlatform *platform, const char *path, const char *value)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
|
||
g_hash_table_insert (priv->options, g_strdup (path), g_strdup (value));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static char *
|
||
sysctl_get (NMPlatform *platform, const char *path)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
|
||
return g_strdup (g_hash_table_lookup (priv->options, path));
|
||
}
|
||
|
||
static const char *
|
||
type_to_type_name (NMLinkType type)
|
||
{
|
||
switch (type) {
|
||
case NM_LINK_TYPE_UNKNOWN:
|
||
return "unknown";
|
||
case NM_LINK_TYPE_LOOPBACK:
|
||
return "loopback";
|
||
case NM_LINK_TYPE_ETHERNET:
|
||
return "ethernet";
|
||
case NM_LINK_TYPE_DUMMY:
|
||
return "dummy";
|
||
case NM_LINK_TYPE_BRIDGE:
|
||
return "bridge";
|
||
case NM_LINK_TYPE_BOND:
|
||
return "bond";
|
||
case NM_LINK_TYPE_TEAM:
|
||
return "team";
|
||
case NM_LINK_TYPE_VLAN:
|
||
return "vlan";
|
||
case NM_LINK_TYPE_NONE:
|
||
default:
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
static void
|
||
link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name)
|
||
{
|
||
g_assert (!name || strlen (name) < sizeof(device->link.name));
|
||
|
||
memset (device, 0, sizeof (*device));
|
||
|
||
device->link.ifindex = name ? ifindex : 0;
|
||
device->link.type = type;
|
||
device->link.type_name = type_to_type_name (type);
|
||
device->link.driver = type_to_type_name (type);
|
||
device->link.udi = device->udi = g_strdup_printf ("fake:%d", ifindex);
|
||
if (name)
|
||
strcpy (device->link.name, name);
|
||
switch (device->link.type) {
|
||
case NM_LINK_TYPE_DUMMY:
|
||
device->link.arp = FALSE;
|
||
break;
|
||
default:
|
||
device->link.arp = TRUE;
|
||
}
|
||
device->address = NULL;
|
||
}
|
||
|
||
static NMFakePlatformLink *
|
||
link_get (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMFakePlatformLink *device;
|
||
|
||
if (ifindex >= priv->links->len)
|
||
goto not_found;
|
||
device = &g_array_index (priv->links, NMFakePlatformLink, ifindex);
|
||
if (!device->link.ifindex)
|
||
goto not_found;
|
||
|
||
return device;
|
||
not_found:
|
||
debug ("link not found: %d", ifindex);
|
||
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
||
return NULL;
|
||
}
|
||
|
||
static GArray *
|
||
link_get_all (NMPlatform *platform)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
GArray *links = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), priv->links->len);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->links->len; i++)
|
||
if (g_array_index (priv->links, NMFakePlatformLink, i).link.ifindex)
|
||
g_array_append_val (links, g_array_index (priv->links, NMFakePlatformLink, i).link);
|
||
|
||
return links;
|
||
}
|
||
|
||
typedef struct {
|
||
NMPlatform *platform;
|
||
int ifindex;
|
||
guint id;
|
||
} LinkAddedInfo;
|
||
|
||
static gboolean
|
||
link_added_emit (gpointer user_data)
|
||
{
|
||
LinkAddedInfo *info = user_data;
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (info->platform);
|
||
NMFakePlatformLink *device;
|
||
|
||
priv->link_added_ids = g_slist_remove (priv->link_added_ids, GUINT_TO_POINTER (info->id));
|
||
|
||
device = link_get (info->platform, info->ifindex);
|
||
g_assert (device);
|
||
g_signal_emit_by_name (info->platform, NM_PLATFORM_LINK_ADDED, info->ifindex, &device->link, NM_PLATFORM_REASON_INTERNAL);
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
link_add (NMPlatform *platform, const char *name, NMLinkType type)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMFakePlatformLink device;
|
||
LinkAddedInfo *info;
|
||
|
||
link_init (&device, priv->links->len, type, name);
|
||
|
||
g_array_append_val (priv->links, device);
|
||
|
||
if (device.link.ifindex) {
|
||
/* Platform requires LINK_ADDED signal emission from an idle handler */
|
||
info = g_new0 (LinkAddedInfo, 1);
|
||
info->platform = platform;
|
||
info->ifindex = device.link.ifindex;
|
||
info->id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
|
||
link_added_emit,
|
||
info,
|
||
g_free);
|
||
priv->link_added_ids = g_slist_prepend (priv->link_added_ids, GUINT_TO_POINTER (info->id));
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_delete (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
NMPlatformLink deleted_device;
|
||
int i;
|
||
|
||
if (!device || !device->link.ifindex)
|
||
return FALSE;
|
||
|
||
memcpy (&deleted_device, &device->link, sizeof (deleted_device));
|
||
memset (&device->link, 0, sizeof (device->link));
|
||
|
||
/* Remove addresses and routes which belong to the deleted interface */
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
|
||
if (address->ifindex == ifindex)
|
||
memset (address, 0, sizeof (*address));
|
||
}
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
|
||
if (address->ifindex == ifindex)
|
||
memset (address, 0, sizeof (*address));
|
||
}
|
||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||
|
||
if (route->ifindex == ifindex)
|
||
memset (route, 0, sizeof (*route));
|
||
}
|
||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||
|
||
if (route->ifindex == ifindex)
|
||
memset (route, 0, sizeof (*route));
|
||
}
|
||
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_LINK_REMOVED, ifindex, &deleted_device, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static int
|
||
link_get_ifindex (NMPlatform *platform, const char *name)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->links->len; i++) {
|
||
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
|
||
|
||
if (device && !g_strcmp0 (device->link.name, name))
|
||
return device->link.ifindex;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static const char *
|
||
link_get_name (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.name : NULL;
|
||
}
|
||
|
||
static NMLinkType
|
||
link_get_type (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.type : NM_LINK_TYPE_NONE;
|
||
}
|
||
|
||
static const char *
|
||
link_get_type_name (NMPlatform *platform, int ifindex)
|
||
{
|
||
return type_to_type_name (link_get_type (platform, ifindex));
|
||
}
|
||
|
||
static void
|
||
link_changed (NMPlatform *platform, NMFakePlatformLink *device)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_LINK_CHANGED, device->link.ifindex, &device->link, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
if (device->link.master) {
|
||
NMFakePlatformLink *master = link_get (platform, device->link.master);
|
||
|
||
g_return_if_fail (master != device);
|
||
|
||
master->link.connected = FALSE;
|
||
for (i = 0; i < priv->links->len; i++) {
|
||
NMFakePlatformLink *slave = &g_array_index (priv->links, NMFakePlatformLink, i);
|
||
|
||
if (slave && slave->link.master == master->link.ifindex && slave->link.connected)
|
||
master->link.connected = TRUE;
|
||
}
|
||
|
||
link_changed (platform, master);
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
link_set_up (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
device->link.up = TRUE;
|
||
switch (device->link.type) {
|
||
case NM_LINK_TYPE_DUMMY:
|
||
case NM_LINK_TYPE_VLAN:
|
||
device->link.connected = TRUE;
|
||
break;
|
||
case NM_LINK_TYPE_BRIDGE:
|
||
case NM_LINK_TYPE_BOND:
|
||
case NM_LINK_TYPE_TEAM:
|
||
device->link.connected = FALSE;
|
||
break;
|
||
default:
|
||
device->link.connected = FALSE;
|
||
g_error ("Unexpected device type: %d", device->link.type);
|
||
}
|
||
|
||
link_changed (platform, device);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_set_down (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
device->link.up = FALSE;
|
||
device->link.connected = FALSE;
|
||
|
||
link_changed (platform, device);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_set_arp (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
device->link.arp = TRUE;
|
||
|
||
link_changed (platform, device);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_set_noarp (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
device->link.arp = FALSE;
|
||
|
||
link_changed (platform, device);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_is_up (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.up : FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
link_is_connected (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.connected : FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
link_uses_arp (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.arp : FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (device->address)
|
||
g_bytes_unref (device->address);
|
||
|
||
device->address = g_bytes_new (addr, len);
|
||
|
||
link_changed (platform, link_get (platform, ifindex));
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gconstpointer
|
||
link_get_address (NMPlatform *platform, int ifindex, size_t *length)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device || !device->address) {
|
||
if (length)
|
||
*length = 0;
|
||
return NULL;
|
||
}
|
||
|
||
return g_bytes_get_data (device->address, length);
|
||
}
|
||
|
||
static gboolean
|
||
link_set_mtu (NMPlatform *platform, int ifindex, guint32 mtu)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (device) {
|
||
device->link.mtu = mtu;
|
||
link_changed (platform, device);
|
||
}
|
||
|
||
return !!device;
|
||
}
|
||
|
||
static guint32
|
||
link_get_mtu (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
return device ? device->link.mtu : 0;
|
||
}
|
||
|
||
static char *
|
||
link_get_physical_port_id (NMPlatform *platform, int ifindex)
|
||
{
|
||
/* We call link_get just to cause an error to be set if @ifindex is bad. */
|
||
link_get (platform, ifindex);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static gboolean
|
||
link_supports_carrier_detect (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
switch (device->link.type) {
|
||
case NM_LINK_TYPE_DUMMY:
|
||
return FALSE;
|
||
default:
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
link_supports_vlans (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
if (!device)
|
||
return FALSE;
|
||
|
||
switch (device->link.type) {
|
||
case NM_LINK_TYPE_LOOPBACK:
|
||
return FALSE;
|
||
default:
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
static gboolean
|
||
link_enslave (NMPlatform *platform, int master, int slave)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, slave);
|
||
|
||
g_return_val_if_fail (device, FALSE);
|
||
|
||
device->link.master = master;
|
||
|
||
link_changed (platform, device);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
link_release (NMPlatform *platform, int master_idx, int slave_idx)
|
||
{
|
||
NMFakePlatformLink *master = link_get (platform, master_idx);
|
||
NMFakePlatformLink *slave = link_get (platform, slave_idx);
|
||
|
||
g_return_val_if_fail (master, FALSE);
|
||
g_return_val_if_fail (slave, FALSE);
|
||
|
||
if (slave->link.master != master->link.ifindex) {
|
||
platform->error = NM_PLATFORM_ERROR_NOT_SLAVE;
|
||
return FALSE;
|
||
}
|
||
|
||
slave->link.master = 0;
|
||
|
||
link_changed (platform, slave);
|
||
link_changed (platform, master);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static int
|
||
link_get_master (NMPlatform *platform, int slave)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, slave);
|
||
|
||
g_return_val_if_fail (device, FALSE);
|
||
|
||
return device->link.master;
|
||
}
|
||
|
||
static gboolean
|
||
master_set_option (NMPlatform *platform, int master, const char *option, const char *value)
|
||
{
|
||
auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option);
|
||
|
||
return sysctl_set (platform, path, value);
|
||
}
|
||
|
||
static char *
|
||
master_get_option (NMPlatform *platform, int master, const char *option)
|
||
{
|
||
auto_g_free char *path = g_strdup_printf ("master:%d:%s", master, option);
|
||
|
||
return sysctl_get (platform, path);
|
||
}
|
||
|
||
static gboolean
|
||
slave_set_option (NMPlatform *platform, int slave, const char *option, const char *value)
|
||
{
|
||
auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option);
|
||
|
||
return sysctl_set (platform, path, value);
|
||
}
|
||
|
||
static char *
|
||
slave_get_option (NMPlatform *platform, int slave, const char *option)
|
||
{
|
||
auto_g_free char *path = g_strdup_printf ("slave:%d:%s", slave, option);
|
||
|
||
return sysctl_get (platform, path);
|
||
}
|
||
|
||
static gboolean
|
||
vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags)
|
||
{
|
||
NMFakePlatformLink *device;
|
||
|
||
if (!link_add (platform, name, NM_LINK_TYPE_VLAN))
|
||
return FALSE;
|
||
|
||
device = link_get (platform, link_get_ifindex (platform, name));
|
||
|
||
g_return_val_if_fail (device, FALSE);
|
||
|
||
device->vlan_id = vlan_id;
|
||
device->link.parent = parent;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
vlan_get_info (NMPlatform *platform, int ifindex, int *parent, int *vlan_id)
|
||
{
|
||
NMFakePlatformLink *device = link_get (platform, ifindex);
|
||
|
||
g_return_val_if_fail (device, FALSE);
|
||
|
||
if (parent)
|
||
*parent = device->link.parent;
|
||
if (vlan_id)
|
||
*vlan_id = device->vlan_id;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
vlan_set_ingress_map (NMPlatform *platform, int ifindex, int from, int to)
|
||
{
|
||
return !!link_get (platform, ifindex);
|
||
}
|
||
|
||
static gboolean
|
||
vlan_set_egress_map (NMPlatform *platform, int ifindex, int from, int to)
|
||
{
|
||
return !!link_get (platform, ifindex);
|
||
}
|
||
|
||
static gboolean
|
||
infiniband_partition_add (NMPlatform *platform, int parent, int p_key)
|
||
{
|
||
NMFakePlatformLink *parent_device;
|
||
char *name;
|
||
gboolean success;
|
||
|
||
parent_device = link_get (platform, parent);
|
||
g_return_val_if_fail (parent_device != NULL, FALSE);
|
||
|
||
name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key);
|
||
success = link_add (platform, name, NM_LINK_TYPE_INFINIBAND);
|
||
g_free (name);
|
||
|
||
return success;
|
||
}
|
||
|
||
static gboolean
|
||
veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties *props)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *props)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProperties *props)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
gre_get_properties (NMPlatform *platform, int ifindex, NMPlatformGreProperties *props)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
/******************************************************************/
|
||
|
||
static GArray *
|
||
ip4_address_get_all (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
GArray *addresses;
|
||
NMPlatformIP4Address *address;
|
||
int count = 0, i;
|
||
|
||
/* Count addresses */
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
if (address && address->ifindex == ifindex)
|
||
count++;
|
||
}
|
||
|
||
addresses = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Address), count);
|
||
|
||
/* Fill addresses */
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
if (address && address->ifindex == ifindex)
|
||
g_array_append_val (addresses, *address);
|
||
}
|
||
|
||
return addresses;
|
||
}
|
||
|
||
static GArray *
|
||
ip6_address_get_all (NMPlatform *platform, int ifindex)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
GArray *addresses;
|
||
NMPlatformIP6Address *address;
|
||
int count = 0, i;
|
||
|
||
/* Count addresses */
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
if (address && address->ifindex == ifindex)
|
||
count++;
|
||
}
|
||
|
||
addresses = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Address), count);
|
||
|
||
/* Fill addresses */
|
||
count = 0;
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
if (address && address->ifindex == ifindex)
|
||
g_array_append_val (addresses, *address);
|
||
}
|
||
|
||
return addresses;
|
||
}
|
||
|
||
static guint32
|
||
get_time (void)
|
||
{
|
||
struct timespec tp;
|
||
|
||
clock_gettime (CLOCK_MONOTONIC, &tp);
|
||
|
||
return tp.tv_sec;
|
||
}
|
||
|
||
static gboolean
|
||
ip4_address_add (NMPlatform *platform, int ifindex,
|
||
in_addr_t addr, in_addr_t peer_addr,
|
||
int plen, guint32 lifetime, guint32 preferred)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMPlatformIP4Address address;
|
||
int i;
|
||
|
||
memset (&address, 0, sizeof (address));
|
||
address.ifindex = ifindex;
|
||
address.address = addr;
|
||
address.peer_address = peer_addr;
|
||
address.plen = plen;
|
||
address.timestamp = get_time ();
|
||
address.lifetime = lifetime;
|
||
address.preferred = preferred;
|
||
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
NMPlatformIP4Address *item = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
|
||
if (item->ifindex != address.ifindex)
|
||
continue;
|
||
if (item->address != address.address)
|
||
continue;
|
||
if (item->plen != address.plen)
|
||
continue;
|
||
|
||
memcpy (item, &address, sizeof (address));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
|
||
g_array_append_val (priv->ip4_addresses, address);
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ADDRESS_ADDED, ifindex, &address, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
ip6_address_add (NMPlatform *platform, int ifindex,
|
||
struct in6_addr addr, struct in6_addr peer_addr,
|
||
int plen, guint32 lifetime, guint32 preferred, guint flags)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMPlatformIP6Address address;
|
||
int i;
|
||
|
||
memset (&address, 0, sizeof (address));
|
||
address.ifindex = ifindex;
|
||
address.address = addr;
|
||
address.peer_address = peer_addr;
|
||
address.plen = plen;
|
||
address.timestamp = get_time ();
|
||
address.lifetime = lifetime;
|
||
address.preferred = preferred;
|
||
address.flags = flags;
|
||
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
NMPlatformIP6Address *item = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
|
||
if (item->ifindex != address.ifindex)
|
||
continue;
|
||
if (!IN6_ARE_ADDR_EQUAL (&item->address, &address.address))
|
||
continue;
|
||
if (item->plen != address.plen)
|
||
continue;
|
||
|
||
memcpy (item, &address, sizeof (address));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ADDRESS_CHANGED, ifindex, &address, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
|
||
g_array_append_val (priv->ip6_addresses, address);
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ADDRESS_ADDED, ifindex, &address, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
|
||
if (address->ifindex == ifindex && address->plen == plen && address->address == addr) {
|
||
NMPlatformIP4Address deleted_address;
|
||
|
||
memcpy (&deleted_address, address, sizeof (deleted_address));
|
||
memset (address, 0, sizeof (*address));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ADDRESS_REMOVED, ifindex, &deleted_address, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
g_assert_not_reached ();
|
||
}
|
||
|
||
static gboolean
|
||
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
|
||
if (address->ifindex == ifindex && address->plen == plen
|
||
&& IN6_ARE_ADDR_EQUAL (&address->address, &addr)) {
|
||
NMPlatformIP6Address deleted_address;
|
||
|
||
memcpy (&deleted_address, address, sizeof (deleted_address));
|
||
memset (address, 0, sizeof (*address));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ADDRESS_REMOVED, ifindex, &deleted_address, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
g_assert_not_reached ();
|
||
}
|
||
|
||
static gboolean
|
||
ip4_address_exists (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip4_addresses->len; i++) {
|
||
NMPlatformIP4Address *address = &g_array_index (priv->ip4_addresses, NMPlatformIP4Address, i);
|
||
|
||
if (address->ifindex == ifindex && address->plen == plen && address->address == addr)
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
static gboolean
|
||
ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip6_addresses->len; i++) {
|
||
NMPlatformIP6Address *address = &g_array_index (priv->ip6_addresses, NMPlatformIP6Address, i);
|
||
|
||
if (address->ifindex == ifindex && address->plen == plen &&
|
||
IN6_ARE_ADDR_EQUAL (&address->address, &addr))
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
/******************************************************************/
|
||
|
||
static GArray *
|
||
ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
GArray *routes;
|
||
NMPlatformIP4Route *route;
|
||
int count = 0, i;
|
||
|
||
/* Count routes */
|
||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||
route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||
if (route && route->ifindex == ifindex)
|
||
count++;
|
||
}
|
||
|
||
routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Route), count);
|
||
|
||
/* Fill routes */
|
||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||
route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||
if (route && route->ifindex == ifindex) {
|
||
if (route->plen != 0 || include_default)
|
||
g_array_append_val (routes, *route);
|
||
}
|
||
}
|
||
|
||
return routes;
|
||
}
|
||
|
||
static GArray *
|
||
ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
GArray *routes;
|
||
NMPlatformIP6Route *route;
|
||
int count = 0, i;
|
||
|
||
/* Count routes */
|
||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||
route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||
if (route && route->ifindex == ifindex)
|
||
count++;
|
||
}
|
||
|
||
routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Route), count);
|
||
|
||
/* Fill routes */
|
||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||
route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||
if (route && route->ifindex == ifindex) {
|
||
if (route->plen != 0 || include_default)
|
||
g_array_append_val (routes, *route);
|
||
}
|
||
}
|
||
|
||
return routes;
|
||
}
|
||
|
||
static gboolean
|
||
ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen,
|
||
in_addr_t gateway, int metric, int mss)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMPlatformIP4Route route;
|
||
guint i;
|
||
|
||
memset (&route, 0, sizeof (route));
|
||
route.ifindex = ifindex;
|
||
route.network = network;
|
||
route.plen = plen;
|
||
route.gateway = gateway;
|
||
route.metric = metric;
|
||
route.mss = mss;
|
||
|
||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||
NMPlatformIP4Route *item = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||
|
||
if (item->ifindex != route.ifindex)
|
||
continue;
|
||
if (item->network != route.network)
|
||
continue;
|
||
if (item->plen != route.plen)
|
||
continue;
|
||
|
||
memcpy (item, &route, sizeof (route));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
|
||
g_array_append_val (priv->ip4_routes, route);
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_ADDED, ifindex, &route, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
ip6_route_add (NMPlatform *platform, int ifindex, struct in6_addr network, int plen,
|
||
struct in6_addr gateway, int metric, int mss)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
NMPlatformIP6Route route;
|
||
guint i;
|
||
|
||
memset (&route, 0, sizeof (route));
|
||
route.ifindex = ifindex;
|
||
route.network = network;
|
||
route.plen = plen;
|
||
route.gateway = gateway;
|
||
route.metric = metric;
|
||
route.mss = mss;
|
||
|
||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||
NMPlatformIP6Route *item = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||
|
||
if (item->ifindex != route.ifindex)
|
||
continue;
|
||
if (!IN6_ARE_ADDR_EQUAL (&item->network, &route.network))
|
||
continue;
|
||
if (item->plen != route.plen)
|
||
continue;
|
||
|
||
memcpy (item, &route, sizeof (route));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_CHANGED, ifindex, &route, NM_PLATFORM_REASON_INTERNAL);
|
||
return TRUE;
|
||
}
|
||
|
||
g_array_append_val (priv->ip6_routes, route);
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_ADDED, ifindex, &route, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static NMPlatformIP4Route *
|
||
ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip4_routes->len; i++) {
|
||
NMPlatformIP4Route *route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
|
||
|
||
if (route->ifindex == ifindex
|
||
&& route->network == network
|
||
&& route->plen == plen
|
||
&& route->metric == metric)
|
||
return route;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static NMPlatformIP6Route *
|
||
ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
|
||
int i;
|
||
|
||
for (i = 0; i < priv->ip6_routes->len; i++) {
|
||
NMPlatformIP6Route *route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
|
||
|
||
if (route->ifindex == ifindex
|
||
&& IN6_ARE_ADDR_EQUAL (&route->network, &network)
|
||
&& route->plen == plen
|
||
&& route->metric == metric)
|
||
return route;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static gboolean
|
||
ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
|
||
{
|
||
NMPlatformIP4Route *route = ip4_route_get (platform, ifindex, network, plen, metric);
|
||
NMPlatformIP4Route deleted_route;
|
||
|
||
g_assert (route);
|
||
|
||
memcpy (&deleted_route, route, sizeof (deleted_route));
|
||
memset (route, 0, sizeof (*route));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
|
||
{
|
||
NMPlatformIP6Route *route = ip6_route_get (platform, ifindex, network, plen, metric);
|
||
NMPlatformIP6Route deleted_route;
|
||
|
||
g_assert (route);
|
||
|
||
memcpy (&deleted_route, route, sizeof (deleted_route));
|
||
memset (route, 0, sizeof (*route));
|
||
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_REMOVED, ifindex, &deleted_route, NM_PLATFORM_REASON_INTERNAL);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static gboolean
|
||
ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
|
||
{
|
||
return !!ip4_route_get (platform, ifindex, network, plen, metric);
|
||
}
|
||
|
||
static gboolean
|
||
ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
|
||
{
|
||
return !!ip6_route_get (platform, ifindex, network, plen, metric);
|
||
}
|
||
|
||
/******************************************************************/
|
||
|
||
static void
|
||
nm_fake_platform_init (NMFakePlatform *fake_platform)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (fake_platform);
|
||
|
||
priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||
priv->links = g_array_new (TRUE, TRUE, sizeof (NMFakePlatformLink));
|
||
priv->ip4_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Address));
|
||
priv->ip6_addresses = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Address));
|
||
priv->ip4_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route));
|
||
priv->ip6_routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route));
|
||
}
|
||
|
||
static gboolean
|
||
setup (NMPlatform *platform)
|
||
{
|
||
/* skip zero element */
|
||
link_add (platform, NULL, NM_LINK_TYPE_NONE);
|
||
|
||
/* add loopback interface */
|
||
link_add (platform, "lo", NM_LINK_TYPE_LOOPBACK);
|
||
|
||
/* add some ethernets */
|
||
link_add (platform, "eth0", NM_LINK_TYPE_ETHERNET);
|
||
link_add (platform, "eth1", NM_LINK_TYPE_ETHERNET);
|
||
link_add (platform, "eth2", NM_LINK_TYPE_ETHERNET);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
static void
|
||
nm_fake_platform_finalize (GObject *object)
|
||
{
|
||
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object);
|
||
int i;
|
||
GSList *iter;
|
||
|
||
for (iter = priv->link_added_ids; iter; iter = iter->next)
|
||
g_source_remove (GPOINTER_TO_UINT (iter->data));
|
||
g_slist_free (priv->link_added_ids);
|
||
|
||
g_hash_table_unref (priv->options);
|
||
for (i = 0; i < priv->links->len; i++) {
|
||
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
|
||
|
||
g_bytes_unref (device->address);
|
||
g_free (device->udi);
|
||
}
|
||
g_array_unref (priv->links);
|
||
g_array_unref (priv->ip4_addresses);
|
||
g_array_unref (priv->ip6_addresses);
|
||
g_array_unref (priv->ip4_routes);
|
||
g_array_unref (priv->ip6_routes);
|
||
|
||
G_OBJECT_CLASS (nm_fake_platform_parent_class)->finalize (object);
|
||
}
|
||
|
||
static void
|
||
nm_fake_platform_class_init (NMFakePlatformClass *klass)
|
||
{
|
||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||
NMPlatformClass *platform_class = NM_PLATFORM_CLASS (klass);
|
||
|
||
g_type_class_add_private (klass, sizeof (NMFakePlatformPrivate));
|
||
|
||
/* virtual methods */
|
||
object_class->finalize = nm_fake_platform_finalize;
|
||
|
||
platform_class->setup = setup;
|
||
|
||
platform_class->sysctl_set = sysctl_set;
|
||
platform_class->sysctl_get = sysctl_get;
|
||
|
||
platform_class->link_get_all = link_get_all;
|
||
platform_class->link_add = link_add;
|
||
platform_class->link_delete = link_delete;
|
||
platform_class->link_get_ifindex = link_get_ifindex;
|
||
platform_class->link_get_name = link_get_name;
|
||
platform_class->link_get_type = link_get_type;
|
||
platform_class->link_get_type_name = link_get_type_name;
|
||
|
||
platform_class->link_set_up = link_set_up;
|
||
platform_class->link_set_down = link_set_down;
|
||
platform_class->link_set_arp = link_set_arp;
|
||
platform_class->link_set_noarp = link_set_noarp;
|
||
platform_class->link_is_up = link_is_up;
|
||
platform_class->link_is_connected = link_is_connected;
|
||
platform_class->link_uses_arp = link_uses_arp;
|
||
|
||
platform_class->link_set_address = link_set_address;
|
||
platform_class->link_get_address = link_get_address;
|
||
platform_class->link_get_mtu = link_get_mtu;
|
||
platform_class->link_set_mtu = link_set_mtu;
|
||
|
||
platform_class->link_get_physical_port_id = link_get_physical_port_id;
|
||
|
||
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
|
||
platform_class->link_supports_vlans = link_supports_vlans;
|
||
|
||
platform_class->link_enslave = link_enslave;
|
||
platform_class->link_release = link_release;
|
||
platform_class->link_get_master = link_get_master;
|
||
platform_class->master_set_option = master_set_option;
|
||
platform_class->master_get_option = master_get_option;
|
||
platform_class->slave_set_option = slave_set_option;
|
||
platform_class->slave_get_option = slave_get_option;
|
||
|
||
platform_class->vlan_add = vlan_add;
|
||
platform_class->vlan_get_info = vlan_get_info;
|
||
platform_class->vlan_set_ingress_map = vlan_set_ingress_map;
|
||
platform_class->vlan_set_egress_map = vlan_set_egress_map;
|
||
|
||
platform_class->infiniband_partition_add = infiniband_partition_add;
|
||
|
||
platform_class->veth_get_properties = veth_get_properties;
|
||
platform_class->tun_get_properties = tun_get_properties;
|
||
platform_class->macvlan_get_properties = macvlan_get_properties;
|
||
platform_class->gre_get_properties = gre_get_properties;
|
||
|
||
platform_class->ip4_address_get_all = ip4_address_get_all;
|
||
platform_class->ip6_address_get_all = ip6_address_get_all;
|
||
platform_class->ip4_address_add = ip4_address_add;
|
||
platform_class->ip6_address_add = ip6_address_add;
|
||
platform_class->ip4_address_delete = ip4_address_delete;
|
||
platform_class->ip6_address_delete = ip6_address_delete;
|
||
platform_class->ip4_address_exists = ip4_address_exists;
|
||
platform_class->ip6_address_exists = ip6_address_exists;
|
||
|
||
platform_class->ip4_route_get_all = ip4_route_get_all;
|
||
platform_class->ip6_route_get_all = ip6_route_get_all;
|
||
platform_class->ip4_route_add = ip4_route_add;
|
||
platform_class->ip6_route_add = ip6_route_add;
|
||
platform_class->ip4_route_delete = ip4_route_delete;
|
||
platform_class->ip6_route_delete = ip6_route_delete;
|
||
platform_class->ip4_route_exists = ip4_route_exists;
|
||
platform_class->ip6_route_exists = ip6_route_exists;
|
||
}
|