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

1086 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* -*- 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) 20122013 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;
} 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;
}
static gboolean
link_add (NMPlatform *platform, const char *name, NMLinkType type)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMFakePlatformLink device;
link_init (&device, priv->links->len, type, name);
g_array_append_val (priv->links, device);
if (device.link.ifindex)
g_signal_emit_by_name (platform, NM_PLATFORM_LINK_ADDED, device.link.ifindex, &device.link);
return TRUE;
}
static gboolean
link_delete (NMPlatform *platform, int ifindex)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
NMPlatformLink deleted_device;
if (!device || !device->link.ifindex)
return FALSE;
memcpy (&deleted_device, &device->link, sizeof (deleted_device));
memset (&device->link, 0, sizeof (device->link));
g_signal_emit_by_name (platform, NM_PLATFORM_LINK_REMOVED, ifindex, &deleted_device);
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, "link-changed", device->link.ifindex, &device->link);
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 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 gboolean
ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP4Address address;
memset (&address, 0, sizeof (address));
address.ifindex = ifindex;
address.address = addr;
address.plen = plen;
g_array_append_val (priv->ip4_addresses, address);
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ADDRESS_ADDED, ifindex, &address);
return TRUE;
}
static gboolean
ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP6Address address;
memset (&address, 0, sizeof (address));
address.ifindex = ifindex;
address.address = addr;
address.plen = plen;
g_array_append_val (priv->ip6_addresses, address);
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ADDRESS_ADDED, ifindex, &address);
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);
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);
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)
{
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)
g_array_append_val (routes, *route);
}
return routes;
}
static GArray *
ip6_route_get_all (NMPlatform *platform, int ifindex)
{
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)
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;
memset (&route, 0, sizeof (route));
route.ifindex = ifindex;
route.network = network;
route.plen = plen;
route.gateway = gateway;
route.metric = metric;
route.mss = mss;
g_array_append_val (priv->ip4_routes, route);
g_signal_emit_by_name (platform, NM_PLATFORM_IP4_ROUTE_ADDED, ifindex, &route);
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;
memset (&route, 0, sizeof (route));
route.ifindex = ifindex;
route.network = network;
route.plen = plen;
route.gateway = gateway;
route.metric = metric;
route.mss = mss;
g_array_append_val (priv->ip6_routes, route);
g_signal_emit_by_name (platform, NM_PLATFORM_IP6_ROUTE_ADDED, ifindex, &route);
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);
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);
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;
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_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;
}