summaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/Makefile.in6
-rw-r--r--src/platform/nm-fake-platform.c108
-rw-r--r--src/platform/nm-fake-platform.h6
-rw-r--r--src/platform/nm-linux-platform.c623
-rw-r--r--src/platform/nm-linux-platform.h6
-rw-r--r--src/platform/nm-platform.c293
-rw-r--r--src/platform/nm-platform.h201
-rw-r--r--src/platform/tests/Makefile.am9
-rw-r--r--src/platform/tests/Makefile.in16
-rw-r--r--src/platform/tests/dump.c6
-rw-r--r--src/platform/tests/monitor.c2
-rw-r--r--src/platform/tests/platform.c28
-rw-r--r--src/platform/tests/test-address.c8
-rw-r--r--src/platform/tests/test-cleanup.c24
-rw-r--r--src/platform/tests/test-common.c2
-rw-r--r--src/platform/tests/test-link.c13
-rw-r--r--src/platform/tests/test-route.c48
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.c59
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.h8
-rw-r--r--src/platform/wifi/wifi-utils-private.h12
-rw-r--r--src/platform/wifi/wifi-utils-wext.c19
-rw-r--r--src/platform/wifi/wifi-utils-wext.h6
-rw-r--r--src/platform/wifi/wifi-utils.c23
-rw-r--r--src/platform/wifi/wifi-utils.h16
24 files changed, 1017 insertions, 525 deletions
diff --git a/src/platform/Makefile.in b/src/platform/Makefile.in
index 9358879f3..d4c8ade7f 100644
--- a/src/platform/Makefile.in
+++ b/src/platform/Makefile.in
@@ -189,6 +189,8 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
@@ -312,6 +314,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
NEWT_LIBS = @NEWT_LIBS@
NM = @NM@
NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
NM_MICRO_VERSION = @NM_MICRO_VERSION@
NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -331,6 +334,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -357,7 +361,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
USE_NLS = @USE_NLS@
UUID_CFLAGS = @UUID_CFLAGS@
UUID_LIBS = @UUID_LIBS@
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 46272217d..a5eb7d4ed 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -18,11 +18,14 @@
* Copyright (C) 2012–2013 Red Hat, Inc.
*/
+#include "config.h"
+
#include <errno.h>
#include <unistd.h>
#include <netinet/icmp6.h>
#include <netinet/in.h>
+#include "gsystem-local-alloc.h"
#include "NetworkManagerUtils.h"
#include "nm-fake-platform.h"
#include "nm-logging.h"
@@ -162,12 +165,12 @@ link_get_all (NMPlatform *platform)
}
static gboolean
-_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link)
+_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
if (device)
- *link = device->link;
+ *l = device->link;
return !!device;
}
@@ -543,7 +546,7 @@ link_get_master (NMPlatform *platform, int slave)
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);
+ gs_free char *path = g_strdup_printf ("master:%d:%s", master, option);
return sysctl_set (platform, path, value);
}
@@ -551,7 +554,7 @@ master_set_option (NMPlatform *platform, int master, const char *option, const c
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);
+ gs_free char *path = g_strdup_printf ("master:%d:%s", master, option);
return sysctl_get (platform, path);
}
@@ -559,7 +562,7 @@ master_get_option (NMPlatform *platform, int master, const char *option)
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);
+ gs_free char *path = g_strdup_printf ("slave:%d:%s", slave, option);
return sysctl_set (platform, path, value);
}
@@ -567,7 +570,7 @@ slave_set_option (NMPlatform *platform, int slave, const char *option, const cha
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);
+ gs_free char *path = g_strdup_printf ("slave:%d:%s", slave, option);
return sysctl_get (platform, path);
}
@@ -688,7 +691,7 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti
}
static gboolean
-wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid)
+wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid)
{
return FALSE;
}
@@ -754,7 +757,7 @@ mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel)
}
static gboolean
-mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid)
+mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len)
{
return FALSE;
}
@@ -827,7 +830,7 @@ ip4_address_add (NMPlatform *platform, int ifindex,
int i;
memset (&address, 0, sizeof (address));
- address.source = NM_PLATFORM_SOURCE_KERNEL;
+ address.source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = peer_addr;
@@ -869,7 +872,7 @@ ip6_address_add (NMPlatform *platform, int ifindex,
int i;
memset (&address, 0, sizeof (address));
- address.source = NM_PLATFORM_SOURCE_KERNEL;
+ address.source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = peer_addr;
@@ -901,7 +904,7 @@ ip6_address_add (NMPlatform *platform, int ifindex,
}
static gboolean
-ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
+ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -909,7 +912,8 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
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) {
+ if (address->ifindex == ifindex && address->plen == plen && address->address == addr &&
+ (!peer_address || address->peer_address == peer_address)) {
NMPlatformIP4Address deleted_address;
memcpy (&deleted_address, address, sizeof (deleted_address));
@@ -978,31 +982,37 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int
return FALSE;
}
+static gboolean
+ip4_check_reinstall_device_route (NMPlatform *platform, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
+{
+ return FALSE;
+}
+
/******************************************************************/
static GArray *
-ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
+ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP4Route *route;
- int count = 0, i;
+ guint 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++;
- }
+ g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL);
- routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP4Route), count);
+ routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP4Route));
/* 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);
+ if (route && (!ifindex || route->ifindex == ifindex)) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
+ if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ g_array_append_val (routes, *route);
+ } else {
+ if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ g_array_append_val (routes, *route);
+ }
}
}
@@ -1010,28 +1020,28 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
}
static GArray *
-ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
+ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP6Route *route;
- int count = 0, i;
+ guint 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++;
- }
+ g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL);
- routes = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformIP6Route), count);
+ routes = g_array_new (TRUE, TRUE, sizeof (NMPlatformIP6Route));
/* 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);
+ if (route && (!ifindex || route->ifindex == ifindex)) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
+ if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ g_array_append_val (routes, *route);
+ } else {
+ if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ g_array_append_val (routes, *route);
+ }
}
}
@@ -1039,16 +1049,16 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
}
static gboolean
-ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
+ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
- int metric, int mss)
+ guint32 pref_src, guint32 metric, guint32 mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP4Route route;
guint i;
memset (&route, 0, sizeof (route));
- route.source = NM_PLATFORM_SOURCE_KERNEL;
+ route.source = NM_IP_CONFIG_SOURCE_KERNEL;
route.ifindex = ifindex;
route.source = source;
route.network = network;
@@ -1079,16 +1089,16 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
}
static gboolean
-ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
+ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
- int metric, int mss)
+ guint32 metric, guint32 mss)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP6Route route;
guint i;
memset (&route, 0, sizeof (route));
- route.source = NM_PLATFORM_SOURCE_KERNEL;
+ route.source = NM_IP_CONFIG_SOURCE_KERNEL;
route.ifindex = ifindex;
route.source = source;
route.network = network;
@@ -1119,7 +1129,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
}
static NMPlatformIP4Route *
-ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
+ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1138,7 +1148,7 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, int plen, i
}
static NMPlatformIP6Route *
-ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
+ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
int i;
@@ -1157,7 +1167,7 @@ ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, int p
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
+ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
{
NMPlatformIP4Route *route = ip4_route_get (platform, ifindex, network, plen, metric);
NMPlatformIP4Route deleted_route;
@@ -1172,7 +1182,7 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
}
static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
+ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
NMPlatformIP6Route *route = ip6_route_get (platform, ifindex, network, plen, metric);
NMPlatformIP6Route deleted_route;
@@ -1187,13 +1197,13 @@ ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, in
}
static gboolean
-ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
+ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 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)
+ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
return !!ip6_route_get (platform, ifindex, network, plen, metric);
}
@@ -1341,6 +1351,8 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->ip4_address_exists = ip4_address_exists;
platform_class->ip6_address_exists = ip6_address_exists;
+ platform_class->ip4_check_reinstall_device_route = ip4_check_reinstall_device_route;
+
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;
diff --git a/src/platform/nm-fake-platform.h b/src/platform/nm-fake-platform.h
index c9fa42eb6..53a2ff1a6 100644
--- a/src/platform/nm-fake-platform.h
+++ b/src/platform/nm-fake-platform.h
@@ -18,8 +18,8 @@
* Copyright (C) 2012 Red Hat, Inc.
*/
-#ifndef NM_FAKE_PLATFORM_H
-#define NM_FAKE_PLATFORM_H
+#ifndef __NETWORKMANAGER_FAKE_PLATFORM_H__
+#define __NETWORKMANAGER_FAKE_PLATFORM_H__
#include "nm-platform.h"
@@ -46,4 +46,4 @@ GType nm_fake_platform_get_type (void);
void nm_fake_platform_setup (void);
-#endif /* NM_FAKE_PLATFORM_H */
+#endif /* __NETWORKMANAGER_FAKE_PLATFORM_H__ */
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f73ff3207..5d1522ce9 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -17,7 +17,7 @@
*
* Copyright (C) 2012-2013 Red Hat, Inc.
*/
-#include <config.h>
+#include "config.h"
#include <errno.h>
#include <unistd.h>
@@ -44,6 +44,17 @@
#include <netlink/route/route.h>
#include <gudev/gudev.h>
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
+#include <netlink/route/link/inet6.h>
+#if HAVE_KERNEL_INET6_ADDR_GEN_MODE
+#include <linux/if_link.h>
+#else
+#define IN6_ADDR_GEN_MODE_EUI64 0
+#define IN6_ADDR_GEN_MODE_NONE 1
+#endif
+#endif
+
+#include "gsystem-local-alloc.h"
#include "NetworkManagerUtils.h"
#include "nm-linux-platform.h"
#include "NetworkManagerUtils.h"
@@ -83,6 +94,7 @@ typedef struct {
GHashTable *wifi_data;
int support_kernel_extended_ifa_flags;
+ int support_user_ipv6ll;
} NMLinuxPlatformPrivate;
#define NM_LINUX_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LINUX_PLATFORM, NMLinuxPlatformPrivate))
@@ -90,6 +102,8 @@ typedef struct {
G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM)
static const char *to_string_object (NMPlatform *platform, struct nl_object *obj);
+static gboolean _address_match (struct rtnl_addr *addr, int family, int ifindex);
+static gboolean _route_match (struct rtnl_route *rtnlroute, int family, int ifindex, gboolean include_proto_kernel);
void
nm_linux_platform_setup (void)
@@ -106,7 +120,7 @@ _nl_f_nl_has_capability (int capability)
}
static struct libnl_vtable *
-_nl_get_vtable ()
+_nl_get_vtable (void)
{
static struct libnl_vtable vtable;
@@ -268,7 +282,7 @@ _nm_rtnl_addr_alloc (int ifindex)
}
static struct rtnl_route *
-_nm_rtnl_route_alloc ()
+_nm_rtnl_route_alloc (void)
{
struct rtnl_route *rtnlroute = rtnl_route_alloc ();
@@ -278,7 +292,7 @@ _nm_rtnl_route_alloc ()
}
static struct rtnl_nexthop *
-_nm_rtnl_route_nh_alloc ()
+_nm_rtnl_route_nh_alloc (void)
{
struct rtnl_nexthop *nexthop;
@@ -596,8 +610,8 @@ ethtool_get (const char *name, gpointer edata)
static int
ethtool_get_stringset_index (const char *ifname, int stringset_id, const char *string)
{
- auto_g_free struct ethtool_sset_info *info = NULL;
- auto_g_free struct ethtool_gstrings *strings = NULL;
+ gs_free struct ethtool_sset_info *info = NULL;
+ gs_free struct ethtool_gstrings *strings = NULL;
guint32 len, i;
info = g_malloc0 (sizeof (*info) + sizeof (guint32));
@@ -667,6 +681,23 @@ check_support_kernel_extended_ifa_flags (NMPlatform *platform)
return priv->support_kernel_extended_ifa_flags > 0;
}
+static gboolean
+check_support_user_ipv6ll (NMPlatform *platform)
+{
+ NMLinuxPlatformPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE);
+
+ priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+
+ if (priv->support_user_ipv6ll == 0) {
+ nm_log_warn (LOGD_PLATFORM, "Unable to detect kernel support for IFLA_INET6_ADDR_GEN_MODE. Assume no kernel support.");
+ priv->support_user_ipv6ll = -1;
+ }
+
+ return priv->support_user_ipv6ll > 0;
+}
+
/* Object type specific utilities */
@@ -735,7 +766,7 @@ link_type_from_udev (NMPlatform *platform, int ifindex, const char *ifname, int
prop = g_udev_device_get_property (udev_device, "DEVTYPE");
sysfs_path = g_udev_device_get_sysfs_path (udev_device);
- if (g_strcmp0 (prop, "wlan") == 0 || wifi_utils_is_wifi (ifname, sysfs_path))
+ if (wifi_utils_is_wifi (ifname, sysfs_path, prop))
return_type (NM_LINK_TYPE_WIFI, "wifi");
else if (g_strcmp0 (prop, "wwan") == 0)
return_type (NM_LINK_TYPE_WWAN_ETHERNET, "wwan");
@@ -1176,7 +1207,7 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
memset (address, 0, sizeof (*address));
- address->source = NM_PLATFORM_SOURCE_KERNEL;
+ address->source = NM_IP_CONFIG_SOURCE_KERNEL;
address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
address->plen = rtnl_addr_get_prefixlen (rtnladdr);
_init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr);
@@ -1208,7 +1239,7 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
memset (address, 0, sizeof (*address));
- address->source = NM_PLATFORM_SOURCE_KERNEL;
+ address->source = NM_IP_CONFIG_SOURCE_KERNEL;
address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
address->plen = rtnl_addr_get_prefixlen (rtnladdr);
_init_ip_address_lifetime ((NMPlatformIPAddress *) address, rtnladdr);
@@ -1230,16 +1261,16 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
}
static guint
-source_to_rtprot (NMPlatformSource source)
+source_to_rtprot (NMIPConfigSource source)
{
switch (source) {
- case NM_PLATFORM_SOURCE_UNKNOWN:
+ case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
- case NM_PLATFORM_SOURCE_KERNEL:
+ case NM_IP_CONFIG_SOURCE_KERNEL:
return RTPROT_KERNEL;
- case NM_PLATFORM_SOURCE_DHCP:
+ case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
- case NM_PLATFORM_SOURCE_RDISC:
+ case NM_IP_CONFIG_SOURCE_RDISC:
return RTPROT_RA;
default:
@@ -1247,26 +1278,36 @@ source_to_rtprot (NMPlatformSource source)
}
}
-static NMPlatformSource
+static NMIPConfigSource
rtprot_to_source (guint rtprot)
{
switch (rtprot) {
case RTPROT_UNSPEC:
- return NM_PLATFORM_SOURCE_UNKNOWN;
+ return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_REDIRECT:
case RTPROT_KERNEL:
- return NM_PLATFORM_SOURCE_KERNEL;
+ return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
- return NM_PLATFORM_SOURCE_RDISC;
+ return NM_IP_CONFIG_SOURCE_RDISC;
case RTPROT_DHCP:
- return NM_PLATFORM_SOURCE_DHCP;
+ return NM_IP_CONFIG_SOURCE_DHCP;
default:
- return NM_PLATFORM_SOURCE_USER;
+ return NM_IP_CONFIG_SOURCE_USER;
}
}
static gboolean
+_rtnl_route_is_default (const struct rtnl_route *rtnlroute)
+{
+ struct nl_addr *dst;
+
+ return rtnlroute
+ && (dst = rtnl_route_get_dst ((struct rtnl_route *) rtnlroute))
+ && nl_addr_get_prefixlen (dst) == 0;
+}
+
+static gboolean
init_ip4_route (NMPlatformIP4Route *route, struct rtnl_route *rtnlroute)
{
struct nl_addr *dst, *gw;
@@ -1527,8 +1568,20 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
switch (object_type) {
case OBJECT_TYPE_LINK:
{
- NMPlatformLink device;
struct rtnl_link *rtnl_link = (struct rtnl_link *) object;
+ NMPlatformLink device;
+
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
+ /* If we ever see a link with valid IPv6 link-local address
+ * generation modes, the kernel supports it.
+ */
+ if (priv->support_user_ipv6ll == 0) {
+ uint8_t mode;
+
+ if (rtnl_link_inet6_get_addr_gen_mode (rtnl_link, &mode) == 0)
+ priv->support_user_ipv6ll = 1;
+ }
+#endif
if (!init_link (platform, &device, rtnl_link))
return;
@@ -1576,20 +1629,25 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
{
NMPlatformIP4Address address;
- if (!init_ip4_address (&address, (struct rtnl_addr *) object))
- return;
-
/* Address deletion is sometimes accompanied by route deletion. We need to
* check all routes belonging to the same interface.
*/
switch (change_type) {
case NM_PLATFORM_SIGNAL_REMOVED:
- check_cache_items (platform, priv->route_cache, address.ifindex);
+ check_cache_items (platform,
+ priv->route_cache,
+ rtnl_addr_get_ifindex ((struct rtnl_addr *) object));
break;
default:
break;
}
+ if (!_address_match ((struct rtnl_addr *) object, AF_INET, 0)) {
+ nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP4 address %s", to_string_ip4_address ((struct rtnl_addr *) object));
+ return;
+ }
+ if (!init_ip4_address (&address, (struct rtnl_addr *) object))
+ return;
g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason);
}
return;
@@ -1597,6 +1655,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
{
NMPlatformIP6Address address;
+ if (!_address_match ((struct rtnl_addr *) object, AF_INET6, 0)) {
+ nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP6 address %s", to_string_ip6_address ((struct rtnl_addr *) object));
+ return;
+ }
if (!init_ip6_address (&address, (struct rtnl_addr *) object))
return;
g_signal_emit_by_name (platform, sig, address.ifindex, &address, change_type, reason);
@@ -1606,6 +1668,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
{
NMPlatformIP4Route route;
+ if (!_route_match ((struct rtnl_route *) object, AF_INET, 0, FALSE)) {
+ nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP4 route %s", to_string_ip4_route ((struct rtnl_route *) object));
+ return;
+ }
if (init_ip4_route (&route, (struct rtnl_route *) object))
g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason);
}
@@ -1614,6 +1680,10 @@ announce_object (NMPlatform *platform, const struct nl_object *object, NMPlatfor
{
NMPlatformIP6Route route;
+ if (!_route_match ((struct rtnl_route *) object, AF_INET6, 0, FALSE)) {
+ nm_log_dbg (LOGD_PLATFORM, "skip announce unmatching IP6 route %s", to_string_ip6_route ((struct rtnl_route *) object));
+ return;
+ }
if (init_ip6_route (&route, (struct rtnl_route *) object))
g_signal_emit_by_name (platform, sig, route.ifindex, &route, change_type, reason);
}
@@ -1721,15 +1791,14 @@ add_object (NMPlatform *platform, struct nl_object *obj)
/* Decreases the reference count if @obj for convenience */
static gboolean
-delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_object)
+delete_object (NMPlatform *platform, struct nl_object *object, gboolean do_refresh_object)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
- auto_nl_object struct nl_object *obj_cleanup = obj;
- struct nl_object *object = obj;
int object_type;
int nle;
+ gboolean result = FALSE;
- object_type = object_type_from_nl_object (obj);
+ object_type = object_type_from_nl_object (object);
g_return_val_if_fail (object_type != OBJECT_TYPE_UNKNOWN, FALSE);
switch (object_type) {
@@ -1772,14 +1841,18 @@ delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_
goto DEFAULT;
DEFAULT:
default:
- error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, obj), nl_geterror (nle), nle);
- return FALSE;
+ error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, object), nl_geterror (nle), nle);
+ goto out;
}
if (do_refresh_object)
refresh_object (platform, object, TRUE, NM_PLATFORM_REASON_INTERNAL);
- return TRUE;
+ result = TRUE;
+
+out:
+ nl_object_put (object);
+ return result;
}
static void
@@ -1807,6 +1880,33 @@ _rtnl_addr_timestamps_equal_fuzzy (guint32 ts1, guint32 ts2)
return diff <= 2;
}
+static gboolean
+nm_nl_object_diff (ObjectType type, struct nl_object *_a, struct nl_object *_b)
+{
+ if (nl_object_diff (_a, _b)) {
+ /* libnl thinks objects are different*/
+ return TRUE;
+ }
+
+ if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) {
+ struct rtnl_addr *a = (struct rtnl_addr *) _a;
+ struct rtnl_addr *b = (struct rtnl_addr *) _b;
+
+ /* libnl nl_object_diff() ignores differences in timestamp. Let's care about
+ * them (if they are large enough).
+ *
+ * Note that these valid and preferred timestamps are absolute, after
+ * _rtnl_addr_hack_lifetimes_rel_to_abs(). */
+ if ( !_rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (a),
+ rtnl_addr_get_preferred_lifetime (b))
+ || !_rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (a),
+ rtnl_addr_get_valid_lifetime (b)))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* This function does all the magic to avoid race conditions caused
* by concurrent usage of synchronous commands and an asynchronous cache. This
* might be a nice future addition to libnl but it requires to do all operations
@@ -1912,24 +2012,9 @@ event_notification (struct nl_msg *msg, gpointer user_data)
* This also catches notifications for internal addition or change, unless
* another action occured very soon after it.
*/
- if (!nl_object_diff (kernel_object, cached_object)) {
- if (type == OBJECT_TYPE_IP4_ADDRESS || type == OBJECT_TYPE_IP6_ADDRESS) {
- struct rtnl_addr *c = (struct rtnl_addr *) cached_object;
- struct rtnl_addr *k = (struct rtnl_addr *) kernel_object;
-
- /* libnl nl_object_diff() ignores differences in timestamp. Let's care about
- * them (if they are large enough).
- *
- * Note that these valid and preferred timestamps are absolute, after
- * _rtnl_addr_hack_lifetimes_rel_to_abs(). */
- if ( _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_preferred_lifetime (c),
- rtnl_addr_get_preferred_lifetime (k))
- && _rtnl_addr_timestamps_equal_fuzzy (rtnl_addr_get_valid_lifetime (c),
- rtnl_addr_get_valid_lifetime (k)))
- return NL_OK;
- } else
- return NL_OK;
- }
+ if (!nm_nl_object_diff (type, kernel_object, cached_object))
+ return NL_OK;
+
/* Handle external change */
nl_cache_remove (cached_object);
nle = nl_cache_add (cache, kernel_object);
@@ -2133,7 +2218,7 @@ link_get_all (NMPlatform *platform)
}
static gboolean
-_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link)
+_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *l)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
auto_nl_object struct rtnl_link *rtnllink = NULL;
@@ -2141,7 +2226,7 @@ _nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link)
rtnllink = rtnl_link_get (priv->link_cache, ifindex);
if (rtnllink) {
if (link_is_announceable (platform, rtnllink)) {
- if (init_link (platform, link, rtnllink))
+ if (init_link (platform, l, rtnllink))
return TRUE;
}
}
@@ -2166,7 +2251,7 @@ static gboolean
link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len)
{
int r;
- struct nl_object *link;
+ struct nl_object *l;
if (type == NM_LINK_TYPE_BOND) {
/* When the kernel loads the bond module, either via explicit modprobe
@@ -2184,15 +2269,15 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *a
debug ("link: add link '%s' of type '%s' (%d)",
name, type_to_string (type), (int) type);
- link = build_rtnl_link (0, name, type);
+ l = build_rtnl_link (0, name, type);
g_assert ( (address != NULL) ^ (address_len == 0) );
if (address) {
auto_nl_addr struct nl_addr *nladdr = _nm_nl_addr_build (AF_LLC, address, address_len);
- rtnl_link_set_addr ((struct rtnl_link *) link, nladdr);
+ rtnl_link_set_addr ((struct rtnl_link *) l, nladdr);
}
- return add_object (platform, link);
+ return add_object (platform, l);
}
static struct rtnl_link *
@@ -2384,6 +2469,46 @@ link_set_noarp (NMPlatform *platform, int ifindex)
}
static gboolean
+link_get_user_ipv6ll_enabled (NMPlatform *platform, int ifindex)
+{
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+
+ if (priv->support_user_ipv6ll > 0) {
+ auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
+ uint8_t mode = 0;
+
+ if (rtnllink) {
+ if (rtnl_link_inet6_get_addr_gen_mode (rtnllink, &mode) != 0) {
+ /* Default to "disabled" on error */
+ return FALSE;
+ }
+ return mode == IN6_ADDR_GEN_MODE_NONE;
+ }
+ }
+#endif
+ return FALSE;
+}
+
+static gboolean
+link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enabled)
+{
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
+ if (check_support_user_ipv6ll (platform)) {
+ auto_nl_object struct rtnl_link *change = _nm_rtnl_link_alloc (ifindex, NULL);
+ guint8 mode = enabled ? IN6_ADDR_GEN_MODE_NONE : IN6_ADDR_GEN_MODE_EUI64;
+ char buf[32];
+
+ rtnl_link_inet6_set_addr_gen_mode (change, mode);
+ debug ("link: change %d: set IPv6 address generation mode to %s",
+ ifindex, rtnl_link_inet6_addrgenmode2str (mode, buf, sizeof (buf)));
+ return link_change (platform, ifindex, change);
+ }
+#endif
+ return FALSE;
+}
+
+static gboolean
supports_ethtool_carrier_detect (const char *ifname)
{
struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK };
@@ -2455,7 +2580,7 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
{
auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
const char *name = nm_platform_link_get_name (ifindex);
- auto_g_free struct ethtool_gfeatures *features = NULL;
+ gs_free struct ethtool_gfeatures *features = NULL;
int idx, block, bit, size;
/* Only ARPHRD_ETHER links can possibly support VLANs. */
@@ -2494,7 +2619,7 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size
rtnl_link_set_addr (change, nladdr);
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
- char *mac = nm_utils_hwaddr_ntoa_len (address, length);
+ char *mac = nm_utils_hwaddr_ntoa (address, length);
debug ("link: change %d: address %s (%lu bytes)", ifindex, mac, (unsigned long) length);
g_free (mac);
@@ -2508,13 +2633,23 @@ link_get_address (NMPlatform *platform, int ifindex, size_t *length)
{
auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
struct nl_addr *nladdr;
-
- nladdr = rtnllink ? rtnl_link_get_addr (rtnllink) : NULL;
+ size_t l = 0;
+ gconstpointer a = NULL;
+
+ if (rtnllink &&
+ (nladdr = rtnl_link_get_addr (rtnllink))) {
+ l = nl_addr_get_len (nladdr);
+ if (l > NM_UTILS_HWADDR_LEN_MAX) {
+ if (length)
+ *length = 0;
+ g_return_val_if_reached (NULL);
+ } else if (l > 0)
+ a = nl_addr_get_binary_addr (nladdr);
+ }
if (length)
- *length = nladdr ? nl_addr_get_len (nladdr) : 0;
-
- return nladdr ? nl_addr_get_binary_addr (nladdr) : NULL;
+ *length = l;
+ return a;
}
static gboolean
@@ -2667,7 +2802,7 @@ link_option_path (int master, const char *category, const char *option)
static gboolean
link_set_option (int master, const char *category, const char *option, const char *value)
{
- auto_g_free char *path = link_option_path (master, category, option);
+ gs_free char *path = link_option_path (master, category, option);
return path && nm_platform_sysctl_set (path, value);
}
@@ -2675,7 +2810,7 @@ link_set_option (int master, const char *category, const char *option, const cha
static char *
link_get_option (int master, const char *category, const char *option)
{
- auto_g_free char *path = link_option_path (master, category, option);
+ gs_free char *path = link_option_path (master, category, option);
return path ? nm_platform_sysctl_get (path) : NULL;
}
@@ -2754,7 +2889,7 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key)
g_free (path);
if (success) {
- auto_g_free char *ifname = g_strdup_printf ("%s.%04x", parent_name, p_key);
+ gs_free char *ifname = g_strdup_printf ("%s.%04x", parent_name, p_key);
auto_nl_object struct rtnl_link *rtnllink = _nm_rtnl_link_alloc (0, ifname);
success = refresh_object (platform, (struct nl_object *) rtnllink, FALSE, NM_PLATFORM_REASON_INTERNAL);
@@ -2767,7 +2902,7 @@ static gboolean
veth_get_properties (NMPlatform *platform, int ifindex, NMPlatformVethProperties *props)
{
const char *ifname;
- auto_g_free struct ethtool_stats *stats = NULL;
+ gs_free struct ethtool_stats *stats = NULL;
int peer_ifindex_stat;
ifname = nm_platform_link_get_name (ifindex);
@@ -2841,7 +2976,7 @@ tun_get_properties (NMPlatform *platform, int ifindex, NMPlatformTunProperties *
#ifndef IFF_MULTI_QUEUE
const int IFF_MULTI_QUEUE = 0x0100;
#endif
- props->mode = ((flags & TUN_TYPE_MASK) == TUN_TUN_DEV) ? "tun" : "tap";
+ props->mode = ((flags & (IFF_TUN | IFF_TAP)) == IFF_TUN) ? "tun" : "tap";
props->no_pi = !!(flags & IFF_NO_PI);
props->vnet_hdr = !!(flags & IFF_VNET_HDR);
props->multi_queue = !!(flags & IFF_MULTI_QUEUE);
@@ -2947,6 +3082,13 @@ macvlan_get_properties (NMPlatform *platform, int ifindex, NMPlatformMacvlanProp
#undef IFLA_VXLAN_MAX
#define IFLA_VXLAN_MAX IFLA_VXLAN_LOCAL6
+/* older kernel header might not contain 'struct ifla_vxlan_port_range'.
+ * Redefine it. */
+struct nm_ifla_vxlan_port_range {
+ guint16 low;
+ guint16 high;
+};
+
static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_ID] = { .type = NLA_U32 },
[IFLA_VXLAN_GROUP] = { .type = NLA_U32 },
@@ -2962,7 +3104,7 @@ static const struct nla_policy vxlan_info_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_AGEING] = { .type = NLA_U32 },
[IFLA_VXLAN_LIMIT] = { .type = NLA_U32 },
[IFLA_VXLAN_PORT_RANGE] = { .type = NLA_UNSPEC,
- .minlen = sizeof (struct ifla_vxlan_port_range) },
+ .minlen = sizeof (struct nm_ifla_vxlan_port_range) },
[IFLA_VXLAN_PROXY] = { .type = NLA_U8 },
[IFLA_VXLAN_RSC] = { .type = NLA_U8 },
[IFLA_VXLAN_L2MISS] = { .type = NLA_U8 },
@@ -2975,7 +3117,7 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
{
NMPlatformVxlanProperties *props = parser_data;
struct nlattr *tb[IFLA_VXLAN_MAX + 1];
- struct ifla_vxlan_port_range *range;
+ struct nm_ifla_vxlan_port_range *range;
int err;
err = nla_parse_nested (tb, IFLA_VXLAN_MAX, info_data,
@@ -2985,8 +3127,10 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
memset (props, 0, sizeof (*props));
- props->parent_ifindex = tb[IFLA_VXLAN_LINK] ? nla_get_u32 (tb[IFLA_VXLAN_LINK]) : 0;
- props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]);
+ if (tb[IFLA_VXLAN_LINK])
+ props->parent_ifindex = nla_get_u32 (tb[IFLA_VXLAN_LINK]);
+ if (tb[IFLA_VXLAN_ID])
+ props->id = nla_get_u32 (tb[IFLA_VXLAN_ID]);
if (tb[IFLA_VXLAN_GROUP])
props->group = nla_get_u32 (tb[IFLA_VXLAN_GROUP]);
if (tb[IFLA_VXLAN_LOCAL])
@@ -2996,21 +3140,34 @@ vxlan_info_data_parser (struct nlattr *info_data, gpointer parser_data)
if (tb[IFLA_VXLAN_LOCAL6])
memcpy (&props->local6, nla_data (tb[IFLA_VXLAN_LOCAL6]), sizeof (props->local6));
- props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
- props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]);
- props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]);
- props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]);
-
- props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]);
- range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
- props->src_port_min = range->low;
- props->src_port_max = range->high;
+ if (tb[IFLA_VXLAN_AGEING])
+ props->ageing = nla_get_u32 (tb[IFLA_VXLAN_AGEING]);
+ if (tb[IFLA_VXLAN_LIMIT])
+ props->limit = nla_get_u32 (tb[IFLA_VXLAN_LIMIT]);
+ if (tb[IFLA_VXLAN_TOS])
+ props->tos = nla_get_u8 (tb[IFLA_VXLAN_TOS]);
+ if (tb[IFLA_VXLAN_TTL])
+ props->ttl = nla_get_u8 (tb[IFLA_VXLAN_TTL]);
+
+ if (tb[IFLA_VXLAN_PORT])
+ props->dst_port = nla_get_u16 (tb[IFLA_VXLAN_PORT]);
+
+ if (tb[IFLA_VXLAN_PORT_RANGE]) {
+ range = nla_data (tb[IFLA_VXLAN_PORT_RANGE]);
+ props->src_port_min = range->low;
+ props->src_port_max = range->high;
+ }
- props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]);
- props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]);
- props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]);
- props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]);
- props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]);
+ if (tb[IFLA_VXLAN_LEARNING])
+ props->learning = !!nla_get_u8 (tb[IFLA_VXLAN_LEARNING]);
+ if (tb[IFLA_VXLAN_PROXY])
+ props->proxy = !!nla_get_u8 (tb[IFLA_VXLAN_PROXY]);
+ if (tb[IFLA_VXLAN_RSC])
+ props->rsc = !!nla_get_u8 (tb[IFLA_VXLAN_RSC]);
+ if (tb[IFLA_VXLAN_L2MISS])
+ props->l2miss = !!nla_get_u8 (tb[IFLA_VXLAN_L2MISS]);
+ if (tb[IFLA_VXLAN_L3MISS])
+ props->l3miss = !!nla_get_u8 (tb[IFLA_VXLAN_L3MISS]);
return 0;
}
@@ -3131,7 +3288,7 @@ wifi_get_capabilities (NMPlatform *platform, int ifindex, NMDeviceWifiCapabiliti
}
static gboolean
-wifi_get_bssid (NMPlatform *platform, int ifindex, struct ether_addr *bssid)
+wifi_get_bssid (NMPlatform *platform, int ifindex, guint8 *bssid)
{
WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex);
@@ -3244,14 +3401,14 @@ mesh_set_channel (NMPlatform *platform, int ifindex, guint32 channel)
}
static gboolean
-mesh_set_ssid (NMPlatform *platform, int ifindex, const GByteArray *ssid)
+mesh_set_ssid (NMPlatform *platform, int ifindex, const guint8 *ssid, gsize len)
{
WifiData *wifi_data = wifi_get_wifi_data (platform, ifindex);
if (!wifi_data)
return FALSE;
- return wifi_utils_set_mesh_ssid (wifi_data, ssid);
+ return wifi_utils_set_mesh_ssid (wifi_data, ssid, len);
}
static gboolean
@@ -3287,7 +3444,7 @@ _address_match (struct rtnl_addr *addr, int family, int ifindex)
g_return_val_if_fail (addr, FALSE);
return rtnl_addr_get_family (addr) == family &&
- rtnl_addr_get_ifindex (addr) == ifindex;
+ (ifindex == 0 || rtnl_addr_get_ifindex (addr) == ifindex);
}
static GArray *
@@ -3455,9 +3612,9 @@ ip6_address_add (NMPlatform *platform,
}
static gboolean
-ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
+ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, in_addr_t peer_address)
{
- return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, NULL, plen, 0, 0, 0, NULL), TRUE);
+ return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, peer_address ? &peer_address : NULL, plen, 0, 0, 0, NULL), TRUE);
}
static gboolean
@@ -3487,10 +3644,53 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int
return ip_address_exists (platform, AF_INET6, ifindex, &addr, plen);
}
+static gboolean
+ip4_check_reinstall_device_route (NMPlatform *platform, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ NMPlatformIP4Address addr_candidate;
+ NMPlatformIP4Route route_candidate;
+ struct nl_object *object;
+ guint32 device_network;
+
+ for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
+ if (_address_match ((struct rtnl_addr *) object, AF_INET, 0)) {
+ if (init_ip4_address (&addr_candidate, (struct rtnl_addr *) object))
+ if ( addr_candidate.plen == address->plen
+ && addr_candidate.address == address->address) {
+ /* If we already have the same address installed on any interface,
+ * we back off.
+ * Perform this check first, as we expect to have significantly less
+ * addresses to search. */
+ return FALSE;
+ }
+ }
+ }
+
+ device_network = nm_utils_ip4_address_clear_host_address (address->address, address->plen);
+
+ for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
+ if (_route_match ((struct rtnl_route *) object, AF_INET, 0, TRUE)) {
+ if (init_ip4_route (&route_candidate, (struct rtnl_route *) object)) {
+ if ( route_candidate.network == device_network
+ && route_candidate.plen == address->plen
+ && ( route_candidate.metric == 0
+ || route_candidate.metric == device_route_metric)) {
+ /* There is already any route with metric 0 or the metric we want to install
+ * for the same subnet. */
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
/******************************************************************/
static gboolean
-_route_match (struct rtnl_route *rtnlroute, int family, int ifindex)
+_route_match (struct rtnl_route *rtnlroute, int family, int ifindex, gboolean include_proto_kernel)
{
struct rtnl_nexthop *nexthop;
@@ -3498,31 +3698,42 @@ _route_match (struct rtnl_route *rtnlroute, int family, int ifindex)
if (rtnl_route_get_type (rtnlroute) != RTN_UNICAST ||
rtnl_route_get_table (rtnlroute) != RT_TABLE_MAIN ||
- rtnl_route_get_protocol (rtnlroute) == RTPROT_KERNEL ||
+ (!include_proto_kernel && rtnl_route_get_protocol (rtnlroute) == RTPROT_KERNEL) ||
rtnl_route_get_family (rtnlroute) != family ||
- rtnl_route_get_nnexthops (rtnlroute) != 1)
+ rtnl_route_get_nnexthops (rtnlroute) != 1 ||
+ rtnl_route_get_flags (rtnlroute) & RTM_F_CLONED)
return FALSE;
+ if (ifindex == 0)
+ return TRUE;
+
nexthop = rtnl_route_nexthop_n (rtnlroute, 0);
return rtnl_route_nh_get_ifindex (nexthop) == ifindex;
}
static GArray *
-ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
+ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP4Route route;
struct nl_object *object;
+ g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL);
+
routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
- if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex)) {
- if (init_ip4_route (&route, (struct rtnl_route *) object)) {
- if (route.plen != 0 || include_default)
- g_array_append_val (routes, route);
+ if (_route_match ((struct rtnl_route *) object, AF_INET, ifindex, FALSE)) {
+ if (_rtnl_route_is_default ((struct rtnl_route *) object)) {
+ if (mode == NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ continue;
+ } else {
+ if (mode == NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ continue;
}
+ if (init_ip4_route (&route, (struct rtnl_route *) object))
+ g_array_append_val (routes, route);
}
}
@@ -3530,21 +3741,28 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
}
static GArray *
-ip6_route_get_all (NMPlatform *platform, int ifindex, gboolean include_default)
+ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP6Route route;
struct nl_object *object;
+ g_return_val_if_fail (NM_IN_SET (mode, NM_PLATFORM_GET_ROUTE_MODE_ALL, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT), NULL);
+
routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
for (object = nl_cache_get_first (priv->route_cache); object; object = nl_cache_get_next (object)) {
- if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex)) {
- if (init_ip6_route (&route, (struct rtnl_route *) object)) {
- if (route.plen != 0 || include_default)
- g_array_append_val (routes, route);
+ if (_route_match ((struct rtnl_route *) object, AF_INET6, ifindex, FALSE)) {
+ if (_rtnl_route_is_default ((struct rtnl_route *) object)) {
+ if (mode == NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ continue;
+ } else {
+ if (mode == NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ continue;
}
+ if (init_ip6_route (&route, (struct rtnl_route *) object))
+ g_array_append_val (routes, route);
}
}
@@ -3570,9 +3788,10 @@ clear_host_address (int family, const void *network, int plen, void *dst)
}
static struct nl_object *
-build_rtnl_route (int family, int ifindex, NMPlatformSource source,
+build_rtnl_route (int family, int ifindex, NMIPConfigSource source,
gconstpointer network, int plen, gconstpointer gateway,
- int metric, int mss)
+ gconstpointer pref_src,
+ guint32 metric, guint32 mss)
{
guint32 network_clean[4];
struct rtnl_route *rtnlroute;
@@ -3581,6 +3800,7 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source,
/* Workaround a libnl bug by using zero destination address length for default routes */
auto_nl_addr struct nl_addr *dst = NULL;
auto_nl_addr struct nl_addr *gw = gateway ? _nm_nl_addr_build (family, gateway, addrlen) : NULL;
+ auto_nl_addr struct nl_addr *pref_src_nl = pref_src ? _nm_nl_addr_build (family, pref_src, addrlen) : NULL;
/* There seem to be problems adding a route with non-zero host identifier.
* Adding IPv6 routes is simply ignored, without error message.
@@ -3602,6 +3822,8 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source,
rtnl_route_nh_set_ifindex (nexthop, ifindex);
if (gw && !nl_addr_iszero (gw))
rtnl_route_nh_set_gateway (nexthop, gw);
+ if (pref_src_nl)
+ rtnl_route_set_pref_src (rtnlroute, pref_src_nl);
rtnl_route_add_nexthop (rtnlroute, nexthop);
if (mss > 0)
@@ -3611,23 +3833,23 @@ build_rtnl_route (int family, int ifindex, NMPlatformSource source,
}
static gboolean
-ip4_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
+ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
- int metric, int mss)
+ guint32 pref_src, guint32 metric, guint32 mss)
{
- return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, metric, mss));
+ return add_object (platform, build_rtnl_route (AF_INET, ifindex, source, &network, plen, &gateway, pref_src ? &pref_src : NULL, metric, mss));
}
static gboolean
-ip6_route_add (NMPlatform *platform, int ifindex, NMPlatformSource source,
+ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
- int metric, int mss)
+ guint32 metric, guint32 mss)
{
- return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, metric, mss));
+ return add_object (platform, build_rtnl_route (AF_INET6, ifindex, source, &network, plen, &gateway, NULL, metric, mss));
}
static struct rtnl_route *
-route_search_cache (struct nl_cache *cache, int family, int ifindex, const void *network, int plen, int metric)
+route_search_cache (struct nl_cache *cache, int family, int ifindex, const void *network, int plen, guint32 metric)
{
guint32 network_clean[4], dst_clean[4];
struct nl_object *object;
@@ -3638,7 +3860,7 @@ route_search_cache (struct nl_cache *cache, int family, int ifindex, const void
struct nl_addr *dst;
struct rtnl_route *rtnlroute = (struct rtnl_route *) object;
- if (!_route_match (rtnlroute, family, ifindex))
+ if (!_route_match (rtnlroute, family, ifindex, FALSE))
continue;
if (metric && metric != rtnl_route_get_priority (rtnlroute))
@@ -3676,11 +3898,11 @@ refresh_route (NMPlatform *platform, int family, int ifindex, const void *networ
}
static gboolean
-ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
+ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
{
in_addr_t gateway = 0;
struct rtnl_route *cached_object;
- struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_PLATFORM_SOURCE_UNKNOWN, &network, plen, &gateway, metric, 0);
+ struct nl_object *route = build_rtnl_route (AF_INET, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN, &network, plen, &gateway, NULL, metric, 0);
uint8_t scope = RT_SCOPE_NOWHERE;
struct nl_cache *cache;
@@ -3736,20 +3958,20 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, int plen
}
static gboolean
-ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
+ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
struct in6_addr gateway = IN6ADDR_ANY_INIT;
- return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_PLATFORM_SOURCE_UNKNOWN ,&network, plen, &gateway, metric, 0), FALSE) &&
+ return delete_object (platform, build_rtnl_route (AF_INET6, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN ,&network, plen, &gateway, NULL, metric, 0), FALSE) &&
refresh_route (platform, AF_INET6, ifindex, &network, plen, metric);
}
static gboolean
-ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, int metric)
+ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network, int plen, guint32 metric)
{
auto_nl_object struct nl_object *object = build_rtnl_route (family, ifindex,
- NM_PLATFORM_SOURCE_UNKNOWN,
- network, plen, NULL, metric, 0);
+ NM_IP_CONFIG_SOURCE_UNKNOWN,
+ network, plen, NULL, NULL, metric, 0);
struct nl_cache *cache = choose_cache (platform, object);
auto_nl_object struct nl_object *cached_object = nl_cache_search (cache, object);
@@ -3759,19 +3981,119 @@ ip_route_exists (NMPlatform *platform, int family, int ifindex, gpointer network
}
static gboolean
-ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, int metric)
+ip4_route_exists (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint32 metric)
{
return ip_route_exists (platform, AF_INET, ifindex, &network, plen, metric);
}
static gboolean
-ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, int metric)
+ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, int plen, guint32 metric)
{
return ip_route_exists (platform, AF_INET6, ifindex, &network, plen, metric);
}
/******************************************************************/
+/* Initialize the link cache while ensuring all links are of AF_UNSPEC,
+ * family (even though the kernel might set AF_BRIDGE for bridges).
+ * See also: _nl_link_family_unset() */
+static void
+init_link_cache (NMPlatform *platform)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ struct nl_object *object = NULL;
+
+ rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache);
+
+ do {
+ for (object = nl_cache_get_first (priv->link_cache); object; object = nl_cache_get_next (object)) {
+ if (rtnl_link_get_family ((struct rtnl_link *)object) != AF_UNSPEC)
+ break;
+ }
+
+ if (object) {
+ /* A non-AF_UNSPEC object encoutnered */
+ struct nl_object *existing;
+
+ nl_object_get (object);
+ nl_cache_remove (object);
+ rtnl_link_set_family ((struct rtnl_link *)object, AF_UNSPEC);
+ existing = nl_cache_search (priv->link_cache, object);
+ if (existing)
+ nl_object_put (existing);
+ else
+ nl_cache_add (priv->link_cache, object);
+ nl_object_put (object);
+ }
+ } while (object);
+}
+
+/* Calls announce_object with appropriate arguments for all objects
+ * which are not coherent between old and new caches and deallocates
+ * the old cache. */
+static void
+cache_announce_changes (NMPlatform *platform, struct nl_cache *new, struct nl_cache *old)
+{
+ struct nl_object *object;
+
+ if (!old)
+ return;
+
+ for (object = nl_cache_get_first (new); object; object = nl_cache_get_next (object)) {
+ struct nl_object *cached_object = nm_nl_cache_search (old, object);
+
+ if (cached_object) {
+ ObjectType type = object_type_from_nl_object (object);
+ if (nm_nl_object_diff (type, object, cached_object))
+ announce_object (platform, object, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_REASON_EXTERNAL);
+ nl_object_put (cached_object);
+ } else
+ announce_object (platform, object, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL);
+ }
+ for (object = nl_cache_get_first (old); object; object = nl_cache_get_next (object)) {
+ struct nl_object *cached_object = nm_nl_cache_search (new, object);
+ if (cached_object)
+ nl_object_put (cached_object);
+ else
+ announce_object (platform, object, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL);
+ }
+
+ nl_cache_free (old);
+}
+
+/* Creates and populates the netlink object caches. Called upon platform init and
+ * when we run out of sync (out of buffer space, netlink congestion control). In case
+ * the caches already exist, it finds changed, added and removed objects, announces
+ * them and destroys the old caches. */
+static void
+cache_repopulate_all (NMPlatform *platform)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ struct nl_cache *old_link_cache = priv->link_cache;
+ struct nl_cache *old_address_cache = priv->address_cache;
+ struct nl_cache *old_route_cache = priv->route_cache;
+ struct nl_object *object;
+
+ debug ("platform: %spopulate platform cache", old_link_cache ? "re" : "");
+
+ /* Allocate new netlink caches */
+ init_link_cache (platform);
+ rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache);
+ rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache);
+ g_assert (priv->link_cache && priv->address_cache && priv->route_cache);
+
+ for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object)) {
+ _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object);
+ }
+
+ /* Make sure all changes we've missed are announced. */
+ cache_announce_changes (platform, priv->link_cache, old_link_cache);
+ cache_announce_changes (platform, priv->address_cache, old_address_cache);
+ cache_announce_changes (platform, priv->route_cache, old_route_cache);
+}
+
+/******************************************************************/
+
#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI))
#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL))
#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP))
@@ -3798,7 +4120,8 @@ event_handler (GIOChannel *channel,
GIOCondition io_condition,
gpointer user_data)
{
- NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (user_data);
+ NMPlatform *platform = NM_PLATFORM (user_data);
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
int nle;
nle = nl_recvmsgs_default (priv->nlh_event);
@@ -3810,6 +4133,17 @@ event_handler (GIOChannel *channel,
* and can happen easily. */
debug ("Uncritical failure to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
break;
+ case -NLE_NOMEM:
+ warning ("Too many netlink events. Need to resynchronize platform cache");
+ /* Drain the event queue, we've lost events and are out of sync anyway and we'd
+ * like to free up some space. We'll read in the status synchronously. */
+ nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_DEFAULT, NULL, NULL);
+ do {
+ nle = nl_recvmsgs_default (priv->nlh_event);
+ } while (nle != -NLE_AGAIN);
+ nl_socket_modify_cb (priv->nlh_event, NL_CB_VALID, NL_CB_CUSTOM, event_notification, user_data);
+ cache_repopulate_all (platform);
+ break;
default:
error ("Failed to retrieve incoming events: %s (%d)", nl_geterror (nle), nle);
break;
@@ -3841,6 +4175,12 @@ setup_socket (gboolean event, gpointer user_data)
nle = nl_socket_set_passcred (sock, 1);
g_assert (!nle);
+ /* No blocking for event socket, so that we can drain it safely. */
+ if (event) {
+ nle = nl_socket_set_nonblocking (sock);
+ g_assert (!nle);
+ }
+
return sock;
}
@@ -3979,7 +4319,9 @@ setup (NMPlatform *platform)
int channel_flags;
gboolean status;
int nle;
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
struct nl_object *object;
+#endif
/* Initialize netlink socket for requests */
priv->nlh = setup_socket (FALSE, platform);
@@ -4015,14 +4357,25 @@ setup (NMPlatform *platform)
(EVENT_CONDITIONS | ERROR_CONDITIONS | DISCONNECT_CONDITIONS),
event_handler, platform);
- /* Allocate netlink caches */
- rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache);
- rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache);
- rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache);
- g_assert (priv->link_cache && priv->address_cache && priv->route_cache);
+ cache_repopulate_all (platform);
- for (object = nl_cache_get_first (priv->address_cache); object; object = nl_cache_get_next (object))
- _rtnl_addr_hack_lifetimes_rel_to_abs ((struct rtnl_addr *) object);
+#if HAVE_LIBNL_INET6_ADDR_GEN_MODE
+ /* Initial check for user IPv6LL support once the link cache is allocated
+ * and filled. If there are no links in the cache yet then we'll check
+ * when a new link shows up in announce_object().
+ */
+ object = nl_cache_get_first (priv->link_cache);
+ if (object) {
+ uint8_t mode;
+
+ if (rtnl_link_inet6_get_addr_gen_mode ((struct rtnl_link *) object, &mode) == 0)
+ priv->support_user_ipv6ll = 1;
+ else
+ priv->support_user_ipv6ll = -1;
+ }
+#else
+ priv->support_user_ipv6ll = -1;
+#endif
/* Set up udev monitoring */
priv->udev_client = g_udev_client_new (udev_subsys);
@@ -4111,6 +4464,9 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_is_connected = link_is_connected;
platform_class->link_uses_arp = link_uses_arp;
+ platform_class->link_get_user_ipv6ll_enabled = link_get_user_ipv6ll_enabled;
+ platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled;
+
platform_class->link_get_address = link_get_address;
platform_class->link_set_address = link_set_address;
platform_class->link_get_mtu = link_get_mtu;
@@ -4167,6 +4523,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->ip4_address_exists = ip4_address_exists;
platform_class->ip6_address_exists = ip6_address_exists;
+ platform_class->ip4_check_reinstall_device_route = ip4_check_reinstall_device_route;
+
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;
@@ -4177,4 +4535,5 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->ip6_route_exists = ip6_route_exists;
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
+ platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll;
}
diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h
index 53ea75e69..6f2c19939 100644
--- a/src/platform/nm-linux-platform.h
+++ b/src/platform/nm-linux-platform.h
@@ -18,8 +18,8 @@
* Copyright (C) 2012 Red Hat, Inc.
*/
-#ifndef NM_LINUX_PLATFORM_H
-#define NM_LINUX_PLATFORM_H
+#ifndef __NETWORKMANAGER_LINUX_PLATFORM_H__
+#define __NETWORKMANAGER_LINUX_PLATFORM_H__
#include "nm-platform.h"
@@ -46,4 +46,4 @@ GType nm_linux_platform_get_type (void);
void nm_linux_platform_setup (void);
-#endif /* NM_LINUX_PLATFORM_H */
+#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 542b0faab..14fc44c5f 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -18,6 +18,8 @@
* Copyright (C) 2012 Red Hat, Inc.
*/
+#include "config.h"
+
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
@@ -26,6 +28,7 @@
#include <string.h>
#include <netlink/route/addr.h>
+#include "gsystem-local-alloc.h"
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-platform.h"
@@ -215,6 +218,21 @@ nm_platform_check_support_kernel_extended_ifa_flags ()
return klass->check_support_kernel_extended_ifa_flags (platform);
}
+gboolean
+nm_platform_check_support_user_ipv6ll (void)
+{
+ static int supported = -1;
+
+ g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE);
+
+ if (!klass->check_support_user_ipv6ll)
+ return FALSE;
+
+ if (supported < 0)
+ supported = klass->check_support_user_ipv6ll (platform) ? 1 : 0;
+ return !!supported;
+}
+
/******************************************************************/
/**
@@ -730,6 +748,52 @@ nm_platform_link_uses_arp (int ifindex)
}
/**
+ * nm_platform_link_get_user_ip6vll_enabled:
+ * @ifindex: Interface index
+ *
+ * Check whether NM handles IPv6LL address creation for the link. If the
+ * platform or OS doesn't support changing the IPv6LL address mode, this call
+ * will fail and return %FALSE.
+ *
+ * Returns: %TRUE if NM handles the IPv6LL address for @ifindex
+ */
+gboolean
+nm_platform_link_get_user_ipv6ll_enabled (int ifindex)
+{
+ reset_error ();
+
+ g_return_val_if_fail (ifindex >= 0, FALSE);
+ g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE);
+
+ if (klass->link_get_user_ipv6ll_enabled)
+ return klass->link_get_user_ipv6ll_enabled (platform, ifindex);
+ return FALSE;
+}
+
+/**
+ * nm_platform_link_set_user_ip6vll_enabled:
+ * @ifindex: Interface index
+ *
+ * Set whether NM handles IPv6LL address creation for the link. If the
+ * platform or OS doesn't support changing the IPv6LL address mode, this call
+ * will fail and return %FALSE.
+ *
+ * Returns: %TRUE if the operation was successful, %FALSE if it failed.
+ */
+gboolean
+nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled)
+{
+ reset_error ();
+
+ g_return_val_if_fail (ifindex >= 0, FALSE);
+ g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE);
+
+ if (klass->link_set_user_ipv6ll_enabled)
+ return klass->link_set_user_ipv6ll_enabled (platform, ifindex, enabled);
+ return FALSE;
+}
+
+/**
* nm_platform_link_set_address:
* @ifindex: Interface index
* @address: The new MAC address
@@ -877,7 +941,7 @@ nm_platform_link_set_mtu (int ifindex, guint32 mtu)
g_return_val_if_fail (mtu > 0, FALSE);
g_return_val_if_fail (klass->link_set_mtu, FALSE);
- debug ("link: setting '%s' (%d) mtu %d", nm_platform_link_get_name (ifindex), ifindex, mtu);
+ debug ("link: setting '%s' (%d) mtu %"G_GUINT32_FORMAT, nm_platform_link_get_name (ifindex), ifindex, mtu);
return klass->link_set_mtu (platform, ifindex, mtu);
}
@@ -1051,7 +1115,7 @@ nm_platform_team_add (const char *name)
* nm_platform_vlan_add:
* @name: New interface name
* @vlanid: VLAN identifier
- * @vlanflags: VLAN flags from libnm-util
+ * @vlanflags: VLAN flags from libnm
*
* Create a software VLAN device.
*/
@@ -1266,7 +1330,7 @@ nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps)
}
gboolean
-nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid)
+nm_platform_wifi_get_bssid (int ifindex, guint8 *bssid)
{
reset_error ();
@@ -1377,14 +1441,38 @@ nm_platform_mesh_set_channel (int ifindex, guint32 channel)
}
gboolean
-nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid)
+nm_platform_mesh_set_ssid (int ifindex, const guint8 *ssid, gsize len)
{
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (ssid != NULL, FALSE);
- return klass->mesh_set_ssid (platform, ifindex, ssid);
+ return klass->mesh_set_ssid (platform, ifindex, ssid, len);
+}
+
+#define TO_STRING_DEV_BUF_SIZE (5+15+1)
+static const char *
+_to_string_dev (int ifindex, char *buf, size_t size)
+{
+ g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE);
+
+ if (ifindex) {
+ const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL;
+ char *buf2;
+
+ strcpy (buf, " dev ");
+ buf2 = buf + 5;
+ size -= 5;
+
+ if (name)
+ g_strlcpy (buf2, name, size);
+ else
+ g_snprintf (buf2, size, "%d", ifindex);
+ } else
+ buf[0] = 0;
+
+ return buf;
}
/******************************************************************/
@@ -1482,28 +1570,41 @@ nm_platform_ip6_address_add (int ifindex,
}
gboolean
-nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen)
+nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen, in_addr_t peer_address)
{
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
+ char str_peer[NM_UTILS_INET_ADDRSTRLEN];
+
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (klass->ip4_address_delete, FALSE);
- debug ("address: deleting IPv4 address %s/%d", nm_utils_inet4_ntop (address, NULL), plen);
- return klass->ip4_address_delete (platform, ifindex, address, plen);
+ debug ("address: deleting IPv4 address %s/%d, %s%s%sifindex %d%s",
+ nm_utils_inet4_ntop (address, NULL), plen,
+ peer_address ? "peer " : "",
+ peer_address ? nm_utils_inet4_ntop (peer_address, str_peer) : "",
+ peer_address ? ", " : "",
+ ifindex,
+ _to_string_dev (ifindex, str_dev, sizeof (str_dev)));
+ return klass->ip4_address_delete (platform, ifindex, address, plen, peer_address);
}
gboolean
nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen)
{
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
+
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (klass->ip6_address_delete, FALSE);
- debug ("address: deleting IPv6 address %s/%d", nm_utils_inet6_ntop (&address, NULL), plen);
+ debug ("address: deleting IPv6 address %s/%d, ifindex %d%s",
+ nm_utils_inet6_ntop (&address, NULL), plen, ifindex,
+ _to_string_dev (ifindex, str_dev, sizeof (str_dev)));
return klass->ip6_address_delete (platform, ifindex, address, plen);
}
@@ -1600,11 +1701,16 @@ _rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now,
static gboolean
_address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 padding, guint32 *out_lifetime, guint32 *out_preferred)
{
- gint32 lifetime, preferred;
+ guint32 lifetime, preferred;
if (address->lifetime == 0) {
*out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
*out_preferred = NM_PLATFORM_LIFETIME_PERMANENT;
+
+ /* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses
+ * (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT).
+ * In that case we also expect that the other fields (timestamp and preferred) are left unset. */
+ g_return_val_if_fail (address->timestamp == 0 && address->preferred == 0, TRUE);
} else {
lifetime = _rebase_relative_time_on_now (address->timestamp, address->lifetime, now, padding);
if (!lifetime)
@@ -1626,10 +1732,31 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32
return TRUE;
}
+gboolean
+nm_platform_ip4_check_reinstall_device_route (int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
+{
+ g_return_val_if_fail (address, FALSE);
+
+ if ( ifindex <= 0
+ || address->plen <= 0
+ || address->plen >= 32)
+ return FALSE;
+
+ if (device_route_metric == NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
+ /* The automatically added route would be already our desired priority.
+ * Nothing to do. */
+ return FALSE;
+ }
+
+ return klass->ip4_check_reinstall_device_route (platform, ifindex, address, device_route_metric);
+}
+
/**
* nm_platform_ip4_address_sync:
* @ifindex: Interface index
* @known_addresses: List of addresses
+ * @device_route_metric: the route metric for adding subnet routes (replaces
+ * the kernel added routes).
*
* A convenience function to synchronize addresses for a specific interface
* with the least possible disturbance. It simply removes addresses that are
@@ -1638,7 +1765,7 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32
* Returns: %TRUE on success.
*/
gboolean
-nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
+nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses, guint32 device_route_metric)
{
GArray *addresses;
NMPlatformIP4Address *address;
@@ -1651,7 +1778,7 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
address = &g_array_index (addresses, NMPlatformIP4Address, i);
if (!array_contains_ip4_address (known_addresses, address))
- nm_platform_ip4_address_delete (ifindex, address->address, address->plen);
+ nm_platform_ip4_address_delete (ifindex, address->address, address->plen, address->peer_address);
}
g_array_free (addresses, TRUE);
@@ -1662,13 +1789,34 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
for (i = 0; i < known_addresses->len; i++) {
const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
guint32 lifetime, preferred;
+ guint32 network;
+ gboolean reinstall_device_route = FALSE;
/* add a padding of 5 seconds to avoid potential races. */
if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred))
continue;
+ if (nm_platform_ip4_check_reinstall_device_route (ifindex, known_address, device_route_metric))
+ reinstall_device_route = TRUE;
+
if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label))
return FALSE;
+
+ if (reinstall_device_route) {
+ /* Kernel automatically adds a device route for us with metric 0. That is not what we want.
+ * Remove it, and re-add it.
+ *
+ * In face of having the same subnets on two different interfaces with the same metric,
+ * this is a problem. Surprisingly, kernel is able to add two routes for the same subnet/prefix,metric
+ * to different interfaces. We cannot. Adding one, would replace the other. This is avoided
+ * by the above nm_platform_ip4_check_reinstall_device_route() check.
+ */
+ network = nm_utils_ip4_address_clear_host_address (known_address->address, known_address->plen);
+ (void) nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_KERNEL, network, known_address->plen,
+ 0, known_address->address, device_route_metric, 0);
+ (void) nm_platform_ip4_route_delete (ifindex, network, known_address->plen,
+ NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE);
+ }
}
return TRUE;
@@ -1731,49 +1879,49 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
gboolean
nm_platform_address_flush (int ifindex)
{
- return nm_platform_ip4_address_sync (ifindex, NULL)
+ return nm_platform_ip4_address_sync (ifindex, NULL, 0)
&& nm_platform_ip6_address_sync (ifindex, NULL);
}
/******************************************************************/
GArray *
-nm_platform_ip4_route_get_all (int ifindex, gboolean include_default)
+nm_platform_ip4_route_get_all (int ifindex, NMPlatformGetRouteMode mode)
{
reset_error ();
- g_return_val_if_fail (ifindex > 0, NULL);
+ g_return_val_if_fail (ifindex >= 0, NULL);
g_return_val_if_fail (klass->ip4_route_get_all, NULL);
- return klass->ip4_route_get_all (platform, ifindex, include_default);
+ return klass->ip4_route_get_all (platform, ifindex, mode);
}
GArray *
-nm_platform_ip6_route_get_all (int ifindex, gboolean include_default)
+nm_platform_ip6_route_get_all (int ifindex, NMPlatformGetRouteMode mode)
{
reset_error ();
- g_return_val_if_fail (ifindex > 0, NULL);
+ g_return_val_if_fail (ifindex >= 0, NULL);
g_return_val_if_fail (klass->ip6_route_get_all, NULL);
- return klass->ip6_route_get_all (platform, ifindex, include_default);
+ return klass->ip6_route_get_all (platform, ifindex, mode);
}
gboolean
-nm_platform_ip4_route_add (int ifindex, NMPlatformSource source,
+nm_platform_ip4_route_add (int ifindex, NMIPConfigSource source,
in_addr_t network, int plen,
- in_addr_t gateway, int metric, int mss)
+ in_addr_t gateway, guint32 pref_src,
+ guint32 metric, guint32 mss)
{
reset_error ();
g_return_val_if_fail (platform, FALSE);
g_return_val_if_fail (0 <= plen && plen <= 32, FALSE);
- g_return_val_if_fail (metric >= 0, FALSE);
- g_return_val_if_fail (mss >= 0, FALSE);
g_return_val_if_fail (klass->ip4_route_add, FALSE);
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
NMPlatformIP4Route route = { 0 };
+ char pref_src_buf[NM_UTILS_INET_ADDRSTRLEN];
route.ifindex = ifindex;
route.source = source;
@@ -1783,20 +1931,21 @@ nm_platform_ip4_route_add (int ifindex, NMPlatformSource source,
route.metric = metric;
route.mss = mss;
- debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route));
+ debug ("route: adding or updating IPv4 route: %s%s%s%s", nm_platform_ip4_route_to_string (&route),
+ pref_src ? " (src: " : "",
+ pref_src ? nm_utils_inet4_ntop (pref_src, pref_src_buf) : "",
+ pref_src ? ")" : "");
}
- return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, metric, mss);
+ return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, pref_src, metric, mss);
}
gboolean
-nm_platform_ip6_route_add (int ifindex, NMPlatformSource source,
+nm_platform_ip6_route_add (int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
- int metric, int mss)
+ guint32 metric, guint32 mss)
{
g_return_val_if_fail (platform, FALSE);
g_return_val_if_fail (0 <= plen && plen <= 128, FALSE);
- g_return_val_if_fail (metric >= 0, FALSE);
- g_return_val_if_fail (mss >= 0, FALSE);
g_return_val_if_fail (klass->ip6_route_add, FALSE);
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
@@ -1816,31 +1965,39 @@ nm_platform_ip6_route_add (int ifindex, NMPlatformSource source,
}
gboolean
-nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric)
+nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, guint32 metric)
{
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
+
reset_error ();
g_return_val_if_fail (platform, FALSE);
g_return_val_if_fail (klass->ip4_route_delete, FALSE);
- debug ("route: deleting IPv4 route %s/%d, metric=%d", nm_utils_inet4_ntop (network, NULL), plen, metric);
+ debug ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
+ nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex,
+ _to_string_dev (ifindex, str_dev, sizeof (str_dev)));
return klass->ip4_route_delete (platform, ifindex, network, plen, metric);
}
gboolean
-nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric)
+nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, guint32 metric)
{
+ char str_dev[TO_STRING_DEV_BUF_SIZE];
+
reset_error ();
g_return_val_if_fail (platform, FALSE);
g_return_val_if_fail (klass->ip6_route_delete, FALSE);
- debug ("route: deleting IPv6 route %s/%d, metric=%d", nm_utils_inet6_ntop (&network, NULL), plen, metric);
+ debug ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
+ nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex,
+ _to_string_dev (ifindex, str_dev, sizeof (str_dev)));
return klass->ip6_route_delete (platform, ifindex, network, plen, metric);
}
gboolean
-nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric)
+nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, guint32 metric)
{
reset_error ();
@@ -1851,7 +2008,7 @@ nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metr
}
gboolean
-nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric)
+nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, guint32 metric)
{
reset_error ();
@@ -1907,6 +2064,8 @@ array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route)
* A convenience function to synchronize routes for a specific interface
* with the least possible disturbance. It simply removes routes that are
* not listed and adds routes that are.
+ * Default routes are ignored (both in @known_routes and those already
+ * configured on the device).
*
* Returns: %TRUE on success.
*/
@@ -1920,12 +2079,12 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
int i, i_type;
/* Delete unknown routes */
- routes = nm_platform_ip4_route_get_all (ifindex, FALSE);
+ routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP4Route, i);
if (!array_contains_ip4_route (known_routes, route))
- nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric);
+ (void) nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric);
}
if (!known_routes) {
@@ -1938,6 +2097,9 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
for (i = 0; i < known_routes->len && success; i++) {
known_route = &g_array_index (known_routes, NMPlatformIP4Route, i);
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
+ continue;
+
if ((known_route->gateway == 0) ^ (i_type != 0)) {
/* Make two runs over the list of routes. On the first, only add
* device routes, on the second the others (gateway routes). */
@@ -1951,9 +2113,10 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
known_route->network,
known_route->plen,
known_route->gateway,
+ 0,
known_route->metric,
known_route->mss);
- if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) {
+ if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s",
nm_platform_ip4_route_to_string (known_route));
success = TRUE;
@@ -1974,6 +2137,8 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
* A convenience function to synchronize routes for a specific interface
* with the least possible disturbance. It simply removes routes that are
* not listed and adds routes that are.
+ * Default routes are ignored (both in @known_routes and those already
+ * configured on the device).
*
* Returns: %TRUE on success.
*/
@@ -1987,7 +2152,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
int i, i_type;
/* Delete unknown routes */
- routes = nm_platform_ip6_route_get_all (ifindex, FALSE);
+ routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP6Route, i);
route->ifindex = 0;
@@ -2006,6 +2171,9 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
for (i = 0; i < known_routes->len && success; i++) {
known_route = &g_array_index (known_routes, NMPlatformIP6Route, i);
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
+ continue;
+
if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) {
/* Make two runs over the list of routes. On the first, only add
* device routes, on the second the others (gateway routes). */
@@ -2021,7 +2189,7 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
known_route->gateway,
known_route->metric,
known_route->mss);
- if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) {
+ if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s",
nm_platform_ip6_route_to_string (known_route));
success = TRUE;
@@ -2044,26 +2212,26 @@ nm_platform_route_flush (int ifindex)
/******************************************************************/
static const char *
-source_to_string (NMPlatformSource source)
+source_to_string (NMIPConfigSource source)
{
switch (source) {
- case NM_PLATFORM_SOURCE_KERNEL:
+ case NM_IP_CONFIG_SOURCE_KERNEL:
return "kernel";
- case NM_PLATFORM_SOURCE_SHARED:
+ case NM_IP_CONFIG_SOURCE_SHARED:
return "shared";
- case NM_PLATFORM_SOURCE_IP4LL:
+ case NM_IP_CONFIG_SOURCE_IP4LL:
return "ipv4ll";
- case NM_PLATFORM_SOURCE_PPP:
+ case NM_IP_CONFIG_SOURCE_PPP:
return "ppp";
- case NM_PLATFORM_SOURCE_WWAN:
+ case NM_IP_CONFIG_SOURCE_WWAN:
return "wwan";
- case NM_PLATFORM_SOURCE_VPN:
+ case NM_IP_CONFIG_SOURCE_VPN:
return "vpn";
- case NM_PLATFORM_SOURCE_DHCP:
+ case NM_IP_CONFIG_SOURCE_DHCP:
return "dhcp";
- case NM_PLATFORM_SOURCE_RDISC:
+ case NM_IP_CONFIG_SOURCE_RDISC:
return "rdisc";
- case NM_PLATFORM_SOURCE_USER:
+ case NM_IP_CONFIG_SOURCE_USER:
return "user";
default:
break;
@@ -2071,27 +2239,6 @@ source_to_string (NMPlatformSource source)
return "unknown";
}
-#define TO_STRING_DEV_BUF_SIZE (5+15+1)
-static void
-_to_string_dev (int ifindex, char *buf, size_t size)
-{
- g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE);
-
- if (ifindex){
- const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL;
-
- strcpy (buf, " dev ");
- buf += 5;
- size -= 5;
-
- if (name)
- g_strlcpy (buf, name, size);
- else
- g_snprintf (buf, size, "%d", ifindex);
- } else
- buf[0] = 0;
-}
-
static const char *
_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
{
@@ -2330,7 +2477,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
_to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
- g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s",
+ g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s",
s_network, route->plen, s_gateway,
str_dev,
route->metric, route->mss,
@@ -2363,7 +2510,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
_to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
- g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %u mss %u src %s",
+ g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s",
s_network, route->plen, s_gateway,
str_dev,
route->metric, route->mss,
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 96b6cfabb..848f78e42 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -18,17 +18,17 @@
* Copyright (C) 2009 - 2010 Red Hat, Inc.
*/
-#ifndef NM_PLATFORM_H
-#define NM_PLATFORM_H
+#ifndef __NETWORKMANAGER_PLATFORM_H__
+#define __NETWORKMANAGER_PLATFORM_H__
#include <glib-object.h>
#include "nm-glib-compat.h"
#include <netinet/in.h>
-#include <net/ethernet.h>
#include <linux/if.h>
#include <linux/if_addr.h>
-#include <NetworkManager.h>
+#include <nm-dbus-interface.h>
+#include "nm-types.h"
#define NM_TYPE_PLATFORM (nm_platform_get_type ())
#define NM_PLATFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
@@ -72,54 +72,11 @@ typedef enum {
NM_PLATFORM_REASON_CACHE_CHECK
} NMPlatformReason;
-typedef enum {
- /* Please don't interpret type numbers outside nm-platform and use functions
- * like nm_platform_link_is_software() and nm_platform_supports_slaves().
- *
- * type & 0x10000 -> Software device type
- * type & 0x20000 -> Type supports slaves
- */
-
- /* No type, used as error value */
- NM_LINK_TYPE_NONE,
-
- /* Unknown type */
- NM_LINK_TYPE_UNKNOWN,
-
- /* Hardware types */
- NM_LINK_TYPE_ETHERNET,
- NM_LINK_TYPE_INFINIBAND,
- NM_LINK_TYPE_OLPC_MESH,
- NM_LINK_TYPE_WIFI,
- NM_LINK_TYPE_WWAN_ETHERNET, /* WWAN pseudo-ethernet */
- NM_LINK_TYPE_WIMAX,
-
- /* Software types */
- NM_LINK_TYPE_DUMMY = 0x10000,
- NM_LINK_TYPE_GRE,
- NM_LINK_TYPE_GRETAP,
- NM_LINK_TYPE_IFB,
- NM_LINK_TYPE_LOOPBACK,
- NM_LINK_TYPE_MACVLAN,
- NM_LINK_TYPE_MACVTAP,
- NM_LINK_TYPE_OPENVSWITCH,
- NM_LINK_TYPE_TAP,
- NM_LINK_TYPE_TUN,
- NM_LINK_TYPE_VETH,
- NM_LINK_TYPE_VLAN,
- NM_LINK_TYPE_VXLAN,
-
- /* Software types with slaves */
- NM_LINK_TYPE_BRIDGE = 0x10000 | 0x20000,
- NM_LINK_TYPE_BOND,
- NM_LINK_TYPE_TEAM,
-} NMLinkType;
-
#define __NMPlatformObject_COMMON \
int ifindex; \
;
-typedef struct {
+struct _NMPlatformLink {
__NMPlatformObject_COMMON;
char name[IFNAMSIZ];
NMLinkType type;
@@ -132,7 +89,7 @@ typedef struct {
gboolean connected;
gboolean arp;
guint mtu;
-} NMPlatformLink;
+};
typedef enum {
NM_PLATFORM_SIGNAL_ADDED,
@@ -143,19 +100,10 @@ typedef enum {
#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
typedef enum {
- /* In priority order; higher number == higher priority */
- NM_PLATFORM_SOURCE_UNKNOWN,
- NM_PLATFORM_SOURCE_KERNEL,
- NM_PLATFORM_SOURCE_SHARED,
- NM_PLATFORM_SOURCE_IP4LL,
- NM_PLATFORM_SOURCE_PPP,
- NM_PLATFORM_SOURCE_WWAN,
- NM_PLATFORM_SOURCE_VPN,
- NM_PLATFORM_SOURCE_DHCP,
- NM_PLATFORM_SOURCE_RDISC,
- NM_PLATFORM_SOURCE_USER,
-} NMPlatformSource;
-
+ NM_PLATFORM_GET_ROUTE_MODE_ALL,
+ NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT,
+ NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT,
+} NMPlatformGetRouteMode;
typedef struct {
__NMPlatformObject_COMMON;
@@ -164,7 +112,7 @@ typedef struct {
#define __NMPlatformIPAddress_COMMON \
__NMPlatformObject_COMMON; \
- NMPlatformSource source; \
+ NMIPConfigSource source; \
\
/* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
*
@@ -207,37 +155,55 @@ typedef struct {
* NMPlatformIP4Address:
* @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s()
**/
-typedef struct {
+struct _NMPlatformIP4Address {
__NMPlatformIPAddress_COMMON;
in_addr_t address;
in_addr_t peer_address; /* PTP peer address */
char label[IFNAMSIZ];
-} NMPlatformIP4Address;
+};
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Address, address));
/**
* NMPlatformIP6Address:
* @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s()
**/
-typedef struct {
+struct _NMPlatformIP6Address {
__NMPlatformIPAddress_COMMON;
struct in6_addr address;
struct in6_addr peer_address;
guint flags; /* ifa_flags from <linux/if_addr.h>, field type "unsigned int" is as used in rtnl_addr_get_flags. */
-} NMPlatformIP6Address;
+};
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPAddress, address_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Address, address));
+typedef union {
+ NMPlatformIPAddress ax;
+ NMPlatformIP4Address a4;
+ NMPlatformIP6Address a6;
+} NMPlatformIPXAddress;
+
#undef __NMPlatformIPAddress_COMMON
-#define NM_PLATFORM_ROUTE_METRIC_DEFAULT 1024
+/* Default value for adding an IPv4 route. This is also what iproute2 does.
+ * Note that contrary to IPv6, you can add routes with metric 0 and it is even
+ * the default.
+ */
+#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0
+
+/* Default value for adding an IPv6 route. This is also what iproute2 does.
+ * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). */
+#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024
+
+/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user
+ * configures addresses. */
+#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE 0
#define __NMPlatformIPRoute_COMMON \
__NMPlatformObject_COMMON; \
- NMPlatformSource source; \
+ NMIPConfigSource source; \
int plen; \
- guint metric; \
- guint mss; \
+ guint32 metric; \
+ guint32 mss; \
;
typedef struct {
@@ -248,20 +214,29 @@ typedef struct {
};
} NMPlatformIPRoute;
-typedef struct {
+#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
+ ( ((const NMPlatformIPRoute *) (route))->plen <= 0 )
+
+struct _NMPlatformIP4Route {
__NMPlatformIPRoute_COMMON;
in_addr_t network;
in_addr_t gateway;
-} NMPlatformIP4Route;
+};
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network));
-typedef struct {
+struct _NMPlatformIP6Route {
__NMPlatformIPRoute_COMMON;
struct in6_addr network;
struct in6_addr gateway;
-} NMPlatformIP6Route;
+};
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP6Route, network));
+typedef union {
+ NMPlatformIPRoute rx;
+ NMPlatformIP4Route r4;
+ NMPlatformIP6Route r6;
+} NMPlatformIPXRoute;
+
#undef __NMPlatformIPRoute_COMMON
@@ -384,6 +359,9 @@ typedef struct {
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
+ gboolean (*link_get_user_ipv6ll_enabled) (NMPlatform *, int ifindex);
+ gboolean (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled);
+
gconstpointer (*link_get_address) (NMPlatform *, int ifindex, size_t *length);
gboolean (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
guint32 (*link_get_mtu) (NMPlatform *, int ifindex);
@@ -417,7 +395,7 @@ typedef struct {
gboolean (*gre_get_properties) (NMPlatform *, int ifindex, NMPlatformGreProperties *props);
gboolean (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps);
- gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, struct ether_addr *bssid);
+ gboolean (*wifi_get_bssid) (NMPlatform *, int ifindex, guint8 *bssid);
GByteArray *(*wifi_get_ssid) (NMPlatform *, int ifindex);
guint32 (*wifi_get_frequency) (NMPlatform *, int ifindex);
int (*wifi_get_quality) (NMPlatform *, int ifindex);
@@ -429,7 +407,7 @@ typedef struct {
guint32 (*mesh_get_channel) (NMPlatform *, int ifindex);
gboolean (*mesh_set_channel) (NMPlatform *, int ifindex, guint32 channel);
- gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const GByteArray *ssid);
+ gboolean (*mesh_set_ssid) (NMPlatform *, int ifindex, const guint8 *ssid, gsize len);
GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex);
@@ -440,25 +418,28 @@ typedef struct {
gboolean (*ip6_address_add) (NMPlatform *, int ifindex,
struct in6_addr address, struct in6_addr peer_address, int plen,
guint32 lifetime, guint32 preferred_lft, guint flags);
- gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen);
+ gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen);
gboolean (*ip6_address_exists) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
- GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, gboolean include_default);
- GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, gboolean include_default);
- gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMPlatformSource source,
+ gboolean (*ip4_check_reinstall_device_route) (NMPlatform *, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric);
+
+ GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteMode mode);
+ GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteMode mode);
+ gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
- int prio, int mss);
- gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMPlatformSource source,
+ guint32 pref_src, guint32 metric, guint32 mss);
+ gboolean (*ip6_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
- int prio, int mss);
- gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
- gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
- gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, int metric);
- gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, int metric);
+ guint32 metric, guint32 mss);
+ gboolean (*ip4_route_delete) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
+ gboolean (*ip6_route_delete) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
+ gboolean (*ip4_route_exists) (NMPlatform *, int ifindex, in_addr_t network, int plen, guint32 metric);
+ gboolean (*ip6_route_exists) (NMPlatform *, int ifindex, struct in6_addr network, int plen, guint32 metric);
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
+ gboolean (*check_support_user_ipv6ll) (NMPlatform *);
} NMPlatformClass;
/* NMPlatform signals
@@ -524,6 +505,9 @@ gboolean nm_platform_link_is_up (int ifindex);
gboolean nm_platform_link_is_connected (int ifindex);
gboolean nm_platform_link_uses_arp (int ifindex);
+gboolean nm_platform_link_get_user_ipv6ll_enabled (int ifindex);
+gboolean nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled);
+
gconstpointer nm_platform_link_get_address (int ifindex, size_t *length);
gboolean nm_platform_link_set_address (int ifindex, const void *address, size_t length);
guint32 nm_platform_link_get_mtu (int ifindex);
@@ -557,7 +541,7 @@ gboolean nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanPropertie
gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props);
gboolean nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps);
-gboolean nm_platform_wifi_get_bssid (int ifindex, struct ether_addr *bssid);
+gboolean nm_platform_wifi_get_bssid (int ifindex, guint8 *bssid);
GByteArray *nm_platform_wifi_get_ssid (int ifindex);
guint32 nm_platform_wifi_get_frequency (int ifindex);
int nm_platform_wifi_get_quality (int ifindex);
@@ -569,7 +553,7 @@ void nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean
guint32 nm_platform_mesh_get_channel (int ifindex);
gboolean nm_platform_mesh_set_channel (int ifindex, guint32 channel);
-gboolean nm_platform_mesh_set_ssid (int ifindex, const GByteArray *ssid);
+gboolean nm_platform_mesh_set_ssid (int ifindex, const guint8 *ssid, gsize len);
GArray *nm_platform_ip4_address_get_all (int ifindex);
GArray *nm_platform_ip6_address_get_all (int ifindex);
@@ -580,27 +564,28 @@ gboolean nm_platform_ip4_address_add (int ifindex,
gboolean nm_platform_ip6_address_add (int ifindex,
struct in6_addr address, struct in6_addr peer_address, int plen,
guint32 lifetime, guint32 preferred_lft, guint flags);
-gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen);
+gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen, in_addr_t peer_address);
gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen);
gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen);
gboolean nm_platform_ip6_address_exists (int ifindex, struct in6_addr address, int plen);
-gboolean nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses);
+gboolean nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses, guint32 device_route_metric);
gboolean nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses);
gboolean nm_platform_address_flush (int ifindex);
-GArray *nm_platform_ip4_route_get_all (int ifindex, gboolean include_default);
-GArray *nm_platform_ip6_route_get_all (int ifindex, gboolean include_default);
-gboolean nm_platform_route_set_metric (int ifindex, int metric);
-gboolean nm_platform_ip4_route_add (int ifindex, NMPlatformSource source,
+gboolean nm_platform_ip4_check_reinstall_device_route (int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric);
+
+GArray *nm_platform_ip4_route_get_all (int ifindex, NMPlatformGetRouteMode mode);
+GArray *nm_platform_ip6_route_get_all (int ifindex, NMPlatformGetRouteMode mode);
+gboolean nm_platform_ip4_route_add (int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
- int metric, int mss);
-gboolean nm_platform_ip6_route_add (int ifindex, NMPlatformSource source,
+ guint32 pref_src, guint32 metric, guint32 mss);
+gboolean nm_platform_ip6_route_add (int ifindex, NMIPConfigSource source,
struct in6_addr network, int plen, struct in6_addr gateway,
- int metric, int mss);
-gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, int metric);
-gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, int metric);
-gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, int metric);
-gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, int metric);
+ guint32 metric, guint32 mss);
+gboolean nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, guint32 metric);
+gboolean nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, guint32 metric);
+gboolean nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, guint32 metric);
+gboolean nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, guint32 metric);
gboolean nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes);
gboolean nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes);
gboolean nm_platform_route_flush (int ifindex);
@@ -619,16 +604,10 @@ int nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6R
gboolean nm_platform_check_support_libnl_extended_ifa_flags (void);
gboolean nm_platform_check_support_kernel_extended_ifa_flags (void);
+gboolean nm_platform_check_support_user_ipv6ll (void);
void nm_platform_addr_flags2str (int flags, char *buf, size_t size);
int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b);
-#define auto_g_free __attribute__((cleanup(put_g_free)))
-static void __attribute__((unused))
-put_g_free (void *ptr)
-{
- g_clear_pointer ((gpointer *) ptr, g_free);
-}
-
-#endif /* NM_PLATFORM_H */
+#endif /* __NETWORKMANAGER_PLATFORM_H__ */
diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am
index 9b10ea7b2..b06e25e0c 100644
--- a/src/platform/tests/Makefile.am
+++ b/src/platform/tests/Makefile.am
@@ -1,14 +1,13 @@
AM_CPPFLAGS = \
-I${top_srcdir} \
-I${top_srcdir}/include \
- -I${top_builddir}/include \
-I${top_srcdir}/src \
-I${top_builddir}/src \
- -I${top_srcdir}/src/logging \
- -I${top_srcdir}/libnm-util \
- -I${top_builddir}/libnm-util \
+ -I${top_srcdir}/libnm-core \
+ -I${top_builddir}/libnm-core \
-I${srcdir}/.. \
-DG_LOG_DOMAIN=\""NetworkManager"\" \
+ -DNETWORKMANAGER_COMPILATION \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
$(GLIB_CFLAGS) \
$(GUDEV_CFLAGS) \
@@ -111,6 +110,6 @@ test_cleanup_linux_CPPFLAGS = \
test_cleanup_linux_LDADD = $(PLATFORM_LDADD)
#@VALGRIND_RULES@
-TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-link-linux test-address-linux test-route-linux test-cleanup-linux
+TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-address-linux test-route-linux test-cleanup-linux
diff --git a/src/platform/tests/Makefile.in b/src/platform/tests/Makefile.in
index 6b03e315a..052636abe 100644
--- a/src/platform/tests/Makefile.in
+++ b/src/platform/tests/Makefile.in
@@ -86,8 +86,8 @@ noinst_PROGRAMS = dump$(EXEEXT) monitor$(EXEEXT) platform$(EXEEXT) \
test-cleanup-fake$(EXEEXT) test-cleanup-linux$(EXEEXT)
TESTS = test-link-fake$(EXEEXT) test-address-fake$(EXEEXT) \
test-route-fake$(EXEEXT) test-cleanup-fake$(EXEEXT) \
- test-link-linux$(EXEEXT) test-address-linux$(EXEEXT) \
- test-route-linux$(EXEEXT) test-cleanup-linux$(EXEEXT)
+ test-address-linux$(EXEEXT) test-route-linux$(EXEEXT) \
+ test-cleanup-linux$(EXEEXT)
subdir = src/platform/tests
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/depcomp
@@ -299,6 +299,8 @@ AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
@@ -422,6 +424,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@
NEWT_LIBS = @NEWT_LIBS@
NM = @NM@
NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
NM_MICRO_VERSION = @NM_MICRO_VERSION@
NM_MINOR_VERSION = @NM_MINOR_VERSION@
@@ -441,6 +444,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -467,7 +471,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
-UDEV_BASE_DIR = @UDEV_BASE_DIR@
+UDEV_DIR = @UDEV_DIR@
USE_NLS = @USE_NLS@
UUID_CFLAGS = @UUID_CFLAGS@
UUID_LIBS = @UUID_LIBS@
@@ -547,10 +551,10 @@ with_netconfig = @with_netconfig@
with_resolvconf = @with_resolvconf@
with_valgrind = @with_valgrind@
AM_CPPFLAGS = -I${top_srcdir} -I${top_srcdir}/include \
- -I${top_builddir}/include -I${top_srcdir}/src \
- -I${top_builddir}/src -I${top_srcdir}/src/logging \
- -I${top_srcdir}/libnm-util -I${top_builddir}/libnm-util \
+ -I${top_srcdir}/src -I${top_builddir}/src \
+ -I${top_srcdir}/libnm-core -I${top_builddir}/libnm-core \
-I${srcdir}/.. -DG_LOG_DOMAIN=\""NetworkManager"\" \
+ -DNETWORKMANAGER_COMPILATION \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
$(GUDEV_CFLAGS) $(LIBNL_CFLAGS) $(am__append_1)
PLATFORM_SOURCES = \
diff --git a/src/platform/tests/dump.c b/src/platform/tests/dump.c
index e97ef138c..3bb61da41 100644
--- a/src/platform/tests/dump.c
+++ b/src/platform/tests/dump.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
@@ -83,8 +85,8 @@ dump_interface (NMPlatformLink *link)
g_array_unref (ip4_addresses);
g_array_unref (ip6_addresses);
- ip4_routes = nm_platform_ip4_route_get_all (link->ifindex, TRUE);
- ip6_routes = nm_platform_ip6_route_get_all (link->ifindex, TRUE);
+ ip4_routes = nm_platform_ip4_route_get_all (link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ ip6_routes = nm_platform_ip6_route_get_all (link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
g_assert (ip4_routes);
g_assert (ip6_routes);
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index d56cc2bf8..9aff10476 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include <stdlib.h>
#include <syslog.h>
diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
index ea8bd0e3b..eea6610d3 100644
--- a/src/platform/tests/platform.c
+++ b/src/platform/tests/platform.c
@@ -18,12 +18,15 @@
* Copyright (C) 2013 Red Hat, Inc.
*/
+#include "config.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netlink/route/addr.h>
+#include "gsystem-local-alloc.h"
#include "nm-platform.h"
#include "nm-linux-platform.h"
#include "nm-fake-platform.h"
@@ -47,7 +50,7 @@ do_sysctl_set (char **argv)
static gboolean
do_sysctl_get (char **argv)
{
- auto_g_free char *value = nm_platform_sysctl_get (argv[0]);
+ gs_free char *value = nm_platform_sysctl_get (argv[0]);
printf ("%s\n", value);
@@ -281,7 +284,7 @@ do_master_get_option (char **argv)
{
int ifindex = parse_ifindex (*argv++);
const char *option = *argv++;
- auto_g_free char *value = nm_platform_master_get_option (ifindex, option);
+ gs_free char *value = nm_platform_master_get_option (ifindex, option);
printf ("%s\n", value);
@@ -303,7 +306,7 @@ do_slave_get_option (char **argv)
{
int ifindex = parse_ifindex (*argv++);
const char *option = *argv++;
- auto_g_free char *value = nm_platform_slave_get_option (ifindex, option);
+ gs_free char *value = nm_platform_slave_get_option (ifindex, option);
printf ("%s\n", value);
@@ -532,6 +535,9 @@ parse_ip_address (int family, char *str, gpointer address, int *plen)
{
char *endptr;
+ if (plen)
+ *plen = 0;
+
if (plen) {
char *ptr = strchr (str, '/');
if (ptr) {
@@ -594,7 +600,7 @@ do_ip6_address_add (char **argv)
return FALSE;
}
-#define ADDR_CMD_FULL(v, cmdname, print) \
+#define ADDR_CMD_FULL(v, cmdname, print, ...) \
static gboolean \
do_##v##_address_##cmdname (char **argv) \
{ \
@@ -602,7 +608,7 @@ do_ip6_address_add (char **argv)
v##_t address; \
int plen; \
if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \
- gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \
+ gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen, ##__VA_ARGS__); \
if (print) { \
print_boolean (value); \
return TRUE; \
@@ -611,7 +617,7 @@ do_ip6_address_add (char **argv)
} else \
return FALSE; \
}
-#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE)
+#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE, 0) ADDR_CMD_FULL (ip6, cmdname, FALSE)
#define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE)
ADDR_CMD (delete)
@@ -627,7 +633,7 @@ do_ip4_route_get_all (char **argv)
int i;
if (ifindex) {
- routes = nm_platform_ip4_route_get_all (ifindex, TRUE);
+ routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP4Route, i);
inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr));
@@ -651,7 +657,7 @@ do_ip6_route_get_all (char **argv)
int i;
if (ifindex) {
- routes = nm_platform_ip6_route_get_all (ifindex, TRUE);
+ routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP6Route, i);
inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr));
@@ -677,8 +683,8 @@ do_ip4_route_add (char **argv)
metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10);
- return nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER,
- network, plen, gateway,
+ return nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER,
+ network, plen, gateway, 0,
metric, mss);
}
@@ -693,7 +699,7 @@ do_ip6_route_add (char **argv)
parse_ip6_address (*argv++, &gateway, NULL);
metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10);
- return nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER,
+ return nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER,
network, plen, gateway,
metric, mss);
}
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index 3fef53752..3ef13b8ec 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include "test-common.h"
#define DEVICE_NAME "nm-test-device"
@@ -91,13 +93,13 @@ test_ip4_address (void)
g_array_unref (addresses);
/* Remove address */
- g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN));
+ g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0));
no_error ();
g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
accept_signal (address_removed);
/* Remove address again */
- g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN));
+ g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0));
no_error ();
free_signal (address_added);
@@ -196,7 +198,7 @@ test_ip4_address_external (void)
g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
accept_signal (address_added);
/*run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME);
- g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN));
+ g_assert (nm_platform_ip4_address_delete (ifindex, addr, IP4_PLEN, 0));
no_error ();
g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
accept_signal (address_removed);*/
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index e60d82f0e..afbb438cc 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -1,9 +1,11 @@
+#include "config.h"
+
#include "test-common.h"
#define DEVICE_NAME "nm-test-device"
static void
-test_cleanup_internal ()
+test_cleanup_internal (void)
{
SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME);
int ifindex;
@@ -43,17 +45,17 @@ test_cleanup_internal ()
/* Add routes and addresses */
g_assert (nm_platform_ip4_address_add (ifindex, addr4, 0, plen4, lifetime, preferred, NULL));
g_assert (nm_platform_ip6_address_add (ifindex, addr6, in6addr_any, plen6, lifetime, preferred, flags));
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway4, 32, INADDR_ANY, metric, mss));
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network4, plen4, gateway4, metric, mss));
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway4, metric, mss));
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss));
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network6, plen6, gateway6, metric, mss));
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway4, 32, INADDR_ANY, 0, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network4, plen4, gateway4, 0, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway4, 0, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway6, 128, in6addr_any, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, metric, mss));
addresses4 = nm_platform_ip4_address_get_all (ifindex);
addresses6 = nm_platform_ip6_address_get_all (ifindex);
- routes4 = nm_platform_ip4_route_get_all (ifindex, TRUE);
- routes6 = nm_platform_ip6_route_get_all (ifindex, TRUE);
+ routes4 = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes6 = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
g_assert_cmpint (addresses4->len, ==, 1);
g_assert_cmpint (addresses6->len, ==, 1);
@@ -70,8 +72,8 @@ test_cleanup_internal ()
addresses4 = nm_platform_ip4_address_get_all (ifindex);
addresses6 = nm_platform_ip6_address_get_all (ifindex);
- routes4 = nm_platform_ip4_route_get_all (ifindex, TRUE);
- routes6 = nm_platform_ip6_route_get_all (ifindex, TRUE);
+ routes4 = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes6 = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
g_assert_cmpint (addresses4->len, ==, 0);
g_assert_cmpint (addresses6->len, ==, 0);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 59a770c63..ab40f6524 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include "test-common.h"
#include "nm-test-utils.h"
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index a3f757c2e..8bd2ef44d 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include "test-common.h"
#include "nm-test-utils.h"
@@ -130,6 +132,7 @@ software_add (NMLinkType link_type, const char *name)
default:
g_error ("Link type %d unhandled.", link_type);
}
+ g_assert_not_reached ();
}
static void
@@ -188,12 +191,12 @@ test_slave (int master, int type, SignalData *master_changed)
/* Older team versions (e.g. Fedora 17) have a bug that team master stays
* IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if
* `ip link` also claims master to be up, accept it. */
- char *stdout = NULL;
+ char *stdout_str = NULL;
- nmtst_spawn_sync (NULL, &stdout, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (master));
+ nmtst_spawn_sync (NULL, &stdout_str, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (master));
- g_assert (strstr (stdout, "LOWER_UP"));
- g_free (stdout);
+ g_assert (strstr (stdout_str, "LOWER_UP"));
+ g_free (stdout_str);
} else
g_assert_not_reached ();
}
@@ -379,7 +382,7 @@ test_team (void)
}
static void
-test_vlan ()
+test_vlan (void)
{
test_software (NM_LINK_TYPE_VLAN, "vlan");
}
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index d45730ac5..2c70b412b 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -1,3 +1,5 @@
+#include "config.h"
+
#include "test-common.h"
#include "nm-test-utils.h"
@@ -48,7 +50,7 @@ ip6_route_callback (NMPlatform *platform, int ifindex, NMPlatformIP6Route *recei
}
static void
-test_ip4_route ()
+test_ip4_route (void)
{
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback);
@@ -59,63 +61,64 @@ test_ip4_route ()
in_addr_t network;
int plen = 24;
in_addr_t gateway;
- int metric = 20;
+ /* Choose a high metric so that we hopefully don't conflict. */
+ int metric = 22986;
int mss = 1000;
inet_pton (AF_INET, "192.0.3.0", &network);
inet_pton (AF_INET, "198.51.100.1", &gateway);
/* Add route to gateway */
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 32, INADDR_ANY, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 32, INADDR_ANY, 0, metric, mss));
no_error ();
accept_signal (route_added);
/* Add route */
g_assert (!nm_platform_ip4_route_exists (ifindex, network, plen, metric));
no_error ();
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, network, plen, metric));
no_error ();
accept_signal (route_added);
/* Add route again */
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss));
no_error ();
accept_signal (route_changed);
/* Add default route */
g_assert (!nm_platform_ip4_route_exists (ifindex, 0, 0, metric));
no_error ();
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
no_error ();
g_assert (nm_platform_ip4_route_exists (ifindex, 0, 0, metric));
no_error ();
accept_signal (route_added);
/* Add default route again */
- g_assert (nm_platform_ip4_route_add (ifindex, NM_PLATFORM_SOURCE_USER, 0, 0, gateway, metric, mss));
+ g_assert (nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss));
no_error ();
accept_signal (route_changed);
/* Test route listing */
- routes = nm_platform_ip4_route_get_all (ifindex, TRUE);
+ routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
memset (rts, 0, sizeof (rts));
- rts[0].source = NM_PLATFORM_SOURCE_USER;
+ rts[0].source = NM_IP_CONFIG_SOURCE_USER;
rts[0].network = gateway;
rts[0].plen = 32;
rts[0].ifindex = ifindex;
rts[0].gateway = INADDR_ANY;
rts[0].metric = metric;
rts[0].mss = mss;
- rts[1].source = NM_PLATFORM_SOURCE_USER;
+ rts[1].source = NM_IP_CONFIG_SOURCE_USER;
rts[1].network = network;
rts[1].plen = plen;
rts[1].ifindex = ifindex;
rts[1].gateway = gateway;
rts[1].metric = metric;
rts[1].mss = mss;
- rts[2].source = NM_PLATFORM_SOURCE_USER;
+ rts[2].source = NM_IP_CONFIG_SOURCE_USER;
rts[2].network = 0;
rts[2].plen = 0;
rts[2].ifindex = ifindex;
@@ -143,7 +146,7 @@ test_ip4_route ()
}
static void
-test_ip6_route ()
+test_ip6_route (void)
{
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_route_callback);
@@ -154,63 +157,64 @@ test_ip6_route ()
struct in6_addr network;
int plen = 64;
struct in6_addr gateway;
- int metric = 20;
+ /* Choose a high metric so that we hopefully don't conflict. */
+ int metric = 22987;
int mss = 1000;
inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network);
inet_pton (AF_INET6, "2001:db8:c:d:1:2:3:4", &gateway);
/* Add route to gateway */
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, metric, mss));
no_error ();
accept_signal (route_added);
/* Add route */
g_assert (!nm_platform_ip6_route_exists (ifindex, network, plen, metric));
no_error ();
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, network, plen, metric));
no_error ();
accept_signal (route_added);
/* Add route again */
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, network, plen, gateway, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
/* Add default route */
g_assert (!nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric));
no_error ();
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
no_error ();
g_assert (nm_platform_ip6_route_exists (ifindex, in6addr_any, 0, metric));
no_error ();
accept_signal (route_added);
/* Add default route again */
- g_assert (nm_platform_ip6_route_add (ifindex, NM_PLATFORM_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
+ g_assert (nm_platform_ip6_route_add (ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, metric, mss));
no_error ();
accept_signal (route_changed);
/* Test route listing */
- routes = nm_platform_ip6_route_get_all (ifindex, TRUE);
+ routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
memset (rts, 0, sizeof (rts));
- rts[0].source = NM_PLATFORM_SOURCE_USER;
+ rts[0].source = NM_IP_CONFIG_SOURCE_USER;
rts[0].network = gateway;
rts[0].plen = 128;
rts[0].ifindex = ifindex;
rts[0].gateway = in6addr_any;
rts[0].metric = metric;
rts[0].mss = mss;
- rts[1].source = NM_PLATFORM_SOURCE_USER;
+ rts[1].source = NM_IP_CONFIG_SOURCE_USER;
rts[1].network = network;
rts[1].plen = plen;
rts[1].ifindex = ifindex;
rts[1].gateway = gateway;
rts[1].metric = metric;
rts[1].mss = mss;
- rts[2].source = NM_PLATFORM_SOURCE_USER;
+ rts[2].source = NM_IP_CONFIG_SOURCE_USER;
rts[2].network = in6addr_any;
rts[2].plen = 0;
rts[2].ifindex = ifindex;
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index 25ebd1b3c..752da926a 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -20,7 +20,8 @@
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*/
-#include <config.h>
+#include "config.h"
+
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
@@ -442,7 +443,7 @@ wifi_nl80211_get_ssid (WifiData *data)
}
static gboolean
-wifi_nl80211_get_bssid (WifiData *data, struct ether_addr *out_bssid)
+wifi_nl80211_get_bssid (WifiData *data, guint8 *out_bssid)
{
WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data;
struct nl80211_bss_info bss_info;
@@ -679,11 +680,20 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg)
static struct nla_policy freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
[NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
[NL80211_FREQUENCY_ATTR_DISABLED] = { .type = NLA_FLAG },
+#ifdef NL80211_FREQUENCY_ATTR_NO_IR
+ [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
+#else
[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
+#endif
[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
};
+#ifdef NL80211_FREQUENCY_ATTR_NO_IR
+ G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN == NL80211_FREQUENCY_ATTR_NO_IR && NL80211_FREQUENCY_ATTR_NO_IBSS == NL80211_FREQUENCY_ATTR_NO_IR);
+#else
+ G_STATIC_ASSERT (NL80211_FREQUENCY_ATTR_PASSIVE_SCAN != NL80211_FREQUENCY_ATTR_NO_IBSS);
+#endif
if (nla_parse (tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
genlmsg_attrlen (gnlh, 0), NULL) < 0)
@@ -924,48 +934,3 @@ error:
return NULL;
}
-gboolean
-wifi_nl80211_is_wifi (const char *iface)
-{
- struct nl_sock *nl_sock;
- struct nl_cb *nl_cb = NULL;
- struct nl_msg *msg = NULL;
- int id, ifindex;
- struct nl80211_iface_info iface_info = {
- .mode = NM_802_11_MODE_UNKNOWN,
- };
- gboolean is_wifi = FALSE;
-
- nl_sock = nl_socket_alloc ();
- if (nl_sock == NULL)
- return FALSE;
-
- if (genl_connect (nl_sock))
- goto error;
-
- ifindex = nm_platform_link_get_ifindex (iface);
- if (ifindex < 0)
- goto error;
-
- id = genl_ctrl_resolve (nl_sock, "nl80211");
- if (id < 0)
- goto error;
-
- nl_cb = nl_cb_alloc (NL_CB_DEFAULT);
- if (nl_cb) {
- msg = _nl80211_alloc_msg (id, ifindex, -1, NL80211_CMD_GET_INTERFACE, 0);
- if (_nl80211_send_and_recv (nl_sock,
- nl_cb,
- msg,
- nl80211_iface_info_handler,
- &iface_info) >= 0)
- is_wifi = (iface_info.mode != NM_802_11_MODE_UNKNOWN);
- }
-
- error:
- if (nl_cb)
- nl_cb_put (nl_cb);
- nl_socket_free (nl_sock);
- return is_wifi;
-}
-
diff --git a/src/platform/wifi/wifi-utils-nl80211.h b/src/platform/wifi/wifi-utils-nl80211.h
index 2a7fe874a..b3e8c8976 100644
--- a/src/platform/wifi/wifi-utils-nl80211.h
+++ b/src/platform/wifi/wifi-utils-nl80211.h
@@ -18,13 +18,11 @@
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*/
-#ifndef WIFI_UTILS_NL80211_H
-#define WIFI_UTILS_NL80211_H
+#ifndef __WIFI_UTILS_NL80211_H__
+#define __WIFI_UTILS_NL80211_H__
#include "wifi-utils.h"
WifiData *wifi_nl80211_init (const char *iface, int ifindex);
-gboolean wifi_nl80211_is_wifi (const char *iface);
-
-#endif /* WIFI_UTILS_NL80211_H */
+#endif /* __WIFI_UTILS_NL80211_H__ */
diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h
index e7601752d..aaedd5b7a 100644
--- a/src/platform/wifi/wifi-utils-private.h
+++ b/src/platform/wifi/wifi-utils-private.h
@@ -18,12 +18,12 @@
* Copyright (C) 2011 Red Hat, Inc.
*/
-#ifndef WIFI_UTILS_PRIVATE_H
-#define WIFI_UTILS_PRIVATE_H
+#ifndef __WIFI_UTILS_PRIVATE_H__
+#define __WIFI_UTILS_PRIVATE_H__
#include <glib.h>
-#include "NetworkManager.h"
+#include "nm-dbus-interface.h"
#include "wifi-utils.h"
struct WifiData {
@@ -47,7 +47,7 @@ struct WifiData {
/* Return current bitrate in Kbps */
guint32 (*get_rate) (WifiData *data);
- gboolean (*get_bssid) (WifiData *data, struct ether_addr *out_bssid);
+ gboolean (*get_bssid) (WifiData *data, guint8 *out_bssid);
/* Return a signal strength percentage 0 - 100% for the current BSSID;
* return -1 on errors or if not associated.
@@ -66,7 +66,7 @@ struct WifiData {
gboolean (*set_mesh_channel) (WifiData *data, guint32 channel);
/* ssid == NULL means "auto SSID" */
- gboolean (*set_mesh_ssid) (WifiData *data, const GByteArray *ssid);
+ gboolean (*set_mesh_ssid) (WifiData *data, const guint8 *ssid, gsize len);
gboolean (*indicate_addressing_running) (WifiData *data, gboolean running);
};
@@ -74,4 +74,4 @@ struct WifiData {
gpointer wifi_data_new (const char *iface, int ifindex, gsize len);
void wifi_data_free (WifiData *data);
-#endif /* WIFI_UTILS_PRIVATE_H */
+#endif /* __WIFI_UTILS_PRIVATE_H__ */
diff --git a/src/platform/wifi/wifi-utils-wext.c b/src/platform/wifi/wifi-utils-wext.c
index cc94b69a3..e0331de7c 100644
--- a/src/platform/wifi/wifi-utils-wext.c
+++ b/src/platform/wifi/wifi-utils-wext.c
@@ -19,7 +19,8 @@
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
-#include <config.h>
+#include "config.h"
+
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
@@ -41,7 +42,6 @@
#include <sys/types.h>
#include <linux/types.h>
#include <sys/socket.h>
-#include <linux/if.h>
#include <linux/wireless.h>
@@ -230,7 +230,7 @@ wifi_wext_get_ssid (WifiData *data)
}
static gboolean
-wifi_wext_get_bssid (WifiData *data, struct ether_addr *out_bssid)
+wifi_wext_get_bssid (WifiData *data, guint8 *out_bssid)
{
WifiDataWext *wext = (WifiDataWext *) data;
struct iwreq wrq;
@@ -243,7 +243,7 @@ wifi_wext_get_bssid (WifiData *data, struct ether_addr *out_bssid)
wext->parent.iface, strerror (errno));
return FALSE;
}
- memcpy (out_bssid->ether_addr_octet, &(wrq.u.ap_addr.sa_data), ETH_ALEN);
+ memcpy (out_bssid, &(wrq.u.ap_addr.sa_data), ETH_ALEN);
return TRUE;
}
@@ -421,18 +421,15 @@ wifi_wext_set_mesh_channel (WifiData *data, guint32 channel)
}
static gboolean
-wifi_wext_set_mesh_ssid (WifiData *data, const GByteArray *ssid)
+wifi_wext_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
{
WifiDataWext *wext = (WifiDataWext *) data;
struct iwreq wrq;
- guint32 len = 0;
char buf[IW_ESSID_MAX_SIZE + 1];
memset (buf, 0, sizeof (buf));
- if (ssid) {
- len = ssid->len;
- memcpy (buf, ssid->data, MIN (sizeof (buf) - 1, len));
- }
+ memcpy (buf, ssid, MIN (sizeof (buf) - 1, len));
+
wrq.u.essid.pointer = (caddr_t) buf;
wrq.u.essid.length = len;
wrq.u.essid.flags = (len > 0) ? 1 : 0; /* 1=enable SSID, 0=disable/any */
@@ -445,7 +442,7 @@ wifi_wext_set_mesh_ssid (WifiData *data, const GByteArray *ssid)
nm_log_err (LOGD_HW | LOGD_WIFI | LOGD_OLPC,
"(%s): error setting SSID to '%s': %s",
wext->parent.iface,
- ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(null)",
+ ssid ? nm_utils_escape_ssid (ssid, len) : "(null)",
strerror (errno));
}
diff --git a/src/platform/wifi/wifi-utils-wext.h b/src/platform/wifi/wifi-utils-wext.h
index 96ad74eb4..e168fe28a 100644
--- a/src/platform/wifi/wifi-utils-wext.h
+++ b/src/platform/wifi/wifi-utils-wext.h
@@ -18,8 +18,8 @@
* Copyright (C) 2011 Red Hat, Inc.
*/
-#ifndef WIFI_UTILS_WEXT_H
-#define WIFI_UTILS_WEXT_H
+#ifndef __WIFI_UTILS_WEXT_H__
+#define __WIFI_UTILS_WEXT_H__
#include "wifi-utils.h"
@@ -27,4 +27,4 @@ WifiData *wifi_wext_init (const char *iface, int ifindex, gboolean check_scan);
gboolean wifi_wext_is_wifi (const char *iface);
-#endif /* WIFI_UTILS_WEXT_H */
+#endif /* __WIFI_UTILS_WEXT_H__ */
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index ff4802752..daef881bf 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -19,7 +19,8 @@
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
-#include <config.h>
+#include "config.h"
+
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
@@ -120,12 +121,12 @@ wifi_utils_get_ssid (WifiData *data)
}
gboolean
-wifi_utils_get_bssid (WifiData *data, struct ether_addr *out_bssid)
+wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid)
{
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (out_bssid != NULL, FALSE);
- memset (out_bssid, 0, sizeof (*out_bssid));
+ memset (out_bssid, 0, ETH_ALEN);
return data->get_bssid (data, out_bssid);
}
@@ -161,13 +162,20 @@ wifi_utils_deinit (WifiData *data)
}
gboolean
-wifi_utils_is_wifi (const char *iface, const char *sysfs_path)
+wifi_utils_is_wifi (const char *iface, const char *sysfs_path, const char *devtype)
{
char phy80211_path[255];
struct stat s;
g_return_val_if_fail (iface != NULL, FALSE);
+ if (g_strcmp0 (devtype, "wlan") == 0) {
+ /* All Wi-Fi drivers should set DEVTYPE=wlan. Since the kernel's
+ * cfg80211/nl80211 stack does, this check should match any nl80211
+ * capable driver (including mac82011-based ones). */
+ return TRUE;
+ }
+
if (sysfs_path) {
/* Check for nl80211 sysfs paths */
g_snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", sysfs_path);
@@ -175,9 +183,6 @@ wifi_utils_is_wifi (const char *iface, const char *sysfs_path)
return TRUE;
}
- if (wifi_nl80211_is_wifi (iface))
- return TRUE;
-
#if HAVE_WEXT
if (wifi_wext_is_wifi (iface))
return TRUE;
@@ -207,11 +212,11 @@ wifi_utils_set_mesh_channel (WifiData *data, guint32 channel)
}
gboolean
-wifi_utils_set_mesh_ssid (WifiData *data, const GByteArray *ssid)
+wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len)
{
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (data->set_mesh_ssid != NULL, FALSE);
- return data->set_mesh_ssid (data, ssid);
+ return data->set_mesh_ssid (data, ssid, len);
}
gboolean
diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h
index 455e075f5..f1b57aced 100644
--- a/src/platform/wifi/wifi-utils.h
+++ b/src/platform/wifi/wifi-utils.h
@@ -19,17 +19,17 @@
* Copyright (C) 2006 - 2008 Novell, Inc.
*/
-#ifndef WIFI_UTILS_H
-#define WIFI_UTILS_H
+#ifndef __WIFI_UTILS_H__
+#define __WIFI_UTILS_H__
#include <net/ethernet.h>
#include <glib.h>
-#include "NetworkManager.h"
+#include "nm-dbus-interface.h"
typedef struct WifiData WifiData;
-gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path);
+gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path, const char *devtype);
WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan);
@@ -50,8 +50,8 @@ guint32 wifi_utils_find_freq (WifiData *data, const guint32 *freqs);
/* Caller must free returned byte array */
GByteArray *wifi_utils_get_ssid (WifiData *data);
-/* Caller must free returned byte array */
-gboolean wifi_utils_get_bssid (WifiData *data, struct ether_addr *out_bssid);
+/* out_bssid must be ETH_ALEN bytes */
+gboolean wifi_utils_get_bssid (WifiData *data, guint8 *out_bssid);
/* Returns current bitrate in Kbps */
guint32 wifi_utils_get_rate (WifiData *data);
@@ -71,6 +71,6 @@ guint32 wifi_utils_get_mesh_channel (WifiData *data);
gboolean wifi_utils_set_mesh_channel (WifiData *data, guint32 channel);
-gboolean wifi_utils_set_mesh_ssid (WifiData *data, const GByteArray *ssid);
+gboolean wifi_utils_set_mesh_ssid (WifiData *data, const guint8 *ssid, gsize len);
-#endif /* WIFI_UTILS_H */
+#endif /* __WIFI_UTILS_H__ */