mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-04-04 21:20:54 +02:00
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
(cherry picked from commit 1749ad4068)
This commit is contained in:
commit
b774bde8ed
23 changed files with 762 additions and 328 deletions
|
|
@ -112,6 +112,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4297,6 +4297,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)
|
||||
|
|
@ -4398,6 +4502,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);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3076,9 +3076,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;
|
||||
|
|
@ -6332,10 +6332,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;
|
||||
}
|
||||
|
|
@ -7133,6 +7134,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
|
||||
* (adresses,routes) that is no longer present externally from the interal
|
||||
* config. This way, we don't readd addresses that were manually removed
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "gsystem-local-alloc.h"
|
||||
|
||||
G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT)
|
||||
|
||||
|
|
@ -197,11 +198,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)) {
|
||||
|
|
@ -211,9 +212,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++;
|
||||
}
|
||||
|
||||
/* If there is a host route to the gateway, ignore that route. It is
|
||||
|
|
@ -252,25 +254,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
|
||||
|
|
@ -280,10 +316,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;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -309,11 +309,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)) {
|
||||
|
|
@ -323,9 +323,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++;
|
||||
}
|
||||
|
||||
/* If there is a host route to the gateway, ignore that route. It is
|
||||
|
|
@ -397,7 +398,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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -51,8 +51,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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -4023,13 +4032,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);
|
||||
}
|
||||
|
|
@ -4058,6 +4063,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,
|
||||
|
|
@ -4065,8 +4074,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);
|
||||
}
|
||||
|
|
@ -4075,6 +4084,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,
|
||||
|
|
@ -4082,8 +4095,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);
|
||||
}
|
||||
|
|
@ -4169,103 +4182,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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static GArray *
|
||||
ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteMode mode)
|
||||
ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteFlags flags)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
gboolean with_default = FALSE, with_non_default = FALSE;
|
||||
NMPCacheId cache_id;
|
||||
const NMPlatformIPRoute *const* routes;
|
||||
GArray *array;
|
||||
const NMPClass *klass;
|
||||
gboolean with_rtprot_kernel;
|
||||
guint i, len;
|
||||
|
||||
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
|
||||
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);
|
||||
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 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));
|
||||
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);
|
||||
|
||||
routes = (const NMPlatformIPRoute *const*) nmp_cache_lookup_multi (priv->cache, &cache_id, &len);
|
||||
|
||||
array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, len);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
|
@ -4342,7 +4309,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);
|
||||
}
|
||||
|
|
@ -5028,8 +4995,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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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__)
|
||||
|
|
@ -1947,7 +1950,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;
|
||||
|
|
@ -1955,15 +1958,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;
|
||||
|
|
@ -1971,109 +1979,27 @@ 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;
|
||||
if (IN6_ARE_ADDR_EQUAL (&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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return klass->ip4_check_reinstall_device_route (self, ifindex, address, device_route_metric);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_ip4_address_sync:
|
||||
* @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
|
||||
|
|
@ -2082,7 +2008,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;
|
||||
|
|
@ -2096,11 +2022,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;
|
||||
|
||||
|
|
@ -2108,33 +2037,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2171,7 +2085,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);
|
||||
|
|
@ -2184,8 +2098,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,
|
||||
|
|
@ -2202,32 +2116,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
|
||||
|
|
@ -2244,7 +2156,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;
|
||||
|
|
@ -2253,11 +2164,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);
|
||||
}
|
||||
|
|
@ -2345,7 +2254,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";
|
||||
|
|
@ -2380,7 +2289,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;
|
||||
}
|
||||
|
||||
|
|
@ -2662,6 +2571,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];
|
||||
|
||||
|
|
@ -2680,6 +2590,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,
|
||||
|
|
@ -2688,7 +2599,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;
|
||||
}
|
||||
|
||||
|
|
@ -2867,6 +2780,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;
|
||||
}
|
||||
|
||||
|
|
@ -2989,7 +2903,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,
|
||||
|
|
@ -2997,13 +2911,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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -510,10 +520,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);
|
||||
|
|
@ -696,14 +704,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue