summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-07-01 16:05:41 +0200
committerThomas Haller <thaller@redhat.com>2015-07-01 16:06:36 +0200
commit1749ad4068b27ab3955b35128c833096e7c195e4 (patch)
tree74efbca22ea2923d88fbada23a90d5d03b44f99a
parent871c4d90c7cfcb291874fbabcff000d0d2a691b2 (diff)
parent5f54a323d10d2907c6cb5cdcfe223e3cff33b317 (diff)
downloadNetworkManager-1749ad4068b27ab3955b35128c833096e7c195e4.tar.gz
core: merge branch 'th/device-route-bgo751264'
Several fixes to route and address handling in platform. Especially refactor managing of IPv4 device routes and let NMRouteManager handle them. https://bugzilla.gnome.org/show_bug.cgi?id=751264 https://bugzilla.redhat.com/show_bug.cgi?id=1211287
-rw-r--r--libnm-core/nm-core-internal.h2
-rw-r--r--libnm-core/nm-utils.c33
-rw-r--r--libnm-core/tests/test-general.c105
-rw-r--r--src/devices/nm-device.c16
-rw-r--r--src/nm-default-route-manager.c4
-rw-r--r--src/nm-ip4-config.c56
-rw-r--r--src/nm-ip4-config.h2
-rw-r--r--src/nm-ip6-config.c11
-rw-r--r--src/nm-route-manager.c288
-rw-r--r--src/nm-route-manager.h6
-rw-r--r--src/nm-types.h4
-rw-r--r--src/platform/nm-fake-platform.c30
-rw-r--r--src/platform/nm-linux-platform.c155
-rw-r--r--src/platform/nm-platform-utils.c88
-rw-r--r--src/platform/nm-platform-utils.h12
-rw-r--r--src/platform/nm-platform.c198
-rw-r--r--src/platform/nm-platform.h36
-rw-r--r--src/platform/nmp-object.c2
-rw-r--r--src/platform/tests/dump.c4
-rw-r--r--src/platform/tests/platform.c4
-rw-r--r--src/platform/tests/test-cleanup.c8
-rw-r--r--src/platform/tests/test-route.c4
-rw-r--r--src/tests/test-route-manager.c20
23 files changed, 761 insertions, 327 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index 27288df022..f9ae42ecdd 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -114,6 +114,8 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
gssize _nm_utils_ptrarray_find_first (gpointer *list, gssize len, gconstpointer needle);
+gssize _nm_utils_ptrarray_find_binary_search (gpointer *list, gsize len, gpointer needle, GCompareDataFunc cmpfcn, gpointer user_data);
+
gboolean _nm_utils_string_in_list (const char *str,
const char **valid_strings);
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 8ce59b0eeb..f9325e2a47 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -657,6 +657,39 @@ _nm_utils_ptrarray_find_first (gpointer *list, gssize len, gconstpointer needle)
return -1;
}
+gssize
+_nm_utils_ptrarray_find_binary_search (gpointer *list, gsize len, gpointer needle, GCompareDataFunc cmpfcn, gpointer user_data)
+{
+ gssize imin, imax, imid;
+ int cmp;
+
+ g_return_val_if_fail (list || !len, ~((gssize) 0));
+ g_return_val_if_fail (cmpfcn, ~((gssize) 0));
+
+ imin = 0;
+ if (len == 0)
+ return ~imin;
+
+ imax = len - 1;
+
+ while (imin <= imax) {
+ imid = imin + (imax - imin) / 2;
+
+ cmp = cmpfcn (list[imid], needle, user_data);
+ if (cmp == 0)
+ return imid;
+
+ if (cmp < 0)
+ imin = imid + 1;
+ else
+ imax = imid - 1;
+ }
+
+ /* return the inverse of @imin. This is a negative number, but
+ * also is ~imin the position where the value should be inserted. */
+ return ~imin;
+}
+
GVariant *
_nm_utils_bytes_to_dbus (const GValue *prop_value)
{
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 2f330357d6..082015c040 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -4484,6 +4484,110 @@ test_g_ptr_array_insert (void)
/******************************************************************************/
+static int
+_test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
+{
+ int ia, ib;
+
+ ia = GPOINTER_TO_INT (a);
+ ib = GPOINTER_TO_INT (b);
+
+ if (ia == ib)
+ return 0;
+ if (ia < ib)
+ return -1;
+ return 1;
+}
+
+static void
+_test_find_binary_search_do (const int *array, gsize len)
+{
+ gsize i;
+ gssize idx;
+ gs_free gpointer *parray = g_new (gpointer, len);
+ const int needle = 0;
+ gpointer pneedle = GINT_TO_POINTER (needle);
+ gssize expected_result;
+
+ for (i = 0; i < len; i++)
+ parray[i] = GINT_TO_POINTER (array[i]);
+
+ expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle);
+
+ idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL);
+ if (expected_result >= 0)
+ g_assert_cmpint (expected_result, ==, idx);
+ else {
+ gssize idx2 = ~idx;
+ g_assert_cmpint (idx, <, 0);
+
+ g_assert (idx2 >= 0);
+ g_assert (idx2 <= len);
+ g_assert (idx2 - 1 < 0 || _test_find_binary_search_cmp (parray[idx2 - 1], pneedle, NULL) < 0);
+ g_assert (idx2 >= len || _test_find_binary_search_cmp (parray[idx2], pneedle, NULL) > 0);
+ }
+ for (i = 0; i < len; i++) {
+ int cmp;
+
+ cmp = _test_find_binary_search_cmp (parray[i], pneedle, NULL);
+ if (cmp == 0) {
+ g_assert (pneedle == parray[i]);
+ g_assert (idx >= 0);
+ g_assert (i == idx);
+ } else {
+ g_assert (pneedle != parray[i]);
+ if (cmp < 0) {
+ if (idx < 0)
+ g_assert (i < ~idx);
+ else
+ g_assert (i < idx);
+ } else {
+ if (idx < 0)
+ g_assert (i >= ~idx);
+ else
+ g_assert (i >= idx);
+ }
+ }
+ }
+}
+#define test_find_binary_search_do(...) \
+ G_STMT_START { \
+ const int _array[] = { __VA_ARGS__ } ; \
+ _test_find_binary_search_do (_array, G_N_ELEMENTS (_array)); \
+ } G_STMT_END
+
+static void
+test_nm_utils_ptrarray_find_binary_search (void)
+{
+#define _NOT(idx) (~ ((gssize) (idx)))
+ test_find_binary_search_do ( 0);
+ test_find_binary_search_do ( -1, 0);
+ test_find_binary_search_do ( -2, -1, 0);
+ test_find_binary_search_do (-3, -2, -1, 0);
+ test_find_binary_search_do ( 0, 1);
+ test_find_binary_search_do ( 0, 1, 2);
+ test_find_binary_search_do ( -1, 0, 1, 2);
+ test_find_binary_search_do ( -2, -1, 0, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3);
+ test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3, 4);
+
+ test_find_binary_search_do ( -1);
+ test_find_binary_search_do ( -2, -1);
+ test_find_binary_search_do (-3, -2, -1);
+ test_find_binary_search_do ( 1);
+ test_find_binary_search_do ( 1, 2);
+ test_find_binary_search_do ( -1, 1, 2);
+ test_find_binary_search_do ( -2, -1, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 1, 2);
+ test_find_binary_search_do (-3, -2, -1, 1, 2, 3);
+ test_find_binary_search_do (-3, -2, -1, 1, 2, 3, 4);
+}
+
+/******************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -4587,6 +4691,7 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
+ g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 9a70bc6f53..a317ca6ac8 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -3114,9 +3114,9 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat
GArray *routes;
if (addr_family == AF_INET)
- routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
+ routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT);
else
- routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
+ routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT);
if (routes) {
guint route_metric = G_MAXUINT32, m;
@@ -6345,10 +6345,11 @@ nm_device_set_ip4_config (NMDevice *self,
nm_device_set_mtu (self, nm_ip4_config_get_mtu (new_config));
- /* for assumed devices we set the device_route_metric to the default which will
- * stop nm_platform_ip4_address_sync() to replace the device routes. */
+ /* For assumed devices we must not touch the kernel-routes, such as the device-route.
+ * FIXME: this is wrong in case where "assumed" means "take-over-seamlessly". In this
+ * case, we should manage the device route, for example on new DHCP lease. */
success = nm_ip4_config_commit (new_config, ip_ifindex,
- assumed ? NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE : default_route_metric);
+ assumed ? (gint64) -1 : (gint64) default_route_metric);
if (!success)
reason_local = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
}
@@ -7174,6 +7175,11 @@ update_ip4_config (NMDevice *self, gboolean initial)
capture_lease_config (self, priv->ext_ip4_config, &priv->dev_ip4_config, NULL, NULL);
}
+ /* FIXME: ext_ip4_config does not contain routes with source==RTPROT_KERNEL.
+ * Hence, we will wrongly remove device-routes with metric=0 if they were added by
+ * the user on purpose. This should be fixed by also tracking and exposing
+ * kernel routes. */
+
/* This function was called upon external changes. Remove the configuration
* (addresses,routes) that is no longer present externally from the internal
* config. This way, we don't re-add addresses that were manually removed
diff --git a/src/nm-default-route-manager.c b/src/nm-default-route-manager.c
index e28d92f652..8107ae9274 100644
--- a/src/nm-default-route-manager.c
+++ b/src/nm-default-route-manager.c
@@ -292,7 +292,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
gboolean changed = FALSE;
/* prune all other default routes from this device. */
- routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
+ routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT);
for (i = 0; i < routes->len; i++) {
const NMPlatformIPRoute *route;
@@ -478,7 +478,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
entries = vtable->get_entries (priv);
- routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
+ routes = vtable->vt->route_get_all (NM_PLATFORM_GET, 0, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT);
assumed_metrics = _get_assumed_interface_metrics (vtable, self, routes);
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index a3ef072b90..c811e24d34 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -35,6 +35,7 @@
#include "nm-core-internal.h"
#include "nm-route-manager.h"
#include "nm-core-internal.h"
+#include "gsystem-local-alloc.h"
G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT)
@@ -229,11 +230,11 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
g_array_unref (priv->routes);
priv->addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
- priv->routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ priv->routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
/* Extract gateway from default route */
old_gateway = priv->gateway;
- for (i = 0; i < priv->routes->len; i++) {
+ for (i = 0; i < priv->routes->len; ) {
const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
@@ -243,9 +244,10 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
}
has_gateway = TRUE;
/* Remove the default route from the list */
- g_array_remove_index (priv->routes, i);
- i--;
+ g_array_remove_index_fast (priv->routes, i);
+ continue;
}
+ i++;
}
/* we detect the route metric based on the default route. All non-default
@@ -288,25 +290,59 @@ nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
}
gboolean
-nm_ip4_config_commit (const NMIP4Config *config, int ifindex, guint32 default_route_metric)
+nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric)
{
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
int i;
+ gs_unref_ptrarray GPtrArray *added_addresses = NULL;
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (config != NULL, FALSE);
/* Addresses */
- nm_platform_ip4_address_sync (NM_PLATFORM_GET, ifindex, priv->addresses, default_route_metric);
+ nm_platform_ip4_address_sync (NM_PLATFORM_GET, ifindex, priv->addresses,
+ default_route_metric >= 0 ? &added_addresses : NULL);
/* Routes */
{
int count = nm_ip4_config_get_num_routes (config);
GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count);
- const NMPlatformIP4Route *route;
gboolean success;
+ gs_unref_array GArray *device_route_purge_list = NULL;
+
+ if ( default_route_metric >= 0
+ && added_addresses) {
+ /* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
+ * As we don't do that for IPv4, add it here shortly before syncing
+ * the routes. For NMRouteManager these routes are very much important. */
+ for (i = 0; i < added_addresses->len; i++) {
+ const NMPlatformIP4Address *addr = added_addresses->pdata[i];
+ NMPlatformIP4Route route = { 0 };
+
+ if (addr->plen == 0)
+ continue;
+
+ route.ifindex = ifindex;
+ route.source = NM_IP_CONFIG_SOURCE_KERNEL;
+ route.network = nm_utils_ip4_address_clear_host_address (addr->address, addr->plen);
+ route.plen = addr->plen;
+ route.pref_src = addr->address;
+ route.metric = default_route_metric;
+
+ g_array_append_val (routes, route);
+
+ if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
+ if (!device_route_purge_list)
+ device_route_purge_list = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
+ route.metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
+ g_array_append_val (device_route_purge_list, route);
+ }
+ }
+ }
for (i = 0; i < count; i++) {
+ const NMPlatformIP4Route *route;
+
route = nm_ip4_config_get_route (config, i);
/* Don't add the route if it's more specific than one of the subnets
@@ -316,10 +352,14 @@ nm_ip4_config_commit (const NMIP4Config *config, int ifindex, guint32 default_ro
&& nm_ip4_config_destination_is_direct (config, route->network, route->plen))
continue;
+ /* duplicates in @routes are no problem as route-manager handles them
+ * gracefully (by ignoring them). */
g_array_append_vals (routes, route, 1);
}
- success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip4_route_register_device_route_purge_list (nm_route_manager_get (), device_route_purge_list);
+
+ success = nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, default_route_metric < 0);
g_array_unref (routes);
if (!success)
return FALSE;
diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h
index 69880c1322..0088934a45 100644
--- a/src/nm-ip4-config.h
+++ b/src/nm-ip4-config.h
@@ -71,7 +71,7 @@ const char * nm_ip4_config_get_dbus_path (const NMIP4Config *config);
/* Integration with nm-platform and nm-setting */
NMIP4Config *nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf);
-gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, guint32 default_route_metric);
+gboolean nm_ip4_config_commit (const NMIP4Config *config, int ifindex, gint64 default_route_metric);
void nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIPConfig *setting, guint32 default_route_metric);
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *config);
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index dcb318b7e3..082f1d2db7 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -342,11 +342,11 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
g_array_unref (priv->routes);
priv->addresses = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
- priv->routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ priv->routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
/* Extract gateway from default route */
old_gateway = priv->gateway;
- for (i = 0; i < priv->routes->len; i++) {
+ for (i = 0; i < priv->routes->len; ) {
const NMPlatformIP6Route *route = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
@@ -356,9 +356,10 @@ nm_ip6_config_capture (int ifindex, gboolean capture_resolv_conf, NMSettingIP6Co
}
has_gateway = TRUE;
/* Remove the default route from the list */
- g_array_remove_index (priv->routes, i);
- i--;
+ g_array_remove_index_fast (priv->routes, i);
+ continue;
}
+ i++;
}
/* we detect the route metric based on the default route. All non-default
@@ -436,7 +437,7 @@ nm_ip6_config_commit (const NMIP6Config *config, int ifindex)
g_array_append_vals (routes, route, 1);
}
- success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes);
+ success = nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_unref (routes);
}
diff --git a/src/nm-route-manager.c b/src/nm-route-manager.c
index 3e1d5b5bd8..5afce85489 100644
--- a/src/nm-route-manager.c
+++ b/src/nm-route-manager.c
@@ -24,10 +24,18 @@
#include "nm-route-manager.h"
#include "nm-platform.h"
+#include "nmp-object.h"
+#include "nm-core-internal.h"
#include "nm-logging.h"
#include "gsystem-local-alloc.h"
#include "NetworkManagerUtils.h"
+/* if within half a second after adding an IP address a matching device-route shows
+ * up, we delete it. */
+#define IP4_DEVICE_ROUTES_WAIT_TIME_NS (NM_UTILS_NS_PER_SECOND / 2)
+
+#define IP4_DEVICE_ROUTES_GC_INTERVAL_SEC (IP4_DEVICE_ROUTES_WAIT_TIME_NS * 2)
+
typedef struct {
guint len;
NMPlatformIPXRoute *entries[1];
@@ -39,8 +47,21 @@ typedef struct {
} RouteEntries;
typedef struct {
+ NMRouteManager *self;
+ gint64 scheduled_at_ns;
+ guint idle_id;
+ NMPObject *obj;
+} IP4DeviceRoutePurgeEntry;
+
+typedef struct {
+ NMPlatform *platform;
+
RouteEntries ip4_routes;
RouteEntries ip6_routes;
+ struct {
+ GHashTable *entries;
+ guint gc_id;
+ } ip4_device_routes;
} NMRouteManagerPrivate;
#define NM_ROUTE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ROUTE_MANAGER, NMRouteManagerPrivate))
@@ -123,6 +144,10 @@ static const VTableIP vtable_v4, vtable_v6;
/*********************************************************************************************/
+static gboolean _ip4_device_routes_cancel (NMRouteManager *self);
+
+/*********************************************************************************************/
+
#if defined (NM_MORE_ASSERTS) && !defined (G_DISABLE_ASSERT)
inline static void
ASSERT_route_index_valid (const VTableIP *vtable, const GArray *entries, const RouteIndex *index, gboolean unique_ifindexes)
@@ -232,6 +257,41 @@ _route_index_create (const VTableIP *vtable, const GArray *routes)
return index;
}
+static int
+_vx_route_id_cmp_full (const NMPlatformIPXRoute *r1, const NMPlatformIPXRoute *r2, const VTableIP *vtable)
+{
+ return vtable->route_id_cmp (r1, r2);
+}
+
+static gssize
+_route_index_find (const VTableIP *vtable, const RouteIndex *index, const NMPlatformIPXRoute *needle)
+{
+ gssize idx, idx2;
+
+ idx = _nm_utils_ptrarray_find_binary_search ((gpointer *) index->entries, index->len, (gpointer) needle, (GCompareDataFunc) _vx_route_id_cmp_full, (gpointer) vtable);
+ if (idx < 0)
+ return idx;
+
+ /* we only know that the route at index @idx has matching destination. Also find the one with the right
+ * ifindex by searching the neighbours */
+
+ idx2 = idx;
+ do {
+ if (index->entries[idx2]->rx.ifindex == needle->rx.ifindex)
+ return idx2;
+ } while ( idx2 > 0
+ && vtable->route_id_cmp (index->entries[--idx2], needle) != 0);
+
+ for (idx++; idx < index->len; idx++ ){
+ if (vtable->route_id_cmp (index->entries[idx], needle) != 0)
+ break;
+ if (index->entries[idx]->rx.ifindex == needle->rx.ifindex)
+ return idx;
+ }
+
+ return ~idx;
+}
+
static guint
_route_index_reverse_idx (const VTableIP *vtable, const RouteIndex *index, guint idx_idx, const GArray *routes)
{
@@ -343,7 +403,7 @@ _sort_indexes_cmp (guint *a, guint *b)
/*********************************************************************************************/
static gboolean
-_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes)
+_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes)
{
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
GArray *plat_routes;
@@ -357,8 +417,13 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
const NMPlatformIPXRoute *cur_known_route, *cur_plat_route;
NMPlatformIPXRoute *cur_ipx_route;
+ nm_platform_process_events (priv->platform);
+
ipx_routes = vtable->vt->is_ip4 ? &priv->ip4_routes : &priv->ip6_routes;
- plat_routes = vtable->vt->route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
+ plat_routes = vtable->vt->route_get_all (priv->platform, ifindex,
+ ignore_kernel_routes
+ ? NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT
+ : NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
plat_routes_idx = _route_index_create (vtable, plat_routes);
known_routes_idx = _route_index_create (vtable, known_routes);
@@ -494,7 +559,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
/* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */
if (!(cur_ipx_route && route_id_cmp_result == 0))
- vtable->vt->route_delete (NM_PLATFORM_GET, ifindex, cur_plat_route);
+ vtable->vt->route_delete (priv->platform, ifindex, cur_plat_route);
cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes);
}
@@ -515,7 +580,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
* device routes, on the second the others (gateway routes). */
continue;
}
- vtable->vt->route_add (NM_PLATFORM_GET, 0, rest_route, 0);
+ vtable->vt->route_add (priv->platform, 0, rest_route);
}
}
g_array_unref (to_restore_routes);
@@ -559,7 +624,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
|| route_id_cmp_result != 0
|| !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route)) {
- if (!vtable->vt->route_add (NM_PLATFORM_GET, ifindex, cur_ipx_route, 0)) {
+ if (!vtable->vt->route_add (priv->platform, ifindex, cur_ipx_route)) {
if (cur_ipx_route->rx.source < NM_IP_CONFIG_SOURCE_USER) {
_LOGD (vtable->vt->addr_family,
"ignore error adding IPv%c route to kernel: %s",
@@ -586,6 +651,7 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
* nm_route_manager_ip4_route_sync:
* @ifindex: Interface index
* @known_routes: List of routes
+ * @ignore_kernel_routes: if %TRUE, ignore kernel routes.
*
* A convenience function to synchronize routes for a specific interface
* with the least possible disturbance. It simply removes routes that are
@@ -596,15 +662,16 @@ _vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const
* Returns: %TRUE on success.
*/
gboolean
-nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes)
+nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes)
{
- return _vx_route_sync (&vtable_v4, self, ifindex, known_routes);
+ return _vx_route_sync (&vtable_v4, self, ifindex, known_routes, ignore_kernel_routes);
}
/**
* nm_route_manager_ip6_route_sync:
* @ifindex: Interface index
* @known_routes: List of routes
+ * @ignore_kernel_routes: if %TRUE, ignore kernel routes.
*
* A convenience function to synchronize routes for a specific interface
* with the least possible disturbance. It simply removes routes that are
@@ -615,16 +682,192 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray
* Returns: %TRUE on success.
*/
gboolean
-nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes)
+nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes)
{
- return _vx_route_sync (&vtable_v6, self, ifindex, known_routes);
+ return _vx_route_sync (&vtable_v6, self, ifindex, known_routes, ignore_kernel_routes);
}
gboolean
nm_route_manager_route_flush (NMRouteManager *self, int ifindex)
{
- return nm_route_manager_ip4_route_sync (self, ifindex, NULL)
- && nm_route_manager_ip6_route_sync (self, ifindex, NULL);
+ return nm_route_manager_ip4_route_sync (self, ifindex, NULL, FALSE)
+ && nm_route_manager_ip6_route_sync (self, ifindex, NULL, FALSE);
+}
+
+/*********************************************************************************************/
+
+static gboolean
+_ip4_device_routes_entry_expired (const IP4DeviceRoutePurgeEntry *entry, gint64 now)
+{
+ return entry->scheduled_at_ns + IP4_DEVICE_ROUTES_WAIT_TIME_NS < now;
+}
+
+static IP4DeviceRoutePurgeEntry *
+_ip4_device_routes_purge_entry_create (NMRouteManager *self, const NMPlatformIP4Route *route, gint64 now_ns)
+{
+ IP4DeviceRoutePurgeEntry *entry;
+
+ entry = g_slice_new (IP4DeviceRoutePurgeEntry);
+
+ entry->self = self;
+ entry->scheduled_at_ns = now_ns;
+ entry->idle_id = 0;
+ entry->obj = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, (NMPlatformObject *) route);
+ return entry;
+}
+
+static void
+_ip4_device_routes_purge_entry_free (IP4DeviceRoutePurgeEntry *entry)
+{
+ nmp_object_unref (entry->obj);
+ nm_clear_g_source (&entry->idle_id);
+ g_slice_free (IP4DeviceRoutePurgeEntry, entry);
+}
+
+static gboolean
+_ip4_device_routes_idle_cb (IP4DeviceRoutePurgeEntry *entry)
+{
+ NMRouteManager *self;
+ NMRouteManagerPrivate *priv;
+
+ nm_clear_g_source (&entry->idle_id);
+
+ self = entry->self;
+ priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+ if (_route_index_find (&vtable_v4, priv->ip4_routes.index, &entry->obj->ipx_route) >= 0) {
+ /* we have an identical route in our list. Don't delete it. */
+ return G_SOURCE_REMOVE;
+ }
+
+ _LOGT (vtable_v4.vt->addr_family, "device-route: delete %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+
+ nm_platform_ip4_route_delete (priv->platform,
+ entry->obj->ip4_route.ifindex,
+ entry->obj->ip4_route.network,
+ entry->obj->ip4_route.plen,
+ entry->obj->ip4_route.metric);
+
+ g_hash_table_remove (priv->ip4_device_routes.entries, entry->obj);
+ _ip4_device_routes_cancel (self);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+_ip4_device_routes_ip4_route_changed (NMPlatform *platform,
+ NMPObjectType obj_type,
+ int ifindex,
+ const NMPlatformIP4Route *route,
+ NMPlatformSignalChangeType change_type,
+ NMPlatformReason reason,
+ NMRouteManager *self)
+{
+ NMRouteManagerPrivate *priv;
+ NMPObject obj_needle;
+ IP4DeviceRoutePurgeEntry *entry;
+
+ if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
+ return;
+
+ if ( route->source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
+ || route->metric != 0) {
+ /* we don't have an automatically created device route at hand. Bail out early. */
+ return;
+ }
+
+ priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+
+ entry = g_hash_table_lookup (priv->ip4_device_routes.entries,
+ nmp_object_stackinit (&obj_needle, NMP_OBJECT_TYPE_IP4_ROUTE, (NMPlatformObject *) route));
+ if (!entry)
+ return;
+
+ if (_ip4_device_routes_entry_expired (entry, nm_utils_get_monotonic_timestamp_ns ())) {
+ _LOGT (vtable_v4.vt->addr_family, "device-route: cleanup-ch %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ g_hash_table_remove (priv->ip4_device_routes.entries, entry->obj);
+ _ip4_device_routes_cancel (self);
+ return;
+ }
+
+ if (entry->idle_id == 0) {
+ _LOGT (vtable_v4.vt->addr_family, "device-route: schedule %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ entry->idle_id = g_idle_add ((GSourceFunc) _ip4_device_routes_idle_cb, entry);
+ }
+}
+
+static gboolean
+_ip4_device_routes_cancel (NMRouteManager *self)
+{
+ NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+
+ if (priv->ip4_device_routes.gc_id) {
+ if (g_hash_table_size (priv->ip4_device_routes.entries) > 0)
+ return G_SOURCE_CONTINUE;
+ _LOGT (vtable_v4.vt->addr_family, "device-route: cancel");
+ if (priv->platform)
+ g_signal_handlers_disconnect_by_func (priv->platform, G_CALLBACK (_ip4_device_routes_ip4_route_changed), self);
+ nm_clear_g_source (&priv->ip4_device_routes.gc_id);
+ }
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+_ip4_device_routes_gc (NMRouteManager *self)
+{
+ NMRouteManagerPrivate *priv;
+ GHashTableIter iter;
+ IP4DeviceRoutePurgeEntry *entry;
+ gint64 now = nm_utils_get_monotonic_timestamp_ns ();
+
+ priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+
+ g_hash_table_iter_init (&iter, priv->ip4_device_routes.entries);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &entry)) {
+ if (_ip4_device_routes_entry_expired (entry, now)) {
+ _LOGT (vtable_v4.vt->addr_family, "device-route: cleanup-gc %s", nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ g_hash_table_iter_remove (&iter);
+ }
+ }
+
+ return _ip4_device_routes_cancel (self);
+}
+
+/**
+ * nm_route_manager_ip4_route_register_device_route_purge_list:
+ *
+ * When adding an IPv4 address, kernel will automatically add a device route with
+ * metric zero. We don't want that route and want to delete it. However, the route
+ * by kernel immediately, but some time after. That means during nm_route_manager_ip4_route_sync()
+ * such a route doesn't exist yet. We must remember that we expect such a route to appear later
+ * and to remove it. */
+void
+nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list)
+{
+ NMRouteManagerPrivate *priv;
+ guint i;
+ gint64 now_ns;
+
+ if (!device_route_purge_list || device_route_purge_list->len == 0)
+ return;
+
+ priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+
+ now_ns = nm_utils_get_monotonic_timestamp_ns ();
+ for (i = 0; i < device_route_purge_list->len; i++) {
+ IP4DeviceRoutePurgeEntry *entry;
+
+ entry = _ip4_device_routes_purge_entry_create (self, &g_array_index (device_route_purge_list, NMPlatformIP4Route, i), now_ns);
+ _LOGT (vtable_v4.vt->addr_family, "device-route: watch (%s) %s",
+ g_hash_table_contains (priv->ip4_device_routes.entries, entry->obj)
+ ? "update" : "new",
+ nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
+ g_hash_table_replace (priv->ip4_device_routes.entries,
+ nmp_object_ref (entry->obj),
+ entry);
+ }
+ if (priv->ip4_device_routes.gc_id == 0) {
+ g_signal_connect (priv->platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_ip4_device_routes_ip4_route_changed), self);
+ priv->ip4_device_routes.gc_id = g_timeout_add (IP4_DEVICE_ROUTES_GC_INTERVAL_SEC, (GSourceFunc) _ip4_device_routes_gc, self);
+ }
}
/*********************************************************************************************/
@@ -646,10 +889,30 @@ nm_route_manager_init (NMRouteManager *self)
{
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
+ priv->platform = g_object_ref (NM_PLATFORM_GET);
+
priv->ip4_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
priv->ip6_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
priv->ip4_routes.index = _route_index_create (&vtable_v4, priv->ip4_routes.entries);
priv->ip6_routes.index = _route_index_create (&vtable_v6, priv->ip6_routes.entries);
+ priv->ip4_device_routes.entries = g_hash_table_new_full ((GHashFunc) nmp_object_id_hash,
+ (GEqualFunc) nmp_object_id_equal,
+ (GDestroyNotify) nmp_object_unref,
+ (GDestroyNotify) _ip4_device_routes_purge_entry_free);
+}
+
+static void
+dispose (GObject *object)
+{
+ NMRouteManager *self = NM_ROUTE_MANAGER (object);
+ NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (object);
+
+ g_hash_table_remove_all (priv->ip4_device_routes.entries);
+ _ip4_device_routes_cancel (self);
+
+ g_clear_object (&priv->platform);
+
+ G_OBJECT_CLASS (nm_route_manager_parent_class)->dispose (object);
}
static void
@@ -662,6 +925,8 @@ finalize (GObject *object)
g_free (priv->ip4_routes.index);
g_free (priv->ip6_routes.index);
+ g_hash_table_unref (priv->ip4_device_routes.entries);
+
G_OBJECT_CLASS (nm_route_manager_parent_class)->finalize (object);
}
@@ -673,5 +938,6 @@ nm_route_manager_class_init (NMRouteManagerClass *klass)
g_type_class_add_private (klass, sizeof (NMRouteManagerPrivate));
/* virtual methods */
+ object_class->dispose = dispose;
object_class->finalize = finalize;
}
diff --git a/src/nm-route-manager.h b/src/nm-route-manager.h
index 4c66ffcd94..fdd310b73b 100644
--- a/src/nm-route-manager.h
+++ b/src/nm-route-manager.h
@@ -42,10 +42,12 @@ typedef struct {
GType nm_route_manager_get_type (void);
-gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes);
-gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes);
+gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes);
+gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes);
gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex);
+void nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *self, GArray *device_route_purge_list);
+
NMRouteManager *nm_route_manager_get (void);
#endif /* NM_ROUTE_MANAGER_H */
diff --git a/src/nm-types.h b/src/nm-types.h
index 426aba5a27..530f9f7b5b 100644
--- a/src/nm-types.h
+++ b/src/nm-types.h
@@ -55,8 +55,8 @@ typedef enum {
/* platform internal flag used to mark routes with RTM_F_CLONED. */
_NM_IP_CONFIG_SOURCE_RTM_F_CLONED,
- /* platform internal flag used to mark routes with protocol RTPROT_KERNEL. */
- _NM_IP_CONFIG_SOURCE_RTPROT_KERNEL,
+ /* routes from platform with protocol RTPROT_KERNEL. */
+ NM_IP_CONFIG_SOURCE_RTPROT_KERNEL,
NM_IP_CONFIG_SOURCE_KERNEL,
NM_IP_CONFIG_SOURCE_SHARED,
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 96fd17b716..147e956167 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -1025,35 +1025,30 @@ 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, NMPlatformGetRouteMode mode)
+ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP4Route *route;
guint i;
- 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 (TRUE, TRUE, sizeof (NMPlatformIP4Route));
+ if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
+ flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
+
/* Fill routes */
for (i = 0; i < priv->ip4_routes->len; i++) {
route = &g_array_index (priv->ip4_routes, NMPlatformIP4Route, i);
if (route && (!ifindex || route->ifindex == ifindex)) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
- if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT))
g_array_append_val (routes, *route);
} else {
- if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
g_array_append_val (routes, *route);
}
}
@@ -1063,26 +1058,27 @@ ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mod
}
static GArray *
-ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
+ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
GArray *routes;
NMPlatformIP6Route *route;
guint i;
- 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 (TRUE, TRUE, sizeof (NMPlatformIP6Route));
+ if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
+ flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
+
/* Fill routes */
for (i = 0; i < priv->ip6_routes->len; i++) {
route = &g_array_index (priv->ip6_routes, NMPlatformIP6Route, i);
if (route && (!ifindex || route->ifindex == ifindex)) {
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) {
- if (mode != NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
+ if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT))
g_array_append_val (routes, *route);
} else {
- if (mode != NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
+ if (NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
g_array_append_val (routes, *route);
}
}
@@ -1466,8 +1462,6 @@ 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-linux-platform.c b/src/platform/nm-linux-platform.c
index 4f12596bd0..9642484513 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -597,7 +597,7 @@ _nm_ip_config_source_to_rtprot (NMIPConfigSource source)
case NM_IP_CONFIG_SOURCE_UNKNOWN:
return RTPROT_UNSPEC;
case NM_IP_CONFIG_SOURCE_KERNEL:
- case _NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
+ case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
@@ -616,7 +616,7 @@ _nm_ip_config_source_from_rtprot (guint rtprot)
case RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
case RTPROT_KERNEL:
- return _NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
+ return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
case RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
case RTPROT_RA:
@@ -1289,6 +1289,7 @@ _nmp_vt_cmd_plobj_init_from_nl_ip4_route (NMPlatform *platform, NMPlatformObject
struct rtnl_route *nlo = (struct rtnl_route *) _nlo;
struct nl_addr *dst, *gw;
struct rtnl_nexthop *nexthop;
+ struct nl_addr *pref_src;
if (rtnl_route_get_type (nlo) != RTN_UNICAST ||
rtnl_route_get_table (nlo) != RT_TABLE_MAIN ||
@@ -1334,6 +1335,14 @@ _nmp_vt_cmd_plobj_init_from_nl_ip4_route (NMPlatform *platform, NMPlatformObject
} else
obj->source = _nm_ip_config_source_from_rtprot (rtnl_route_get_protocol (nlo));
+ pref_src = rtnl_route_get_pref_src (nlo);
+ if (pref_src) {
+ if (nl_addr_get_len (pref_src) != sizeof (obj->pref_src))
+ g_warn_if_reached ();
+ else
+ memcpy (&obj->pref_src, nl_addr_get_binary_addr (pref_src), sizeof (obj->pref_src));
+ }
+
return TRUE;
}
@@ -4022,13 +4031,9 @@ build_rtnl_addr (NMPlatform *platform,
}
_nl_rtnl_addr_set_prefixlen (rtnladdr, plen);
- if (lifetime) {
- /* note that here we set the relative timestamps (ticking from *now*).
- * Contrary to the rtnl_addr objects from our cache, which have absolute
- * timestamps (see _rtnl_addr_hack_lifetimes_rel_to_abs()).
- *
- * This is correct, because we only use build_rtnl_addr() for
- * add_object(), delete_object() and cache search (ip_address_exists). */
+ if ( lifetime != 0 || lifetime != NM_PLATFORM_LIFETIME_PERMANENT
+ || preferred != 0 || preferred != NM_PLATFORM_LIFETIME_PERMANENT) {
+ /* note that here we set the relative timestamps (ticking from *now*). */
rtnl_addr_set_valid_lifetime (rtnladdr, lifetime);
rtnl_addr_set_preferred_lifetime (rtnladdr, preferred);
}
@@ -4057,6 +4062,10 @@ struct nl_object *
_nmp_vt_cmd_plobj_to_nl_ip4_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only)
{
const NMPlatformIP4Address *obj = (const NMPlatformIP4Address *) _obj;
+ guint32 lifetime, preferred;
+
+ nmp_utils_lifetime_get (obj->timestamp, obj->lifetime, obj->preferred,
+ 0, 0, &lifetime, &preferred);
return build_rtnl_addr (platform,
AF_INET,
@@ -4064,8 +4073,8 @@ _nmp_vt_cmd_plobj_to_nl_ip4_address (NMPlatform *platform, const NMPlatformObjec
&obj->address,
obj->peer_address ? &obj->peer_address : NULL,
obj->plen,
- obj->lifetime,
- obj->preferred,
+ lifetime,
+ preferred,
0,
obj->label[0] ? obj->label : NULL);
}
@@ -4074,6 +4083,10 @@ struct nl_object *
_nmp_vt_cmd_plobj_to_nl_ip6_address (NMPlatform *platform, const NMPlatformObject *_obj, gboolean id_only)
{
const NMPlatformIP6Address *obj = (const NMPlatformIP6Address *) _obj;
+ guint32 lifetime, preferred;
+
+ nmp_utils_lifetime_get (obj->timestamp, obj->lifetime, obj->preferred,
+ 0, 0, &lifetime, &preferred);
return build_rtnl_addr (platform,
AF_INET6,
@@ -4081,8 +4094,8 @@ _nmp_vt_cmd_plobj_to_nl_ip6_address (NMPlatform *platform, const NMPlatformObjec
&obj->address,
!IN6_IS_ADDR_UNSPECIFIED (&obj->peer_address) ? &obj->peer_address : NULL,
obj->plen,
- obj->lifetime,
- obj->preferred,
+ lifetime,
+ preferred,
0,
NULL);
}
@@ -4168,103 +4181,57 @@ ip6_address_exists (NMPlatform *platform, int ifindex, struct in6_addr addr, int
return nmp_object_is_visible (nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_needle));
}
-static gboolean
-ip4_check_reinstall_device_route (NMPlatform *platform, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
+/******************************************************************/
+
+static GArray *
+ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteFlags flags)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
- guint32 device_network;
- NMPObject obj_needle;
- const NMPlatformIP4Address *const *addresses;
- const NMPlatformIP4Route *const *routes;
-
- device_network = nm_utils_ip4_address_clear_host_address (address->address, address->plen);
-
- /* in many cases we expect the route to already exist. So first do an exact lookup
- * to save the O(n) access below. */
- nmp_object_stackinit_id_ip4_route (&obj_needle, ifindex, device_network, address->plen, device_route_metric);
- if (nmp_cache_lookup_obj (priv->cache, &obj_needle)) {
- /* There is already a route with metric 0 or the metric we want to install
- * for the same subnet. */
- return FALSE;
- }
- if (obj_needle.ip4_route.metric != 0) {
- obj_needle.ip4_route.metric = 0;
- if (nmp_cache_lookup_obj (priv->cache, &obj_needle))
- return FALSE;
- }
+ NMPCacheId cache_id;
+ const NMPlatformIPRoute *const* routes;
+ GArray *array;
+ const NMPClass *klass;
+ gboolean with_rtprot_kernel;
+ guint i, len;
- /* also check whether we already have the same address configured on *any* device. */
- addresses = cache_lookup_all_objects (NMPlatformIP4Address, platform, NMP_OBJECT_TYPE_IP4_ADDRESS, FALSE);
- if (addresses) {
- for (; *addresses; addresses++) {
- const NMPlatformIP4Address *addr_candidate = *addresses;
-
- if ( addr_candidate->plen == address->plen
- && addr_candidate->address == device_network) {
- /* If we already have the same address installed on any interface,
- * we back off. */
- return FALSE;
- }
- }
- }
+ nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
- routes = cache_lookup_all_objects (NMPlatformIP4Route, platform, NMP_OBJECT_TYPE_IP4_ROUTE, FALSE);
- if (routes) {
- for (; *routes; routes++) {
- const NMPlatformIP4Route *route_candidate = *routes;
-
- if ( route_candidate->network == device_network
- && route_candidate->plen == address->plen
- && (route_candidate->metric == 0 || route_candidate->metric == device_route_metric)) {
- /* If we already have the same address installed on any interface,
- * we back off. */
- return FALSE;
- }
- }
- }
+ if (!NM_FLAGS_ANY (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT))
+ flags |= NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT;
- return TRUE;
-}
+ klass = nmp_class_from_type (obj_type);
-/******************************************************************/
+ nmp_cache_id_init_routes_visible (&cache_id,
+ obj_type,
+ NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT),
+ NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT),
+ ifindex);
-static GArray *
-ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteMode mode)
-{
- NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
- gboolean with_default = FALSE, with_non_default = FALSE;
+ routes = (const NMPlatformIPRoute *const*) nmp_cache_lookup_multi (priv->cache, &cache_id, &len);
- nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
+ array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, len);
- if (mode == NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT)
- with_non_default = TRUE;
- else if (mode == NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT)
- with_default = TRUE;
- else if (mode == NM_PLATFORM_GET_ROUTE_MODE_ALL) {
- with_non_default = TRUE;
- with_default = TRUE;
- } else
- g_return_val_if_reached (NULL);
+ with_rtprot_kernel = NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
+ for (i = 0; i < len; i++) {
+ nm_assert (NMP_OBJECT_GET_CLASS (NMP_OBJECT_UP_CAST (routes[i])) == klass);
- return nmp_cache_lookup_multi_to_array (priv->cache,
- obj_type,
- nmp_cache_id_init_routes_visible (NMP_CACHE_ID_STATIC,
- obj_type,
- with_default,
- with_non_default,
- ifindex));
+ if ( with_rtprot_kernel
+ || routes[i]->source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
+ g_array_append_vals (array, routes[i], 1);
+ }
+ return array;
}
static GArray *
-ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
+ip4_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
- return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP4_ROUTE, mode);
+ return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP4_ROUTE, flags);
}
static GArray *
-ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteMode mode)
+ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags flags)
{
- return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, mode);
+ return ipx_route_get_all (platform, ifindex, NMP_OBJECT_TYPE_IP6_ROUTE, flags);
}
static void
@@ -4341,7 +4308,7 @@ _nmp_vt_cmd_plobj_to_nl_ip4_route (NMPlatform *platform, const NMPlatformObject
&obj->network,
obj->plen,
&obj->gateway,
- NULL,
+ obj->pref_src ? &obj->pref_src : NULL,
obj->metric,
obj->mss);
}
@@ -5027,8 +4994,6 @@ 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;
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 407b91fbcc..02773512c8 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -347,4 +347,92 @@ out:
return g_intern_string (driver);
}
+/******************************************************************
+ * utils
+ ******************************************************************/
+
+/**
+ * Takes a pair @timestamp and @duration, and returns the remaining duration based
+ * on the new timestamp @now.
+ */
+guint32
+nmp_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp,
+ guint32 duration,
+ guint32 now,
+ guint32 padding)
+{
+ gint64 t;
+
+ if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
+ return NM_PLATFORM_LIFETIME_PERMANENT;
+
+ if (timestamp == 0) {
+ /* if the @timestamp is zero, assume it was just left unset and that the relative
+ * @duration starts counting from @now. This is convenient to construct an address
+ * and print it in nm_platform_ip4_address_to_string().
+ *
+ * In general it does not make sense to set the @duration without anchoring at
+ * @timestamp because you don't know the absolute expiration time when looking
+ * at the address at a later moment. */
+ timestamp = now;
+ }
+
+ /* For timestamp > now, just accept it and calculate the expected(?) result. */
+ t = (gint64) timestamp + (gint64) duration - (gint64) now;
+
+ /* Optional padding to avoid potential races. */
+ t += (gint64) padding;
+
+ if (t <= 0)
+ return 0;
+ if (t >= NM_PLATFORM_LIFETIME_PERMANENT)
+ return NM_PLATFORM_LIFETIME_PERMANENT - 1;
+ return t;
+}
+
+gboolean
+nmp_utils_lifetime_get (guint32 timestamp,
+ guint32 lifetime,
+ guint32 preferred,
+ guint32 now,
+ guint32 padding,
+ guint32 *out_lifetime,
+ guint32 *out_preferred)
+{
+ guint32 t_lifetime, t_preferred;
+
+ if (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 (timestamp == 0 && preferred == 0, TRUE);
+ } else {
+ if (!now)
+ now = nm_utils_get_monotonic_timestamp_s ();
+ t_lifetime = nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now, padding);
+ if (!t_lifetime) {
+ *out_lifetime = 0;
+ *out_preferred = 0;
+ return FALSE;
+ }
+ t_preferred = nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, preferred, now, padding);
+
+ *out_lifetime = t_lifetime;
+ *out_preferred = MIN (t_preferred, t_lifetime);
+
+ /* Assert that non-permanent addresses have a (positive) @timestamp. nmp_utils_lifetime_rebase_relative_time_on_now()
+ * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
+ * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
+ */
+ g_return_val_if_fail ( timestamp != 0
+ || ( lifetime == NM_PLATFORM_LIFETIME_PERMANENT
+ && preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
+ g_return_val_if_fail (t_preferred <= t_lifetime, TRUE);
+ }
+ return TRUE;
+}
+
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index d0032f5d69..557de8440b 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -50,5 +50,17 @@ gboolean nmp_utils_mii_supports_carrier_detect (const char *ifname);
const char *nmp_utils_udev_get_driver (GUdevDevice *device);
+guint32 nmp_utils_lifetime_rebase_relative_time_on_now (guint32 timestamp,
+ guint32 duration,
+ guint32 now,
+ guint32 padding);
+
+gboolean nmp_utils_lifetime_get (guint32 timestamp,
+ guint32 lifetime,
+ guint32 preferred,
+ guint32 now,
+ guint32 padding,
+ guint32 *out_lifetime,
+ guint32 *out_preferred);
#endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index dddc7219f1..911b4516d2 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -33,11 +33,14 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-platform.h"
+#include "nm-platform-utils.h"
#include "NetworkManagerUtils.h"
#include "nm-logging.h"
#include "nm-enum-types.h"
#include "nm-core-internal.h"
+#define ADDRESS_LIFETIME_PADDING 5
+
G_STATIC_ASSERT (sizeof ( ((NMPlatformLink *) NULL)->addr.data ) == NM_UTILS_HWADDR_LEN_MAX);
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
@@ -1953,7 +1956,7 @@ nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr a
}
static gboolean
-array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address)
+array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint64 now, guint32 padding)
{
guint len = addresses ? addresses->len : 0;
guint i;
@@ -1961,15 +1964,20 @@ array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address
for (i = 0; i < len; i++) {
NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
- if (candidate->address == address->address && candidate->plen == address->plen)
- return TRUE;
+ if (candidate->address == address->address && candidate->plen == address->plen) {
+ guint32 lifetime, preferred;
+
+ if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
+ now, padding, &lifetime, &preferred))
+ return TRUE;
+ }
}
return FALSE;
}
static gboolean
-array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address)
+array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address, gint64 now, guint32 padding)
{
guint len = addresses ? addresses->len : 0;
guint i;
@@ -1977,100 +1985,16 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
for (i = 0; i < len; i++) {
NMPlatformIP6Address *candidate = &g_array_index (addresses, NMPlatformIP6Address, i);
- if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen)
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- * Takes a pair @timestamp and @duration, and returns the remaining duration based
- * on the new timestamp @now.
- */
-static guint32
-_rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now, guint32 padding)
-{
- gint64 t;
-
- if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
- return NM_PLATFORM_LIFETIME_PERMANENT;
-
- if (timestamp == 0) {
- /* if the @timestamp is zero, assume it was just left unset and that the relative
- * @duration starts counting from @now. This is convenient to construct an address
- * and print it in nm_platform_ip4_address_to_string().
- *
- * In general it does not make sense to set the @duration without anchoring at
- * @timestamp because you don't know the absolute expiration time when looking
- * at the address at a later moment. */
- timestamp = now;
- }
-
- /* For timestamp > now, just accept it and calculate the expected(?) result. */
- t = (gint64) timestamp + (gint64) duration - (gint64) now;
-
- /* Optional padding to avoid potential races. */
- t += (gint64) padding;
-
- if (t <= 0)
- return 0;
- if (t >= NM_PLATFORM_LIFETIME_PERMANENT)
- return NM_PLATFORM_LIFETIME_PERMANENT - 1;
- return t;
-}
-
-static gboolean
-_address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 padding, guint32 *out_lifetime, guint32 *out_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)
- return FALSE;
- preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now, padding);
-
- *out_lifetime = lifetime;
- *out_preferred = MIN (preferred, lifetime);
-
- /* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now()
- * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
- * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
- */
- g_return_val_if_fail ( address->timestamp != 0
- || ( address->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
- && address->preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
- g_return_val_if_fail (preferred <= lifetime, TRUE);
- }
- return TRUE;
-}
+ if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) {
+ guint32 lifetime, preferred;
-gboolean
-nm_platform_ip4_check_reinstall_device_route (NMPlatform *self, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
-{
- _CHECK_SELF (self, klass, 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;
+ if (nmp_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
+ now, padding, &lifetime, &preferred))
+ return TRUE;
+ }
}
- return klass->ip4_check_reinstall_device_route (self, ifindex, address, device_route_metric);
+ return FALSE;
}
/**
@@ -2078,8 +2002,10 @@ nm_platform_ip4_check_reinstall_device_route (NMPlatform *self, int ifindex, con
* @self: platform instance
* @ifindex: Interface index
* @known_addresses: List of addresses
- * @device_route_metric: the route metric for adding subnet routes (replaces
- * the kernel added routes).
+ * @out_added_addresses: (out): (allow-none): if not %NULL, return a #GPtrArray
+ * with the addresses added. The pointers point into @known_addresses.
+ * It possibly does not contain all addresses from @known_address because
+ * some addresses might be expired.
*
* A convenience function to synchronize addresses for a specific interface
* with the least possible disturbance. It simply removes addresses that are
@@ -2088,7 +2014,7 @@ nm_platform_ip4_check_reinstall_device_route (NMPlatform *self, int ifindex, con
* Returns: %TRUE on success.
*/
gboolean
-nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, guint32 device_route_metric)
+nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses)
{
GArray *addresses;
NMPlatformIP4Address *address;
@@ -2102,11 +2028,14 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
for (i = 0; i < addresses->len; i++) {
address = &g_array_index (addresses, NMPlatformIP4Address, i);
- if (!array_contains_ip4_address (known_addresses, address))
+ if (!array_contains_ip4_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING))
nm_platform_ip4_address_delete (self, ifindex, address->address, address->plen, address->peer_address);
}
g_array_free (addresses, TRUE);
+ if (out_added_addresses)
+ *out_added_addresses = NULL;
+
if (!known_addresses)
return TRUE;
@@ -2114,33 +2043,18 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
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))
+ if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
+ now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred))
continue;
- if (nm_platform_ip4_check_reinstall_device_route (self, ifindex, known_address, device_route_metric))
- reinstall_device_route = TRUE;
-
if (!nm_platform_ip4_address_add (self, 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 (self, ifindex, NM_IP_CONFIG_SOURCE_KERNEL, network, known_address->plen,
- 0, known_address->address, device_route_metric, 0);
- (void) nm_platform_ip4_route_delete (self, ifindex, network, known_address->plen,
- NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE);
+ if (out_added_addresses) {
+ if (!*out_added_addresses)
+ *out_added_addresses = g_ptr_array_new ();
+ g_ptr_array_add (*out_added_addresses, (gpointer) known_address);
}
}
@@ -2177,7 +2091,7 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address))
continue;
- if (!array_contains_ip6_address (known_addresses, address))
+ if (!array_contains_ip6_address (known_addresses, address, now, ADDRESS_LIFETIME_PADDING))
nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen);
}
g_array_free (addresses, TRUE);
@@ -2190,8 +2104,8 @@ nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known
const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
guint32 lifetime, preferred;
- /* add a padding of 5 seconds to avoid potential races. */
- if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred))
+ if (!nmp_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
+ now, ADDRESS_LIFETIME_PADDING, &lifetime, &preferred))
continue;
if (!nm_platform_ip6_address_add (self, ifindex, known_address->address,
@@ -2208,32 +2122,30 @@ nm_platform_address_flush (NMPlatform *self, int ifindex)
{
_CHECK_SELF (self, klass, FALSE);
- return nm_platform_ip4_address_sync (self, ifindex, NULL, 0)
- && nm_platform_ip6_address_sync (self, ifindex, NULL, FALSE);
+ return nm_platform_ip4_address_sync (self, ifindex, NULL, NULL)
+ && nm_platform_ip6_address_sync (self, ifindex, NULL, FALSE);
}
/******************************************************************/
GArray *
-nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteMode mode)
+nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags)
{
_CHECK_SELF (self, klass, 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 (self, ifindex, mode);
+ return klass->ip4_route_get_all (self, ifindex, flags);
}
GArray *
-nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteMode mode)
+nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags)
{
_CHECK_SELF (self, klass, 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 (self, ifindex, mode);
+ return klass->ip6_route_get_all (self, ifindex, flags);
}
gboolean
@@ -2250,7 +2162,6 @@ nm_platform_ip4_route_add (NMPlatform *self,
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;
@@ -2259,11 +2170,9 @@ nm_platform_ip4_route_add (NMPlatform *self,
route.gateway = gateway;
route.metric = metric;
route.mss = mss;
+ route.pref_src = pref_src;
- 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 ? ")" : "");
+ debug ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route));
}
return klass->ip4_route_add (self, ifindex, source, network, plen, gateway, pref_src, metric, mss);
}
@@ -2351,7 +2260,7 @@ static const char *
source_to_string (NMIPConfigSource source)
{
switch (source) {
- case _NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
+ case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return "rtprot-kernel";
case _NM_IP_CONFIG_SOURCE_RTM_F_CLONED:
return "rtm-f-cloned";
@@ -2386,7 +2295,7 @@ _lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf,
return "forever";
g_snprintf (buf, buf_size, "%usec",
- _rebase_relative_time_on_now (timestamp, lifetime, now, 0));
+ nmp_utils_lifetime_rebase_relative_time_on_now (timestamp, lifetime, now, 0));
return buf;
}
@@ -2668,6 +2577,7 @@ const char *
nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
{
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
+ char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_scope[30];
@@ -2686,6 +2596,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
"%s%s" /* scope */
+ "%s%s" /* pref-src */
"",
s_network, route->plen,
s_gateway,
@@ -2694,7 +2605,9 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
route->mss,
source_to_string (route->source),
route->scope_inv ? " scope " : "",
- route->scope_inv ? (rtnl_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "");
+ route->scope_inv ? (rtnl_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "",
+ route->pref_src ? " pref-src " : "",
+ route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "");
return _nm_platform_to_string_buffer;
}
@@ -2873,6 +2786,7 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
_CMP_FIELD (a, b, metric);
_CMP_FIELD (a, b, mss);
_CMP_FIELD (a, b, scope_inv);
+ _CMP_FIELD (a, b, pref_src);
return 0;
}
@@ -2995,7 +2909,7 @@ log_ip6_route (NMPlatform *p, NMPObjectType obj_type, int ifindex, NMPlatformIP6
/******************************************************************/
static gboolean
-_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src)
+_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
{
return nm_platform_ip4_route_add (self,
ifindex > 0 ? ifindex : route->rx.ifindex,
@@ -3003,13 +2917,13 @@ _vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout
route->r4.network,
route->rx.plen,
route->r4.gateway,
- v4_pref_src,
+ route->r4.pref_src,
route->rx.metric,
route->rx.mss);
}
static gboolean
-_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src)
+_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
{
return nm_platform_ip6_route_add (self,
ifindex > 0 ? ifindex : route->rx.ifindex,
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 4896783078..a8a6caa6fd 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -151,10 +151,16 @@ typedef enum {
#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
typedef enum {
- NM_PLATFORM_GET_ROUTE_MODE_ALL,
- NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT,
- NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT,
-} NMPlatformGetRouteMode;
+ NM_PLATFORM_GET_ROUTE_FLAGS_NONE = 0,
+
+ /* Whether to include default-routes/non-default-routes. Omitting
+ * both WITH_DEFAULT and WITH_NON_DEFAULT, is equal to specifying
+ * both of them. */
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT = (1LL << 0),
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT = (1LL << 1),
+
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL = (1LL << 2),
+} NMPlatformGetRouteFlags;
typedef struct {
__NMPlatformObject_COMMON;
@@ -276,6 +282,10 @@ struct _NMPlatformIP4Route {
/* The bitwise inverse of the route scope. It is inverted so that the
* default value (RT_SCOPE_NOWHERE) is nul. */
guint8 scope_inv;
+
+ /* RTA_PREFSRC/rtnl_route_get_pref_src(). A value of zero means that
+ * no pref-src is set. */
+ guint32 pref_src;
};
G_STATIC_ASSERT (G_STRUCT_OFFSET (NMPlatformIPRoute, network_ptr) == G_STRUCT_OFFSET (NMPlatformIP4Route, network));
@@ -304,8 +314,8 @@ typedef struct {
gsize sizeof_route;
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b);
const char *(*route_to_string) (const NMPlatformIPXRoute *route);
- GArray *(*route_get_all) (NMPlatform *self, int ifindex, NMPlatformGetRouteMode mode);
- gboolean (*route_add) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src);
+ GArray *(*route_get_all) (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
+ gboolean (*route_add) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route);
gboolean (*route_delete) (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route);
gboolean (*route_delete_default) (NMPlatform *self, int ifindex, guint32 metric);
guint32 (*metric_normalize) (guint32 metric);
@@ -511,10 +521,8 @@ typedef struct {
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);
- 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);
+ GArray * (*ip4_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
+ GArray * (*ip6_route_get_all) (NMPlatform *, int ifindex, NMPlatformGetRouteFlags flags);
gboolean (*ip4_route_add) (NMPlatform *, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
guint32 pref_src, guint32 metric, guint32 mss);
@@ -697,14 +705,12 @@ gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_
gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
gboolean nm_platform_ip4_address_exists (NMPlatform *self, int ifindex, in_addr_t address, int plen);
gboolean nm_platform_ip6_address_exists (NMPlatform *self, int ifindex, struct in6_addr address, int plen);
-gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, guint32 device_route_metric);
+gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local);
gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
-gboolean nm_platform_ip4_check_reinstall_device_route (NMPlatform *self, int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric);
-
-GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteMode mode);
-GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteMode mode);
+GArray *nm_platform_ip4_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
+GArray *nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRouteFlags flags);
gboolean nm_platform_ip4_route_add (NMPlatform *self, int ifindex, NMIPConfigSource source,
in_addr_t network, int plen, in_addr_t gateway,
guint32 pref_src, guint32 metric, guint32 mss);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index 77e7b15b99..51684b93c7 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -786,7 +786,7 @@ _vt_cmd_obj_is_visible_ipx_route (const NMPObject *obj)
{
NMIPConfigSource source = obj->ip_route.source;
- return obj->object.ifindex > 0 && (source != _NM_IP_CONFIG_SOURCE_RTPROT_KERNEL && source != _NM_IP_CONFIG_SOURCE_RTM_F_CLONED);
+ return obj->object.ifindex > 0 && source != _NM_IP_CONFIG_SOURCE_RTM_F_CLONED;
}
/******************************************************************/
diff --git a/src/platform/tests/dump.c b/src/platform/tests/dump.c
index 575ce6fb34..54de1da70c 100644
--- a/src/platform/tests/dump.c
+++ b/src/platform/tests/dump.c
@@ -86,8 +86,8 @@ dump_interface (NMPlatformLink *link)
g_array_unref (ip4_addresses);
g_array_unref (ip6_addresses);
- ip4_routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
- ip6_routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, link->ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ ip4_routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, link->ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
+ ip6_routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, link->ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
g_assert (ip4_routes);
g_assert (ip6_routes);
diff --git a/src/platform/tests/platform.c b/src/platform/tests/platform.c
index f87588a30b..60555414da 100644
--- a/src/platform/tests/platform.c
+++ b/src/platform/tests/platform.c
@@ -640,7 +640,7 @@ do_ip4_route_get_all (char **argv)
int i;
if (ifindex) {
- routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP4Route, i);
inet_ntop (AF_INET, &route->network, networkstr, sizeof (networkstr));
@@ -664,7 +664,7 @@ do_ip6_route_get_all (char **argv)
int i;
if (ifindex) {
- routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
for (i = 0; i < routes->len; i++) {
route = &g_array_index (routes, NMPlatformIP6Route, i);
inet_ntop (AF_INET6, &route->network, networkstr, sizeof (networkstr));
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index f14d9c07ac..0b825114aa 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -54,8 +54,8 @@ test_cleanup_internal (void)
addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
- routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
- routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
+ routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
g_assert_cmpint (addresses4->len, ==, 1);
g_assert_cmpint (addresses6->len, ==, 2); /* also has a IPv6 LL address. */
@@ -72,8 +72,8 @@ test_cleanup_internal (void)
addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
- routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
- routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
+ routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
g_assert_cmpint (addresses4->len, ==, 0);
g_assert_cmpint (addresses6->len, ==, 0);
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index 29e7c89851..79d6fce75e 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -155,7 +155,7 @@ test_ip4_route (void)
accept_signals (route_changed, 0, 1);
/* Test route listing */
- routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
rts[0].source = NM_IP_CONFIG_SOURCE_USER;
rts[0].network = gateway;
@@ -242,7 +242,7 @@ test_ip6_route (void)
accept_signals (route_changed, 0, 1);
/* Test route listing */
- routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_MODE_ALL);
+ routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
rts[0].source = NM_IP_CONFIG_SOURCE_USER;
rts[0].network = gateway;
diff --git a/src/tests/test-route-manager.c b/src/tests/test-route-manager.c
index 60199c523f..d62ffea33d 100644
--- a/src/tests/test-route-manager.c
+++ b/src/tests/test-route-manager.c
@@ -61,7 +61,7 @@ setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_
route.mss = 0;
g_array_append_val (routes, route);
- nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -107,7 +107,7 @@ setup_dev1_ip4 (int ifindex)
route.metric = 22;
g_array_append_val (routes, route);
- nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -134,7 +134,7 @@ update_dev0_ip4 (int ifindex)
route.metric = 21;
g_array_append_val (routes, route);
- nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -144,10 +144,10 @@ ip4_routes (test_fixture *fixture)
{
GArray *routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET,
fixture->ifindex0,
- NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
GArray *routes1 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET,
fixture->ifindex1,
- NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
g_array_append_vals (routes, routes1->data, routes1->len);
g_array_free (routes1, TRUE);
@@ -346,7 +346,7 @@ setup_dev0_ip6 (int ifindex)
0);
g_array_append_val (routes, *route);
- nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -403,7 +403,7 @@ setup_dev1_ip6 (int ifindex)
0);
g_array_append_val (routes, *route);
- nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -450,7 +450,7 @@ update_dev0_ip6 (int ifindex)
0);
g_array_append_val (routes, *route);
- nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes);
+ nm_route_manager_ip6_route_sync (nm_route_manager_get (), ifindex, routes, TRUE);
g_array_free (routes, TRUE);
}
@@ -459,10 +459,10 @@ ip6_routes (test_fixture *fixture)
{
GArray *routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET,
fixture->ifindex0,
- NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
GArray *routes1 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET,
fixture->ifindex1,
- NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
+ NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
g_array_append_vals (routes, routes1->data, routes1->len);
g_array_free (routes1, TRUE);