platform: add non-exclusive routes and drop route-manager
Previously, we would add exclusive routes via netlink message flags NLM_F_CREATE | NLM_F_REPLACE for RTM_NEWROUTE. Similar to `ip route replace`. Using that form of RTM_NEWROUTE message, we could only add a certain route with a certain network/plen,metric triple once. That was already hugely inconvenient, because - when configuring routes, multiple (managed) interfaces may get conflicting routes (multihoming). Only one of the routes can be actually configured using `ip route replace`, so we need to track routes that are currently shadowed. - when configuring routes, we might replace externally configured routes on unmanaged interfaces. We should not interfere with such routes. That was worked around by having NMRouteManager (and NMDefaultRouteManager). NMRouteManager would keep a list of the routes which NetworkManager would like to configure, even if momentarily being unable to do so due to conflicting routes. This worked mostly well but was complicated. It involved bumping metrics to avoid conflicts for device routes, as we might require them for gateway routes. Drop that now. Instead, use the corresponding of `ip route append` to configure routes. This allows NetworkManager to confiure (almost) all routes that we care. Especially, it can configure all routes on a managed interface, without replacing/interfering with routes on other interfaces. Hence, NMRouteManager becomes obsolete. It practice it is a bit more complicated because: - when adding an IPv4 address, kernel will automatically create a device route for the subnet. We should avoid that by using the IFA_F_NOPREFIXROUTE flag for IPv4 addresses (still to-do). But as kernel may not support that flag for IPv4 addresses yet (and we don't require such a kernel yet), we still need functionality similar to nm_route_manager_ip4_route_register_device_route_purge_list(). This functionality is now handled via nm_platform_ip4_dev_route_blacklist_set(). - trying to configure an IPv6 route with a source address will be rejected by kernel as long as the address is tentative (see related bug rh#1457196). Preferably, NMDevice would keep the list of routes which should be configured, while kernel would have the list of what actually is configured. There is a feed-back loop where both affect each other (for example, when externally deleting a route, NMDevice must forget about it too). Previously, NMRouteManager would have the task of remembering all routes which we currently want to configure, but cannot due to conflicting routes. We get rid of that, because now we configure non-exclusive routes. We however still will need to remember IPv6 routes with a source address, that currently cannot be configured yet. Hence, we will need to keep track of routes that currently cannot be configured, but later may be. That is still not done yet, as NMRouteManager didn't handle this correctly either.
This commit is contained in:
27
Makefile.am
27
Makefile.am
@@ -1323,9 +1323,6 @@ src_libNetworkManagerBase_la_SOURCES = \
|
|||||||
src/nm-ip6-config.c \
|
src/nm-ip6-config.c \
|
||||||
src/nm-ip6-config.h \
|
src/nm-ip6-config.h \
|
||||||
\
|
\
|
||||||
src/nm-route-manager.c \
|
|
||||||
src/nm-route-manager.h \
|
|
||||||
\
|
|
||||||
src/dhcp/nm-dhcp-client.c \
|
src/dhcp/nm-dhcp-client.c \
|
||||||
src/dhcp/nm-dhcp-client.h \
|
src/dhcp/nm-dhcp-client.h \
|
||||||
src/dhcp/nm-dhcp-client-logging.h \
|
src/dhcp/nm-dhcp-client-logging.h \
|
||||||
@@ -2961,8 +2958,6 @@ check_programs += \
|
|||||||
src/tests/test-general-with-expect \
|
src/tests/test-general-with-expect \
|
||||||
src/tests/test-ip4-config \
|
src/tests/test-ip4-config \
|
||||||
src/tests/test-ip6-config \
|
src/tests/test-ip6-config \
|
||||||
src/tests/test-route-manager-linux \
|
|
||||||
src/tests/test-route-manager-fake \
|
|
||||||
src/tests/test-dcb \
|
src/tests/test-dcb \
|
||||||
src/tests/test-systemd \
|
src/tests/test-systemd \
|
||||||
src/tests/test-resolvconf-capture \
|
src/tests/test-resolvconf-capture \
|
||||||
@@ -3010,28 +3005,6 @@ $(src_tests_test_general_with_expect_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
|||||||
$(src_tests_test_wired_defname_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
$(src_tests_test_wired_defname_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
||||||
$(src_tests_test_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
$(src_tests_test_utils_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
||||||
|
|
||||||
src_tests_test_route_manager_ldflags = \
|
|
||||||
$(CODE_COVERAGE_LDFLAGS)
|
|
||||||
|
|
||||||
src_tests_test_route_manager_ldadd = \
|
|
||||||
src/libNetworkManagerTest.la \
|
|
||||||
$(GLIB_LIBS) \
|
|
||||||
$(LIBUDEV_LIBS) \
|
|
||||||
$(LIBNL_LIBS)
|
|
||||||
|
|
||||||
src_tests_test_route_manager_fake_SOURCES = src/tests/test-route-manager.c
|
|
||||||
src_tests_test_route_manager_fake_CPPFLAGS = $(src_tests_cppflags_fake)
|
|
||||||
src_tests_test_route_manager_fake_LDFLAGS = $(src_tests_test_route_manager_ldflags)
|
|
||||||
src_tests_test_route_manager_fake_LDADD = $(src_tests_test_route_manager_ldadd)
|
|
||||||
|
|
||||||
src_tests_test_route_manager_linux_SOURCES = src/tests/test-route-manager.c
|
|
||||||
src_tests_test_route_manager_linux_CPPFLAGS = $(src_tests_cppflags_linux)
|
|
||||||
src_tests_test_route_manager_linux_LDFLAGS = $(src_tests_test_route_manager_ldflags)
|
|
||||||
src_tests_test_route_manager_linux_LDADD = $(src_tests_test_route_manager_ldadd)
|
|
||||||
|
|
||||||
$(src_tests_test_route_manager_fake_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
|
||||||
$(src_tests_test_route_manager_linux_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
|
|
||||||
|
|
||||||
src_tests_test_systemd_CPPFLAGS = $(src_libsystemd_nm_la_cppflags)
|
src_tests_test_systemd_CPPFLAGS = $(src_libsystemd_nm_la_cppflags)
|
||||||
src_tests_test_systemd_LDADD = \
|
src_tests_test_systemd_LDADD = \
|
||||||
src/libsystemd-nm.la \
|
src/libsystemd-nm.la \
|
||||||
|
@@ -77,7 +77,7 @@ nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
|
|||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static NMDedupMultiEntry *
|
static NMDedupMultiEntry *
|
||||||
_entry_lookup_obj (NMDedupMultiIndex *self,
|
_entry_lookup_obj (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
const NMDedupMultiObj *obj)
|
const NMDedupMultiObj *obj)
|
||||||
{
|
{
|
||||||
@@ -92,7 +92,7 @@ _entry_lookup_obj (NMDedupMultiIndex *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NMDedupMultiHeadEntry *
|
static NMDedupMultiHeadEntry *
|
||||||
_entry_lookup_head (NMDedupMultiIndex *self,
|
_entry_lookup_head (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
const NMDedupMultiObj *obj)
|
const NMDedupMultiObj *obj)
|
||||||
{
|
{
|
||||||
@@ -682,7 +682,7 @@ nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
|
|||||||
* Returns: the cache entry or %NULL if the entry wasn't found.
|
* Returns: the cache entry or %NULL if the entry wasn't found.
|
||||||
*/
|
*/
|
||||||
const NMDedupMultiEntry *
|
const NMDedupMultiEntry *
|
||||||
nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
|
nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
/*const NMDedupMultiObj * */ gconstpointer obj)
|
/*const NMDedupMultiObj * */ gconstpointer obj)
|
||||||
{
|
{
|
||||||
@@ -708,7 +708,7 @@ nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
|
|||||||
* Returns: the cache entry or %NULL if the entry wasn't found.
|
* Returns: the cache entry or %NULL if the entry wasn't found.
|
||||||
*/
|
*/
|
||||||
const NMDedupMultiHeadEntry *
|
const NMDedupMultiHeadEntry *
|
||||||
nm_dedup_multi_index_lookup_head (NMDedupMultiIndex *self,
|
nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
/*const NMDedupMultiObj * */ gconstpointer obj)
|
/*const NMDedupMultiObj * */ gconstpointer obj)
|
||||||
{
|
{
|
||||||
|
@@ -278,11 +278,11 @@ gboolean nm_dedup_multi_index_add (NMDedupMultiIndex *self,
|
|||||||
const NMDedupMultiEntry **out_entry,
|
const NMDedupMultiEntry **out_entry,
|
||||||
/* const NMDedupMultiObj ** */ gpointer out_obj_old);
|
/* const NMDedupMultiObj ** */ gpointer out_obj_old);
|
||||||
|
|
||||||
const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
|
const NMDedupMultiEntry *nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
/*const NMDedupMultiObj * */ gconstpointer obj);
|
/*const NMDedupMultiObj * */ gconstpointer obj);
|
||||||
|
|
||||||
const NMDedupMultiHeadEntry *nm_dedup_multi_index_lookup_head (NMDedupMultiIndex *self,
|
const NMDedupMultiHeadEntry *nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
|
||||||
const NMDedupMultiIdxType *idx_type,
|
const NMDedupMultiIdxType *idx_type,
|
||||||
/*const NMDedupMultiObj * */ gconstpointer obj);
|
/*const NMDedupMultiObj * */ gconstpointer obj);
|
||||||
|
|
||||||
|
@@ -66,7 +66,6 @@
|
|||||||
#include "dns/nm-dns-manager.h"
|
#include "dns/nm-dns-manager.h"
|
||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
#include "nm-default-route-manager.h"
|
#include "nm-default-route-manager.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "systemd/nm-sd.h"
|
#include "systemd/nm-sd.h"
|
||||||
#include "nm-lldp-listener.h"
|
#include "nm-lldp-listener.h"
|
||||||
#include "nm-audit-manager.h"
|
#include "nm-audit-manager.h"
|
||||||
@@ -491,16 +490,14 @@ static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
|
|||||||
static gboolean nm_device_set_ip4_config (NMDevice *self,
|
static gboolean nm_device_set_ip4_config (NMDevice *self,
|
||||||
NMIP4Config *config,
|
NMIP4Config *config,
|
||||||
guint32 default_route_metric,
|
guint32 default_route_metric,
|
||||||
gboolean commit,
|
gboolean commit);
|
||||||
gboolean routes_full_sync);
|
|
||||||
static gboolean ip4_config_merge_and_apply (NMDevice *self,
|
static gboolean ip4_config_merge_and_apply (NMDevice *self,
|
||||||
NMIP4Config *config,
|
NMIP4Config *config,
|
||||||
gboolean commit);
|
gboolean commit);
|
||||||
|
|
||||||
static gboolean nm_device_set_ip6_config (NMDevice *self,
|
static gboolean nm_device_set_ip6_config (NMDevice *self,
|
||||||
NMIP6Config *config,
|
NMIP6Config *config,
|
||||||
gboolean commit,
|
gboolean commit);
|
||||||
gboolean routes_full_sync);
|
|
||||||
static gboolean ip6_config_merge_and_apply (NMDevice *self,
|
static gboolean ip6_config_merge_and_apply (NMDevice *self,
|
||||||
gboolean commit);
|
gboolean commit);
|
||||||
|
|
||||||
@@ -2767,6 +2764,99 @@ link_changed_cb (NMPlatform *platform,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
in_addr_t network;
|
||||||
|
guint8 plen;
|
||||||
|
} IP4RPFilterData;
|
||||||
|
|
||||||
|
static guint
|
||||||
|
_v4_has_shadowed_routes_detect_hash (const IP4RPFilterData *d)
|
||||||
|
{
|
||||||
|
guint h = 0;
|
||||||
|
|
||||||
|
h = NM_HASH_COMBINE (h, d->network);
|
||||||
|
h = NM_HASH_COMBINE (h, d->plen);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_v4_has_shadowed_routes_detect_equal (const IP4RPFilterData *d1, const IP4RPFilterData *d2)
|
||||||
|
{
|
||||||
|
return d1->network == d2->network && d1->plen == d2->plen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_v4_has_shadowed_routes_detect (NMDevice *self)
|
||||||
|
{
|
||||||
|
NMPlatform *platform;
|
||||||
|
int ifindex;
|
||||||
|
NMPLookup lookup;
|
||||||
|
const NMDedupMultiHeadEntry *head_entry;
|
||||||
|
NMDedupMultiIter iter;
|
||||||
|
const NMPObject *o;
|
||||||
|
guint data_len;
|
||||||
|
gs_unref_hashtable GHashTable *data_hash = NULL;
|
||||||
|
gs_free IP4RPFilterData *data_arr = NULL;
|
||||||
|
|
||||||
|
ifindex = nm_device_get_ip_ifindex (self);
|
||||||
|
if (ifindex <= 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
platform = nm_device_get_platform (self);
|
||||||
|
|
||||||
|
head_entry = nm_platform_lookup (platform,
|
||||||
|
nmp_lookup_init_addrroute (&lookup,
|
||||||
|
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||||
|
ifindex));
|
||||||
|
if (!head_entry)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* first, create a lookup index @data_hash for all network/plen pairs. */
|
||||||
|
data_len = 0;
|
||||||
|
data_arr = g_new (IP4RPFilterData, head_entry->len);
|
||||||
|
data_hash = g_hash_table_new ((GHashFunc) _v4_has_shadowed_routes_detect_hash,
|
||||||
|
(GEqualFunc) _v4_has_shadowed_routes_detect_equal);
|
||||||
|
|
||||||
|
nmp_cache_iter_for_each (&iter, head_entry, &o) {
|
||||||
|
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
|
||||||
|
IP4RPFilterData *d;
|
||||||
|
|
||||||
|
nm_assert (r->ifindex == ifindex);
|
||||||
|
|
||||||
|
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
d = &data_arr[data_len++];
|
||||||
|
d->network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
||||||
|
d->plen = r->plen;
|
||||||
|
g_hash_table_add (data_hash, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* then, search if there is any route on another interface with the same
|
||||||
|
* network/plen destination. If yes, we consider this a multihoming
|
||||||
|
* setup. */
|
||||||
|
head_entry = nm_platform_lookup (platform,
|
||||||
|
nmp_lookup_init_obj_type (&lookup,
|
||||||
|
NMP_OBJECT_TYPE_IP4_ROUTE));
|
||||||
|
nmp_cache_iter_for_each (&iter, head_entry, &o) {
|
||||||
|
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (o);
|
||||||
|
IP4RPFilterData d;
|
||||||
|
|
||||||
|
if ( r->ifindex == ifindex
|
||||||
|
|| NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
d.network = nm_utils_ip4_address_clear_host_address (r->network, r->plen);
|
||||||
|
d.plen = r->plen;
|
||||||
|
if (g_hash_table_contains (data_hash, &d))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ip4_rp_filter_update (NMDevice *self)
|
ip4_rp_filter_update (NMDevice *self)
|
||||||
{
|
{
|
||||||
@@ -2792,20 +2882,6 @@ ip4_rp_filter_update (NMDevice *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ip4_routes_changed_changed_cb (NMRouteManager *route_manager, NMDevice *self)
|
|
||||||
{
|
|
||||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
|
||||||
int ifindex = nm_device_get_ip_ifindex (self);
|
|
||||||
|
|
||||||
if (nm_device_sys_iface_state_is_external_or_assume (self))
|
|
||||||
return;
|
|
||||||
|
|
||||||
priv->v4_has_shadowed_routes = nm_route_manager_ip4_routes_shadowed (route_manager,
|
|
||||||
ifindex);
|
|
||||||
ip4_rp_filter_update (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
link_changed (NMDevice *self, const NMPlatformLink *pllink)
|
link_changed (NMDevice *self, const NMPlatformLink *pllink)
|
||||||
{
|
{
|
||||||
@@ -3846,8 +3922,8 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config)
|
|||||||
_update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE);
|
_update_default_route (self, AF_INET6, priv->default_route.v6_has, TRUE);
|
||||||
_update_default_route (self, AF_INET, FALSE, TRUE);
|
_update_default_route (self, AF_INET, FALSE, TRUE);
|
||||||
_update_default_route (self, AF_INET6, FALSE, TRUE);
|
_update_default_route (self, AF_INET6, FALSE, TRUE);
|
||||||
nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE);
|
nm_device_set_ip4_config (self, NULL, 0, FALSE);
|
||||||
nm_device_set_ip6_config (self, NULL, FALSE, FALSE);
|
nm_device_set_ip6_config (self, NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -5582,7 +5658,6 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||||||
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
|
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
|
||||||
guint32 gateway;
|
guint32 gateway;
|
||||||
gboolean connection_has_default_route, connection_is_never_default;
|
gboolean connection_has_default_route, connection_is_never_default;
|
||||||
gboolean routes_full_sync;
|
|
||||||
gboolean ignore_auto_routes = FALSE;
|
gboolean ignore_auto_routes = FALSE;
|
||||||
gboolean ignore_auto_dns = FALSE;
|
gboolean ignore_auto_dns = FALSE;
|
||||||
gboolean auto_method = FALSE;
|
gboolean auto_method = FALSE;
|
||||||
@@ -5749,11 +5824,7 @@ END_ADD_DEFAULT_ROUTE:
|
|||||||
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
|
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
|
||||||
}
|
}
|
||||||
|
|
||||||
routes_full_sync = commit
|
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit);
|
||||||
&& priv->v4_commit_first_time
|
|
||||||
&& !nm_device_sys_iface_state_is_external_or_assume (self);
|
|
||||||
|
|
||||||
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit, routes_full_sync);
|
|
||||||
g_object_unref (composite);
|
g_object_unref (composite);
|
||||||
|
|
||||||
if (commit)
|
if (commit)
|
||||||
@@ -6308,7 +6379,6 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||||||
gboolean has_direct_route;
|
gboolean has_direct_route;
|
||||||
const struct in6_addr *gateway;
|
const struct in6_addr *gateway;
|
||||||
gboolean connection_has_default_route, connection_is_never_default;
|
gboolean connection_has_default_route, connection_is_never_default;
|
||||||
gboolean routes_full_sync;
|
|
||||||
gboolean ignore_auto_routes = FALSE;
|
gboolean ignore_auto_routes = FALSE;
|
||||||
gboolean ignore_auto_dns = FALSE;
|
gboolean ignore_auto_dns = FALSE;
|
||||||
gboolean auto_method = FALSE;
|
gboolean auto_method = FALSE;
|
||||||
@@ -6497,11 +6567,7 @@ END_ADD_DEFAULT_ROUTE:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
routes_full_sync = commit
|
success = nm_device_set_ip6_config (self, composite, commit);
|
||||||
&& priv->v6_commit_first_time
|
|
||||||
&& !nm_device_sys_iface_state_is_external_or_assume (self);
|
|
||||||
|
|
||||||
success = nm_device_set_ip6_config (self, composite, commit, routes_full_sync);
|
|
||||||
g_object_unref (composite);
|
g_object_unref (composite);
|
||||||
if (commit)
|
if (commit)
|
||||||
priv->v6_commit_first_time = FALSE;
|
priv->v6_commit_first_time = FALSE;
|
||||||
@@ -9853,46 +9919,35 @@ static gboolean
|
|||||||
nm_device_set_ip4_config (NMDevice *self,
|
nm_device_set_ip4_config (NMDevice *self,
|
||||||
NMIP4Config *new_config,
|
NMIP4Config *new_config,
|
||||||
guint32 default_route_metric,
|
guint32 default_route_metric,
|
||||||
gboolean commit,
|
gboolean commit)
|
||||||
gboolean routes_full_sync)
|
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv;
|
NMDevicePrivate *priv;
|
||||||
NMIP4Config *old_config = NULL;
|
NMIP4Config *old_config = NULL;
|
||||||
gboolean has_changes = FALSE;
|
gboolean has_changes = FALSE;
|
||||||
gboolean success = TRUE;
|
gboolean success = TRUE;
|
||||||
gboolean def_route_changed;
|
gboolean def_route_changed;
|
||||||
int ip_ifindex, config_ifindex;
|
int ip_ifindex = 0;
|
||||||
|
|
||||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||||
|
|
||||||
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, routes-full-sync=%d, new-config=%p)",
|
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)",
|
||||||
commit, routes_full_sync, new_config);
|
commit, new_config);
|
||||||
|
|
||||||
|
nm_assert ( !new_config
|
||||||
|
|| ( new_config
|
||||||
|
&& ((ip_ifindex = nm_device_get_ip_ifindex (self)) > 0)
|
||||||
|
&& ip_ifindex == nm_ip4_config_get_ifindex (new_config)));
|
||||||
|
|
||||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
|
||||||
|
|
||||||
if (new_config) {
|
|
||||||
config_ifindex = nm_ip4_config_get_ifindex (new_config);
|
|
||||||
if (config_ifindex > 0)
|
|
||||||
g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_config = priv->ip4_config;
|
old_config = priv->ip4_config;
|
||||||
|
|
||||||
/* Always commit to nm-platform to update lifetimes */
|
/* Always commit to nm-platform to update lifetimes */
|
||||||
if (commit && new_config) {
|
if (commit && new_config) {
|
||||||
gboolean assumed = nm_device_sys_iface_state_is_external_or_assume (self);
|
|
||||||
|
|
||||||
_commit_mtu (self, new_config);
|
_commit_mtu (self, new_config);
|
||||||
/* 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,
|
success = nm_ip4_config_commit (new_config,
|
||||||
nm_device_get_platform (self),
|
nm_device_get_platform (self),
|
||||||
nm_netns_get_route_manager (priv->netns),
|
default_route_metric);
|
||||||
ip_ifindex,
|
|
||||||
routes_full_sync,
|
|
||||||
assumed ? (gint64) -1 : (gint64) default_route_metric);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_config) {
|
if (new_config) {
|
||||||
@@ -10031,29 +10086,26 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config)
|
|||||||
static gboolean
|
static gboolean
|
||||||
nm_device_set_ip6_config (NMDevice *self,
|
nm_device_set_ip6_config (NMDevice *self,
|
||||||
NMIP6Config *new_config,
|
NMIP6Config *new_config,
|
||||||
gboolean commit,
|
gboolean commit)
|
||||||
gboolean routes_full_sync)
|
|
||||||
{
|
{
|
||||||
NMDevicePrivate *priv;
|
NMDevicePrivate *priv;
|
||||||
NMIP6Config *old_config = NULL;
|
NMIP6Config *old_config = NULL;
|
||||||
gboolean has_changes = FALSE;
|
gboolean has_changes = FALSE;
|
||||||
gboolean success = TRUE;
|
gboolean success = TRUE;
|
||||||
gboolean def_route_changed;
|
gboolean def_route_changed;
|
||||||
int ip_ifindex, config_ifindex;
|
int ip_ifindex = 0;
|
||||||
|
|
||||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||||
|
|
||||||
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, routes-full-sync=%d, new-config=%p)",
|
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)",
|
||||||
commit, routes_full_sync, new_config);
|
commit, new_config);
|
||||||
|
|
||||||
|
nm_assert ( !new_config
|
||||||
|
|| ( new_config
|
||||||
|
&& ((ip_ifindex = nm_device_get_ip_ifindex (self)) > 0)
|
||||||
|
&& ip_ifindex == nm_ip6_config_get_ifindex (new_config)));
|
||||||
|
|
||||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||||
ip_ifindex = nm_device_get_ip_ifindex (self);
|
|
||||||
|
|
||||||
if (new_config) {
|
|
||||||
config_ifindex = nm_ip6_config_get_ifindex (new_config);
|
|
||||||
if (config_ifindex > 0)
|
|
||||||
g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
old_config = priv->ip6_config;
|
old_config = priv->ip6_config;
|
||||||
|
|
||||||
@@ -10061,10 +10113,7 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||||||
if (commit && new_config) {
|
if (commit && new_config) {
|
||||||
_commit_mtu (self, priv->ip4_config);
|
_commit_mtu (self, priv->ip4_config);
|
||||||
success = nm_ip6_config_commit (new_config,
|
success = nm_ip6_config_commit (new_config,
|
||||||
nm_device_get_platform (self),
|
nm_device_get_platform (self));
|
||||||
nm_netns_get_route_manager (priv->netns),
|
|
||||||
ip_ifindex,
|
|
||||||
routes_full_sync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_config) {
|
if (new_config) {
|
||||||
@@ -10900,6 +10949,11 @@ queued_ip4_config_change (gpointer user_data)
|
|||||||
|
|
||||||
set_unmanaged_external_down (self, TRUE);
|
set_unmanaged_external_down (self, TRUE);
|
||||||
|
|
||||||
|
if (!nm_device_sys_iface_state_is_external_or_assume (self)) {
|
||||||
|
priv->v4_has_shadowed_routes = _v4_has_shadowed_routes_detect (self);;
|
||||||
|
ip4_rp_filter_update (self);
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12105,8 +12159,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||||||
/* Clean up IP configs; this does not actually deconfigure the
|
/* Clean up IP configs; this does not actually deconfigure the
|
||||||
* interface; the caller must flush routes and addresses explicitly.
|
* interface; the caller must flush routes and addresses explicitly.
|
||||||
*/
|
*/
|
||||||
nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE);
|
nm_device_set_ip4_config (self, NULL, 0, TRUE);
|
||||||
nm_device_set_ip6_config (self, NULL, TRUE, TRUE);
|
nm_device_set_ip6_config (self, NULL, TRUE);
|
||||||
g_clear_object (&priv->proxy_config);
|
g_clear_object (&priv->proxy_config);
|
||||||
g_clear_object (&priv->con_ip4_config);
|
g_clear_object (&priv->con_ip4_config);
|
||||||
g_clear_object (&priv->dev_ip4_config);
|
g_clear_object (&priv->dev_ip4_config);
|
||||||
@@ -12194,18 +12248,24 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
|||||||
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
||||||
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
||||||
|
|
||||||
|
ifindex = nm_device_get_ip_ifindex (self);
|
||||||
|
|
||||||
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
||||||
/* master: release slaves */
|
/* master: release slaves */
|
||||||
nm_device_master_release_slaves (self);
|
nm_device_master_release_slaves (self);
|
||||||
|
|
||||||
/* Take out any entries in the routing table and any IP address the device had. */
|
/* Take out any entries in the routing table and any IP address the device had. */
|
||||||
ifindex = nm_device_get_ip_ifindex (self);
|
|
||||||
if (ifindex > 0) {
|
if (ifindex > 0) {
|
||||||
nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), ifindex);
|
NMPlatform *platform = nm_device_get_platform (self);
|
||||||
nm_platform_ip_address_flush (nm_device_get_platform (self), AF_UNSPEC, ifindex);
|
|
||||||
|
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
|
||||||
|
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifindex > 0)
|
||||||
|
nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), ifindex, NULL);
|
||||||
|
|
||||||
/* slave: mark no longer enslaved */
|
/* slave: mark no longer enslaved */
|
||||||
if ( priv->master
|
if ( priv->master
|
||||||
&& nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0)
|
&& nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0)
|
||||||
@@ -13851,9 +13911,6 @@ constructed (GObject *object)
|
|||||||
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
|
||||||
g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self);
|
g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self);
|
||||||
|
|
||||||
g_signal_connect (nm_netns_get_route_manager (priv->netns), NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED,
|
|
||||||
G_CALLBACK (ip4_routes_changed_changed_cb), self);
|
|
||||||
|
|
||||||
priv->settings = g_object_ref (NM_SETTINGS_GET);
|
priv->settings = g_object_ref (NM_SETTINGS_GET);
|
||||||
g_assert (priv->settings);
|
g_assert (priv->settings);
|
||||||
|
|
||||||
@@ -13894,9 +13951,6 @@ dispose (GObject *object)
|
|||||||
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
|
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ipx_changed), self);
|
||||||
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
|
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (link_changed_cb), self);
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (nm_netns_get_route_manager (priv->netns),
|
|
||||||
G_CALLBACK (ip4_routes_changed_changed_cb), self);
|
|
||||||
|
|
||||||
g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
|
g_slist_free_full (priv->arping.dad_list, (GDestroyNotify) nm_arping_manager_destroy);
|
||||||
priv->arping.dad_list = NULL;
|
priv->arping.dad_list = NULL;
|
||||||
|
|
||||||
|
@@ -32,7 +32,6 @@
|
|||||||
#include "nm-setting-connection.h"
|
#include "nm-setting-connection.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "devices/nm-device-private.h"
|
#include "devices/nm-device-private.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "nm-netns.h"
|
#include "nm-netns.h"
|
||||||
#include "nm-act-request.h"
|
#include "nm-act-request.h"
|
||||||
#include "nm-ip4-config.h"
|
#include "nm-ip4-config.h"
|
||||||
@@ -1066,10 +1065,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
|
|||||||
priv->ip6_method == NM_MODEM_IP_METHOD_AUTO) {
|
priv->ip6_method == NM_MODEM_IP_METHOD_AUTO) {
|
||||||
ifindex = nm_device_get_ip_ifindex (device);
|
ifindex = nm_device_get_ip_ifindex (device);
|
||||||
if (ifindex > 0) {
|
if (ifindex > 0) {
|
||||||
nm_route_manager_route_flush (nm_netns_get_route_manager (nm_device_get_netns (device)),
|
NMPlatform *platform = nm_device_get_platform (device);
|
||||||
ifindex);
|
|
||||||
nm_platform_ip_address_flush (nm_device_get_platform (device), AF_UNSPEC, ifindex);
|
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
|
||||||
nm_platform_link_set_down (nm_device_get_platform (device), ifindex);
|
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
|
||||||
|
nm_platform_link_set_down (platform, ifindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
#include "nm-utils.h"
|
#include "nm-utils.h"
|
||||||
#include "nm-setting-ip6-config.h"
|
#include "nm-setting-ip6-config.h"
|
||||||
#include "systemd/nm-sd.h"
|
#include "systemd/nm-sd.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
|
|
||||||
#if !defined(NM_DIST_VERSION)
|
#if !defined(NM_DIST_VERSION)
|
||||||
# define NM_DIST_VERSION VERSION
|
# define NM_DIST_VERSION VERSION
|
||||||
@@ -98,12 +97,6 @@ static struct {
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMRouteManager *route_manager_get (void);
|
|
||||||
|
|
||||||
NM_DEFINE_SINGLETON_GETTER (NMRouteManager, route_manager_get, NM_TYPE_ROUTE_MANAGER);
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dhcp4_state_changed (NMDhcpClient *client,
|
dhcp4_state_changed (NMDhcpClient *client,
|
||||||
NMDhcpState state,
|
NMDhcpState state,
|
||||||
@@ -122,13 +115,17 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case NM_DHCP_STATE_BOUND:
|
case NM_DHCP_STATE_BOUND:
|
||||||
g_assert (ip4_config);
|
g_assert (ip4_config);
|
||||||
|
g_assert (nm_ip4_config_get_ifindex (ip4_config) == gl.ifindex);
|
||||||
|
|
||||||
existing = nm_ip4_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
|
existing = nm_ip4_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
|
||||||
NM_PLATFORM_GET, gl.ifindex, FALSE);
|
NM_PLATFORM_GET, gl.ifindex, FALSE);
|
||||||
if (last_config)
|
if (last_config)
|
||||||
nm_ip4_config_subtract (existing, last_config);
|
nm_ip4_config_subtract (existing, last_config);
|
||||||
|
|
||||||
nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
nm_ip4_config_merge (existing, ip4_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||||
if (!nm_ip4_config_commit (existing, NM_PLATFORM_GET, route_manager_get (), gl.ifindex, TRUE, global_opt.priority_v4))
|
if (!nm_ip4_config_commit (existing,
|
||||||
|
NM_PLATFORM_GET,
|
||||||
|
global_opt.priority_v4))
|
||||||
_LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config");
|
_LOGW (LOGD_DHCP4, "failed to apply DHCPv4 config");
|
||||||
|
|
||||||
if (last_config)
|
if (last_config)
|
||||||
@@ -257,7 +254,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||||||
}
|
}
|
||||||
|
|
||||||
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||||
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET, route_manager_get (), gl.ifindex, TRUE))
|
if (!nm_ip6_config_commit (existing, NM_PLATFORM_GET))
|
||||||
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
|
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@
|
|||||||
#include "platform/nm-platform.h"
|
#include "platform/nm-platform.h"
|
||||||
#include "platform/nm-platform-utils.h"
|
#include "platform/nm-platform-utils.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
|
|
||||||
#include "introspection/org.freedesktop.NetworkManager.IP4Config.h"
|
#include "introspection/org.freedesktop.NetworkManager.IP4Config.h"
|
||||||
@@ -284,6 +283,48 @@ append_force_and_out:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _nm_ip_config_lookup_ip_route:
|
||||||
|
* @multi_idx:
|
||||||
|
* @idx_type:
|
||||||
|
* @needle:
|
||||||
|
* @cmp_type: after lookup, filter the result by comparing with @cmp_type. Only
|
||||||
|
* return the result, if it compares equal to @needle according to this @cmp_type.
|
||||||
|
* Note that the index uses %NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST type, so passing
|
||||||
|
* that compare-type means not to filter any further.
|
||||||
|
*
|
||||||
|
* Returns: the found entry or %NULL.
|
||||||
|
*/
|
||||||
|
const NMDedupMultiEntry *
|
||||||
|
_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
|
||||||
|
const NMIPConfigDedupMultiIdxType *idx_type,
|
||||||
|
const NMPObject *needle,
|
||||||
|
NMPlatformIPRouteCmpType cmp_type)
|
||||||
|
{
|
||||||
|
const NMDedupMultiEntry *entry;
|
||||||
|
|
||||||
|
nm_assert (multi_idx);
|
||||||
|
nm_assert (idx_type);
|
||||||
|
nm_assert (NM_IN_SET (idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||||
|
nm_assert (NMP_OBJECT_GET_TYPE (needle) == idx_type->obj_type);
|
||||||
|
|
||||||
|
entry = nm_dedup_multi_index_lookup_obj (multi_idx,
|
||||||
|
&idx_type->parent,
|
||||||
|
needle);
|
||||||
|
if (!entry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST)
|
||||||
|
nm_assert (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj), NMP_OBJECT_CAST_IP4_ROUTE (needle), cmp_type) == 0);
|
||||||
|
else {
|
||||||
|
if (nm_platform_ip4_route_cmp (NMP_OBJECT_CAST_IP4_ROUTE (entry->obj),
|
||||||
|
NMP_OBJECT_CAST_IP4_ROUTE (needle),
|
||||||
|
cmp_type) != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
|
NM_GOBJECT_PROPERTIES_DEFINE (NMIP4Config,
|
||||||
@@ -352,6 +393,9 @@ G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_EXPORTED_OBJECT)
|
|||||||
|
|
||||||
static void _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
|
static void _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
|
||||||
static void _add_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Route *new);
|
static void _add_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Route *new);
|
||||||
|
static const NMDedupMultiEntry *_lookup_route (const NMIP4Config *self,
|
||||||
|
const NMPObject *needle,
|
||||||
|
NMPlatformIPRouteCmpType cmp_type);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
@@ -669,37 +713,41 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteManager *route_manager, int ifindex, gboolean routes_full_sync, gint64 default_route_metric)
|
nm_ip4_config_commit (const NMIP4Config *self,
|
||||||
|
NMPlatform *platform,
|
||||||
|
guint32 default_route_metric)
|
||||||
{
|
{
|
||||||
|
const NMIP4ConfigPrivate *priv;
|
||||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||||
const NMDedupMultiHeadEntry *head_entry;
|
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||||
|
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||||
|
int ifindex;
|
||||||
guint i;
|
guint i;
|
||||||
gs_unref_array GArray *routes = NULL;
|
gboolean success = TRUE;
|
||||||
gs_unref_array GArray *device_route_purge_list = NULL;
|
|
||||||
const CList *iter;
|
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE);
|
||||||
|
|
||||||
|
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
ifindex = nm_ip4_config_get_ifindex (self);
|
||||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||||
g_return_val_if_fail (self != NULL, FALSE);
|
|
||||||
|
|
||||||
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
|
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
nm_platform_ip4_address_sync (platform, ifindex, addresses);
|
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_routes (self),
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
/* Routes */
|
if (addresses) {
|
||||||
head_entry = nm_ip4_config_lookup_routes (self);
|
|
||||||
|
|
||||||
routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), head_entry ? head_entry->len : 0);
|
|
||||||
|
|
||||||
if ( default_route_metric >= 0
|
|
||||||
&& addresses) {
|
|
||||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
/* 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
|
* As we don't do that for IPv4, add it here shortly before syncing
|
||||||
* the routes. For NMRouteManager these routes are very much important. */
|
* the routes. */
|
||||||
for (i = 0; i < addresses->len; i++) {
|
for (i = 0; i < addresses->len; i++) {
|
||||||
const NMPObject *o = addresses->pdata[i];
|
const NMPObject *o = addresses->pdata[i];
|
||||||
const NMPlatformIP4Address *addr;
|
const NMPlatformIP4Address *addr;
|
||||||
NMPlatformIP4Route route = { 0 };
|
nm_auto_nmpobj NMPObject *r = NULL;
|
||||||
|
NMPlatformIP4Route *route;
|
||||||
|
in_addr_t network;
|
||||||
|
|
||||||
if (!o)
|
if (!o)
|
||||||
continue;
|
continue;
|
||||||
@@ -710,48 +758,77 @@ nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteMana
|
|||||||
|
|
||||||
nm_assert (addr->plen <= 32);
|
nm_assert (addr->plen <= 32);
|
||||||
|
|
||||||
route.ifindex = ifindex;
|
|
||||||
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
|
||||||
|
|
||||||
/* The destination network depends on the peer-address. */
|
/* The destination network depends on the peer-address. */
|
||||||
route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
||||||
|
|
||||||
if (_ipv4_is_zeronet (route.network)) {
|
if (_ipv4_is_zeronet (network)) {
|
||||||
/* Kernel doesn't add device-routes for destinations that
|
/* Kernel doesn't add device-routes for destinations that
|
||||||
* start with 0.x.y.z. Skip them. */
|
* start with 0.x.y.z. Skip them. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
route.plen = addr->plen;
|
r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
|
||||||
route.pref_src = addr->address;
|
route = NMP_OBJECT_CAST_IP4_ROUTE (r);
|
||||||
route.metric = default_route_metric;
|
|
||||||
|
|
||||||
g_array_append_val (routes, route);
|
route->ifindex = ifindex;
|
||||||
|
route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||||
|
route->network = network;
|
||||||
|
route->plen = addr->plen;
|
||||||
|
route->pref_src = addr->address;
|
||||||
|
route->metric = default_route_metric;
|
||||||
|
route->scope_inv = nm_platform_route_scope_inv (NM_RT_SCOPE_LINK);
|
||||||
|
|
||||||
|
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||||
|
|
||||||
|
if (_lookup_route (self,
|
||||||
|
r,
|
||||||
|
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||||
|
/* we already track this route. Don't add it again. */
|
||||||
|
} else {
|
||||||
|
if (!routes)
|
||||||
|
routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||||
|
g_ptr_array_add (routes, (gpointer) nmp_object_ref (r));
|
||||||
|
}
|
||||||
|
|
||||||
if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
||||||
if (!device_route_purge_list)
|
nm_auto_nmpobj NMPObject *r_dev = NULL;
|
||||||
device_route_purge_list = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
||||||
route.metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
|
r_dev = nmp_object_clone (r, FALSE);
|
||||||
g_array_append_val (device_route_purge_list, route);
|
route = NMP_OBJECT_CAST_IP4_ROUTE (r_dev);
|
||||||
|
route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
|
||||||
|
|
||||||
|
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||||
|
|
||||||
|
if (_lookup_route (self,
|
||||||
|
r_dev,
|
||||||
|
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
|
||||||
|
/* we track such a route explicitly. Don't blacklist it. */
|
||||||
|
} else {
|
||||||
|
if (!ip4_dev_route_blacklist)
|
||||||
|
ip4_dev_route_blacklist = g_ptr_array_new_with_free_func ((GDestroyNotify) nmp_object_unref);
|
||||||
|
|
||||||
|
g_ptr_array_add (ip4_dev_route_blacklist,
|
||||||
|
g_steal_pointer (&r_dev));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_entry) {
|
nm_platform_ip4_address_sync (platform, ifindex, addresses);
|
||||||
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
|
||||||
g_array_append_vals (routes,
|
|
||||||
NMP_OBJECT_CAST_IP4_ROUTE (c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj),
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_register_device_route_purge_list (route_manager, device_route_purge_list);
|
if (!nm_platform_ip_route_sync (platform,
|
||||||
|
AF_INET,
|
||||||
|
ifindex,
|
||||||
|
routes,
|
||||||
|
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||||
|
NULL))
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
if (!nm_route_manager_ip4_route_sync (route_manager, ifindex, routes,
|
nm_platform_ip4_dev_route_blacklist_set (platform,
|
||||||
default_route_metric < 0, routes_full_sync))
|
ifindex,
|
||||||
return FALSE;
|
ip4_dev_route_blacklist);
|
||||||
|
|
||||||
return TRUE;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1996,6 +2073,24 @@ nm_ip4_config_address_exists (const NMIP4Config *self,
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static const NMDedupMultiEntry *
|
||||||
|
_lookup_route (const NMIP4Config *self,
|
||||||
|
const NMPObject *needle,
|
||||||
|
NMPlatformIPRouteCmpType cmp_type)
|
||||||
|
{
|
||||||
|
const NMIP4ConfigPrivate *priv;
|
||||||
|
|
||||||
|
nm_assert (NM_IS_IP4_CONFIG (self));
|
||||||
|
nm_assert (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||||
|
|
||||||
|
priv = NM_IP4_CONFIG_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
return _nm_ip_config_lookup_ip_route (priv->multi_idx,
|
||||||
|
&priv->idx_ip4_routes_,
|
||||||
|
needle,
|
||||||
|
cmp_type);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_ip4_config_reset_routes (NMIP4Config *self)
|
nm_ip4_config_reset_routes (NMIP4Config *self)
|
||||||
{
|
{
|
||||||
|
@@ -96,6 +96,11 @@ gboolean _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
|
|||||||
gboolean merge,
|
gboolean merge,
|
||||||
gboolean append_force);
|
gboolean append_force);
|
||||||
|
|
||||||
|
const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route (const NMDedupMultiIndex *multi_idx,
|
||||||
|
const NMIPConfigDedupMultiIdxType *idx_type,
|
||||||
|
const NMPObject *needle,
|
||||||
|
NMPlatformIPRouteCmpType cmp_type);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ())
|
#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ())
|
||||||
@@ -137,7 +142,9 @@ int nm_ip4_config_get_ifindex (const NMIP4Config *self);
|
|||||||
NMDedupMultiIndex *nm_ip4_config_get_multi_idx (const NMIP4Config *self);
|
NMDedupMultiIndex *nm_ip4_config_get_multi_idx (const NMIP4Config *self);
|
||||||
|
|
||||||
NMIP4Config *nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex, gboolean capture_resolv_conf);
|
NMIP4Config *nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex, gboolean capture_resolv_conf);
|
||||||
gboolean nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteManager *route_manager, int ifindex, gboolean routes_full_sync, gint64 default_route_metric);
|
gboolean nm_ip4_config_commit (const NMIP4Config *self,
|
||||||
|
NMPlatform *platform,
|
||||||
|
guint32 default_route_metric);
|
||||||
void nm_ip4_config_merge_setting (NMIP4Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
void nm_ip4_config_merge_setting (NMIP4Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||||
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
|
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
|
||||||
|
|
||||||
|
@@ -32,7 +32,6 @@
|
|||||||
#include "platform/nmp-object.h"
|
#include "platform/nmp-object.h"
|
||||||
#include "platform/nm-platform.h"
|
#include "platform/nm-platform.h"
|
||||||
#include "platform/nm-platform-utils.h"
|
#include "platform/nm-platform-utils.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
#include "nm-ip4-config.h"
|
#include "nm-ip4-config.h"
|
||||||
@@ -516,42 +515,33 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_ip6_config_commit (const NMIP6Config *self,
|
nm_ip6_config_commit (const NMIP6Config *self,
|
||||||
NMPlatform *platform,
|
NMPlatform *platform)
|
||||||
NMRouteManager *route_manager,
|
|
||||||
int ifindex,
|
|
||||||
gboolean routes_full_sync)
|
|
||||||
{
|
{
|
||||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||||
const NMDedupMultiHeadEntry *head_entry;
|
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||||
gs_unref_array GArray *routes = NULL;
|
int ifindex;
|
||||||
const CList *iter;
|
gboolean success = TRUE;
|
||||||
|
|
||||||
|
g_return_val_if_fail (NM_IS_IP6_CONFIG (self), FALSE);
|
||||||
|
|
||||||
|
ifindex = nm_ip6_config_get_ifindex (self);
|
||||||
g_return_val_if_fail (ifindex > 0, FALSE);
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
||||||
g_return_val_if_fail (self != NULL, FALSE);
|
|
||||||
|
|
||||||
/* Addresses */
|
|
||||||
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
|
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
routes = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_routes (self),
|
||||||
|
NULL, NULL);
|
||||||
nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE);
|
nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE);
|
||||||
|
|
||||||
/* Routes */
|
if (!nm_platform_ip_route_sync (platform,
|
||||||
head_entry = nm_ip6_config_lookup_routes (self);
|
AF_INET6,
|
||||||
|
ifindex,
|
||||||
|
routes,
|
||||||
|
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||||
|
NULL))
|
||||||
|
success = FALSE;
|
||||||
|
|
||||||
routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), head_entry ? head_entry->len : 0);
|
return success;
|
||||||
|
|
||||||
if (head_entry) {
|
|
||||||
c_list_for_each (iter, &head_entry->lst_entries_head) {
|
|
||||||
g_array_append_vals (routes,
|
|
||||||
NMP_OBJECT_CAST_IP6_ROUTE (c_list_entry (iter, NMDedupMultiEntry, lst_entries)->obj),
|
|
||||||
1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nm_route_manager_ip6_route_sync (route_manager, ifindex, routes, TRUE, routes_full_sync))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -112,10 +112,7 @@ struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx (const NMIP6Config *self)
|
|||||||
NMIP6Config *nm_ip6_config_capture (struct _NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex,
|
NMIP6Config *nm_ip6_config_capture (struct _NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex,
|
||||||
gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
|
gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
|
||||||
gboolean nm_ip6_config_commit (const NMIP6Config *self,
|
gboolean nm_ip6_config_commit (const NMIP6Config *self,
|
||||||
NMPlatform *platform,
|
NMPlatform *platform);
|
||||||
NMRouteManager *route_manager,
|
|
||||||
int ifindex,
|
|
||||||
gboolean routes_full_sync);
|
|
||||||
void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||||
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self);
|
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self);
|
||||||
|
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "platform/nm-platform.h"
|
#include "platform/nm-platform.h"
|
||||||
#include "platform/nmp-netns.h"
|
#include "platform/nmp-netns.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "nm-default-route-manager.h"
|
#include "nm-default-route-manager.h"
|
||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
#include "NetworkManagerUtils.h"
|
#include "NetworkManagerUtils.h"
|
||||||
@@ -40,7 +39,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
NMPlatform *platform;
|
NMPlatform *platform;
|
||||||
NMPNetns *platform_netns;
|
NMPNetns *platform_netns;
|
||||||
NMRouteManager *route_manager;
|
|
||||||
NMDefaultRouteManager *default_route_manager;
|
NMDefaultRouteManager *default_route_manager;
|
||||||
bool log_with_ptr;
|
bool log_with_ptr;
|
||||||
} NMNetnsPrivate;
|
} NMNetnsPrivate;
|
||||||
@@ -88,12 +86,6 @@ nm_netns_get_default_route_manager (NMNetns *self)
|
|||||||
return NM_NETNS_GET_PRIVATE (self)->default_route_manager;
|
return NM_NETNS_GET_PRIVATE (self)->default_route_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
NMRouteManager *
|
|
||||||
nm_netns_get_route_manager (NMNetns *self)
|
|
||||||
{
|
|
||||||
return NM_NETNS_GET_PRIVATE (self)->route_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -137,7 +129,6 @@ constructed (GObject *object)
|
|||||||
log_with_ptr = nm_platform_get_log_with_ptr (priv->platform);
|
log_with_ptr = nm_platform_get_log_with_ptr (priv->platform);
|
||||||
|
|
||||||
priv->platform_netns = nm_platform_netns_get (priv->platform);
|
priv->platform_netns = nm_platform_netns_get (priv->platform);
|
||||||
priv->route_manager = nm_route_manager_new (log_with_ptr, priv->platform);
|
|
||||||
priv->default_route_manager = nm_default_route_manager_new (log_with_ptr, priv->platform);
|
priv->default_route_manager = nm_default_route_manager_new (log_with_ptr, priv->platform);
|
||||||
|
|
||||||
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
|
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
|
||||||
@@ -157,7 +148,6 @@ dispose (GObject *object)
|
|||||||
NMNetns *self = NM_NETNS (object);
|
NMNetns *self = NM_NETNS (object);
|
||||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||||
|
|
||||||
g_clear_object (&priv->route_manager);
|
|
||||||
g_clear_object (&priv->default_route_manager);
|
g_clear_object (&priv->default_route_manager);
|
||||||
g_clear_object (&priv->platform);
|
g_clear_object (&priv->platform);
|
||||||
|
|
||||||
|
@@ -39,7 +39,6 @@ NMNetns *nm_netns_new (NMPlatform *platform);
|
|||||||
|
|
||||||
NMPlatform *nm_netns_get_platform (NMNetns *self);
|
NMPlatform *nm_netns_get_platform (NMNetns *self);
|
||||||
NMPNetns *nm_netns_get_platform_netns (NMNetns *self);
|
NMPNetns *nm_netns_get_platform_netns (NMNetns *self);
|
||||||
NMRouteManager *nm_netns_get_route_manager (NMNetns *self);
|
|
||||||
NMDefaultRouteManager *nm_netns_get_default_route_manager (NMNetns *self);
|
NMDefaultRouteManager *nm_netns_get_default_route_manager (NMNetns *self);
|
||||||
|
|
||||||
struct _NMDedupMultiIndex *nm_netns_get_multi_idx (NMNetns *self);
|
struct _NMDedupMultiIndex *nm_netns_get_multi_idx (NMNetns *self);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
||||||
/* NetworkManager -- Network link manager
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Red Hat, Inc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NM_ROUTE_MANAGER_H__
|
|
||||||
#define __NM_ROUTE_MANAGER_H__
|
|
||||||
|
|
||||||
#define NM_TYPE_ROUTE_MANAGER (nm_route_manager_get_type ())
|
|
||||||
#define NM_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ROUTE_MANAGER, NMRouteManager))
|
|
||||||
#define NM_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_ROUTE_MANAGER, NMRouteManagerClass))
|
|
||||||
#define NM_IS_ROUTE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_ROUTE_MANAGER))
|
|
||||||
#define NM_IS_ROUTE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_ROUTE_MANAGER))
|
|
||||||
#define NM_ROUTE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_ROUTE_MANAGER, NMRouteManagerClass))
|
|
||||||
|
|
||||||
#define NM_ROUTE_MANAGER_LOG_WITH_PTR "log-with-ptr"
|
|
||||||
#define NM_ROUTE_MANAGER_PLATFORM "platform"
|
|
||||||
|
|
||||||
#define NM_ROUTE_MANAGER_IP4_ROUTES_CHANGED "ip4-routes-changed"
|
|
||||||
|
|
||||||
typedef struct _NMRouteManagerClass NMRouteManagerClass;
|
|
||||||
|
|
||||||
GType nm_route_manager_get_type (void);
|
|
||||||
|
|
||||||
gboolean nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync);
|
|
||||||
gboolean nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes, gboolean ignore_kernel_routes, gboolean full_sync);
|
|
||||||
gboolean nm_route_manager_route_flush (NMRouteManager *self, int ifindex);
|
|
||||||
|
|
||||||
gboolean nm_route_manager_ip4_routes_shadowed (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_new (gboolean log_with_ptr, NMPlatform *platform);
|
|
||||||
|
|
||||||
#endif /* __NM_ROUTE_MANAGER_H__ */
|
|
@@ -50,7 +50,6 @@ typedef struct _NMNetns NMNetns;
|
|||||||
typedef struct _NMPolicy NMPolicy;
|
typedef struct _NMPolicy NMPolicy;
|
||||||
typedef struct _NMRfkillManager NMRfkillManager;
|
typedef struct _NMRfkillManager NMRfkillManager;
|
||||||
typedef struct _NMPacrunnerManager NMPacrunnerManager;
|
typedef struct _NMPacrunnerManager NMPacrunnerManager;
|
||||||
typedef struct _NMRouteManager NMRouteManager;
|
|
||||||
typedef struct _NMSessionMonitor NMSessionMonitor;
|
typedef struct _NMSessionMonitor NMSessionMonitor;
|
||||||
typedef struct _NMSleepMonitor NMSleepMonitor;
|
typedef struct _NMSleepMonitor NMSleepMonitor;
|
||||||
typedef struct _NMLldpListener NMLldpListener;
|
typedef struct _NMLldpListener NMLldpListener;
|
||||||
|
@@ -91,6 +91,9 @@ enum {
|
|||||||
typedef struct _NMPlatformPrivate {
|
typedef struct _NMPlatformPrivate {
|
||||||
bool use_udev:1;
|
bool use_udev:1;
|
||||||
bool log_with_ptr:1;
|
bool log_with_ptr:1;
|
||||||
|
guint ip4_dev_route_blacklist_check_id;
|
||||||
|
guint ip4_dev_route_blacklist_gc_timeout_id;
|
||||||
|
GHashTable *ip4_dev_route_blacklist_hash;
|
||||||
NMDedupMultiIndex *multi_idx;
|
NMDedupMultiIndex *multi_idx;
|
||||||
NMPCache *cache;
|
NMPCache *cache;
|
||||||
} NMPlatformPrivate;
|
} NMPlatformPrivate;
|
||||||
@@ -101,6 +104,10 @@ G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void _ip4_dev_route_blacklist_schedule (NMPlatform *self);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
nm_platform_get_use_udev (NMPlatform *self)
|
nm_platform_get_use_udev (NMPlatform *self)
|
||||||
{
|
{
|
||||||
@@ -3482,6 +3489,153 @@ nm_platform_ip_address_flush (NMPlatform *self,
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_platform_ip_route_sync:
|
||||||
|
* @self: the #NMPlatform instance.
|
||||||
|
* @addr_family: AF_INET or AF_INET6.
|
||||||
|
* @ifindex: the @ifindex for which the routes are to be added.
|
||||||
|
* @routes: (allow-none): a list of routes to configure. Must contain
|
||||||
|
* NMPObject instances of routes, according to @addr_family.
|
||||||
|
* @kernel_delete_predicate: (allow-none): if not %NULL, previously
|
||||||
|
* existing routes already configured will only be deleted if the
|
||||||
|
* predicate returns TRUE. This allows to preserve/ignore some
|
||||||
|
* routes. For example by passing @nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||||
|
* routes with "proto kernel" will be left untouched.
|
||||||
|
* @kernel_delete_userdata: user data for @kernel_delete_predicate.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_platform_ip_route_sync (NMPlatform *self,
|
||||||
|
int addr_family,
|
||||||
|
int ifindex,
|
||||||
|
GPtrArray *routes,
|
||||||
|
NMPObjectPredicateFunc kernel_delete_predicate,
|
||||||
|
gpointer kernel_delete_userdata)
|
||||||
|
{
|
||||||
|
const NMPlatformVTableRoute *vt;
|
||||||
|
gs_unref_ptrarray GPtrArray *plat_routes = NULL;
|
||||||
|
gs_unref_hashtable GHashTable *routes_idx = NULL;
|
||||||
|
const NMPObject *plat_o;
|
||||||
|
const NMPObject *conf_o;
|
||||||
|
const NMDedupMultiEntry *plat_entry;
|
||||||
|
guint i;
|
||||||
|
int i_type;
|
||||||
|
|
||||||
|
nm_assert (NM_IS_PLATFORM (self));
|
||||||
|
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||||
|
nm_assert (ifindex > 0);
|
||||||
|
|
||||||
|
vt = addr_family == AF_INET
|
||||||
|
? &nm_platform_vtable_route_v4
|
||||||
|
: &nm_platform_vtable_route_v6;
|
||||||
|
|
||||||
|
plat_routes = nm_platform_lookup_addrroute_clone (self,
|
||||||
|
vt->obj_type,
|
||||||
|
ifindex,
|
||||||
|
kernel_delete_predicate,
|
||||||
|
kernel_delete_userdata);
|
||||||
|
/* first delete routes which are in platform (@plat_routes), but not to configure (@routes/@routes_idx). */
|
||||||
|
if (plat_routes) {
|
||||||
|
|
||||||
|
/* create a lookup index. */
|
||||||
|
if (routes && routes->len > 0) {
|
||||||
|
routes_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash,
|
||||||
|
(GEqualFunc) nmp_object_id_equal);
|
||||||
|
for (i = 0; i < routes->len; i++) {
|
||||||
|
conf_o = routes->pdata[i];
|
||||||
|
if (!nm_g_hash_table_insert (routes_idx, (gpointer) conf_o, (gpointer) conf_o)) {
|
||||||
|
/* we ignore duplicate @routes. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < plat_routes->len; i++) {
|
||||||
|
plat_o = plat_routes->pdata[i];
|
||||||
|
|
||||||
|
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (NMP_OBJECT_CAST_IP_ROUTE (plat_o))) {
|
||||||
|
/* don't delete default routes. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf_o = routes_idx ? g_hash_table_lookup (routes_idx, plat_o) : NULL;
|
||||||
|
if ( !conf_o
|
||||||
|
|| vt->route_cmp (NMP_OBJECT_CAST_IPX_ROUTE (conf_o),
|
||||||
|
NMP_OBJECT_CAST_IPX_ROUTE (plat_o),
|
||||||
|
NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) == 0) {
|
||||||
|
/* the route in platform is identical to the one we want to add.
|
||||||
|
* Keep it. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_platform_ip_route_delete (self, plat_o)) {
|
||||||
|
/* ignore error... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!routes)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
for (i_type = 0; i_type < 2; i_type++) {
|
||||||
|
for (i = 0; i < routes->len; i++) {
|
||||||
|
conf_o = routes->pdata[i];
|
||||||
|
|
||||||
|
#define VTABLE_IS_DEVICE_ROUTE(vt, o) (vt->is_ip4 \
|
||||||
|
? (NMP_OBJECT_CAST_IP4_ROUTE (o)->gateway == 0) \
|
||||||
|
: IN6_IS_ADDR_UNSPECIFIED (&NMP_OBJECT_CAST_IP6_ROUTE (o)->gateway) )
|
||||||
|
|
||||||
|
if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vt, conf_o))
|
||||||
|
|| (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vt, conf_o))) {
|
||||||
|
/* we add routes in two runs over @i_type.
|
||||||
|
*
|
||||||
|
* First device routes, then gateway routes. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
plat_entry = nm_platform_lookup_entry (self,
|
||||||
|
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||||
|
conf_o);
|
||||||
|
if (plat_entry) {
|
||||||
|
/* we alreay have a route with the same ID in the platform cache.
|
||||||
|
* Skip adding it again. It should identical already, otherwise we would
|
||||||
|
* have deleted it in the previous step. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nm_platform_ip_route_add (self,
|
||||||
|
NMP_NLM_FLAG_APPEND,
|
||||||
|
conf_o)) {
|
||||||
|
/* ignore error adding route. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
nm_platform_ip_route_flush (NMPlatform *self,
|
||||||
|
int addr_family,
|
||||||
|
int ifindex)
|
||||||
|
{
|
||||||
|
gboolean success = TRUE;
|
||||||
|
|
||||||
|
_CHECK_SELF (self, klass, FALSE);
|
||||||
|
|
||||||
|
nm_assert (NM_IN_SET (addr_family, AF_UNSPEC,
|
||||||
|
AF_INET,
|
||||||
|
AF_INET6));
|
||||||
|
|
||||||
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET))
|
||||||
|
success &= nm_platform_ip_route_sync (self, AF_INET, ifindex, NULL, NULL, NULL);
|
||||||
|
if (NM_IN_SET (addr_family, AF_UNSPEC, AF_INET6))
|
||||||
|
success &= nm_platform_ip_route_sync (self, AF_INET6, ifindex, NULL, NULL, NULL);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static guint8
|
static guint8
|
||||||
_ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route)
|
_ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route)
|
||||||
{
|
{
|
||||||
@@ -3616,6 +3770,274 @@ nm_platform_ip_route_delete (NMPlatform *self,
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS ((int) 1500)
|
||||||
|
#define IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S ((int) (((IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS + 999) * 3) / 1000))
|
||||||
|
|
||||||
|
static gint64
|
||||||
|
_ip4_dev_route_blacklist_timeout_ms_get (gint64 timeout_ms)
|
||||||
|
{
|
||||||
|
return timeout_ms >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint64
|
||||||
|
_ip4_dev_route_blacklist_timeout_ms_marked (gint64 timeout_ms)
|
||||||
|
{
|
||||||
|
return !!(timeout_ms & ((gint64) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_ip4_dev_route_blacklist_check_cb (gpointer user_data)
|
||||||
|
{
|
||||||
|
NMPlatform *self = user_data;
|
||||||
|
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
GHashTableIter iter;
|
||||||
|
const NMPObject *p_obj;
|
||||||
|
gint64 *p_timeout_ms;
|
||||||
|
gint64 now_ms;
|
||||||
|
|
||||||
|
priv->ip4_dev_route_blacklist_check_id = 0;
|
||||||
|
|
||||||
|
again:
|
||||||
|
if (!priv->ip4_dev_route_blacklist_hash)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
now_ms = nm_utils_get_monotonic_timestamp_ms ();
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) {
|
||||||
|
if (!_ip4_dev_route_blacklist_timeout_ms_marked (*p_timeout_ms))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* unmark because we checked it. */
|
||||||
|
*p_timeout_ms = *p_timeout_ms & ~((gint64) 1);
|
||||||
|
|
||||||
|
if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!nm_platform_lookup_entry (self,
|
||||||
|
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||||
|
p_obj))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_LOGT ("ip4-dev-route: delete %s",
|
||||||
|
nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||||
|
nm_platform_ip_route_delete (self, p_obj);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ip4_dev_route_blacklist_check_schedule (NMPlatform *self)
|
||||||
|
{
|
||||||
|
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if (!priv->ip4_dev_route_blacklist_check_id) {
|
||||||
|
priv->ip4_dev_route_blacklist_check_id = g_idle_add_full (G_PRIORITY_HIGH,
|
||||||
|
_ip4_dev_route_blacklist_check_cb,
|
||||||
|
self,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ip4_dev_route_blacklist_notify_route (NMPlatform *self,
|
||||||
|
const NMPObject *obj)
|
||||||
|
{
|
||||||
|
NMPlatformPrivate *priv;
|
||||||
|
const NMPObject *p_obj;
|
||||||
|
gint64 *p_timeout_ms;
|
||||||
|
gint64 now_ms;
|
||||||
|
|
||||||
|
nm_assert (NM_IS_PLATFORM (self));
|
||||||
|
nm_assert (NMP_OBJECT_GET_TYPE (obj) == NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||||
|
|
||||||
|
priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
nm_assert (priv->ip4_dev_route_blacklist_gc_timeout_id);
|
||||||
|
|
||||||
|
if (!g_hash_table_lookup_extended (priv->ip4_dev_route_blacklist_hash,
|
||||||
|
obj,
|
||||||
|
(gpointer *) &p_obj,
|
||||||
|
(gpointer *) &p_timeout_ms))
|
||||||
|
return;
|
||||||
|
|
||||||
|
now_ms = nm_utils_get_monotonic_timestamp_ms ();
|
||||||
|
if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) {
|
||||||
|
/* already expired. Wait for gc. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ip4_dev_route_blacklist_timeout_ms_marked (*p_timeout_ms)) {
|
||||||
|
nm_assert (priv->ip4_dev_route_blacklist_check_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We cannot delete it right away because we are in the process of receiving netlink messages.
|
||||||
|
* It may be possible to do so, but complicated and error prone.
|
||||||
|
*
|
||||||
|
* Instead, we mark the entry and schedule an idle action (with high priority). */
|
||||||
|
*p_timeout_ms = (*p_timeout_ms) | ((gint64) 1);
|
||||||
|
_ip4_dev_route_blacklist_check_schedule (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_ip4_dev_route_blacklist_gc_timeout_handle (gpointer user_data)
|
||||||
|
{
|
||||||
|
NMPlatform *self = user_data;
|
||||||
|
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
GHashTableIter iter;
|
||||||
|
const NMPObject *p_obj;
|
||||||
|
gint64 *p_timeout_ms;
|
||||||
|
gint64 now_ms;
|
||||||
|
|
||||||
|
nm_assert (priv->ip4_dev_route_blacklist_gc_timeout_id);
|
||||||
|
|
||||||
|
now_ms = nm_utils_get_monotonic_timestamp_ms ();
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) {
|
||||||
|
if (now_ms > _ip4_dev_route_blacklist_timeout_ms_get (*p_timeout_ms)) {
|
||||||
|
_LOGT ("ip4-dev-route: cleanup %s",
|
||||||
|
nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||||
|
g_hash_table_iter_remove (&iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ip4_dev_route_blacklist_schedule (self);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ip4_dev_route_blacklist_schedule (NMPlatform *self)
|
||||||
|
{
|
||||||
|
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
if ( !priv->ip4_dev_route_blacklist_hash
|
||||||
|
|| g_hash_table_size (priv->ip4_dev_route_blacklist_hash) == 0) {
|
||||||
|
g_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref);
|
||||||
|
nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id);
|
||||||
|
} else {
|
||||||
|
if (!priv->ip4_dev_route_blacklist_gc_timeout_id) {
|
||||||
|
/* this timeout is only to garbage collect the expired entries from priv->ip4_dev_route_blacklist_hash.
|
||||||
|
* It can run infrequently, and it doesn't hurt if expired entries linger around a bit
|
||||||
|
* longer then necessary. */
|
||||||
|
priv->ip4_dev_route_blacklist_gc_timeout_id = g_timeout_add_seconds (IP4_DEV_ROUTE_BLACKLIST_GC_TIMEOUT_S,
|
||||||
|
_ip4_dev_route_blacklist_gc_timeout_handle,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_platform_ip4_dev_route_blacklist_set:
|
||||||
|
* @self:
|
||||||
|
* @ifindex:
|
||||||
|
* @ip4_dev_route_blacklist:
|
||||||
|
*
|
||||||
|
* When adding an IP address, kernel automatically adds a device route.
|
||||||
|
* This can be suppressed via the IFA_F_NOPREFIXROUTE address flag. For IPv6
|
||||||
|
* addresses, we require kernel support for IFA_F_NOPREFIXROUTE and always
|
||||||
|
* add the device route manually.
|
||||||
|
*
|
||||||
|
* For IPv4, this flag is rather new and we don't rely on it yet. We want to use
|
||||||
|
* it (but currently still don't). So, for IPv4, kernel possibly adds a device
|
||||||
|
* route, however it has a wrong metric of zero. We add our own device route (with
|
||||||
|
* proper metric), but need to delete the route that kernel adds.
|
||||||
|
*
|
||||||
|
* The problem is, that kernel does not immidiately add the route, when adding
|
||||||
|
* the address. It only shows up some time later. So, we register here a list
|
||||||
|
* of blacklisted routes, and when they show up within a time out, we assume it's
|
||||||
|
* the kernel generated one, and we delete it.
|
||||||
|
*
|
||||||
|
* Eventually, we want to get rid of this and use IFA_F_NOPREFIXROUTE for IPv4
|
||||||
|
* routes as well.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self,
|
||||||
|
int ifindex,
|
||||||
|
GPtrArray *ip4_dev_route_blacklist)
|
||||||
|
{
|
||||||
|
NMPlatformPrivate *priv;
|
||||||
|
GHashTableIter iter;
|
||||||
|
const NMPObject *p_obj;
|
||||||
|
guint i;
|
||||||
|
gint64 timeout_ms;
|
||||||
|
gint64 timeout_ms_val;
|
||||||
|
gint64 *p_timeout_ms;
|
||||||
|
gboolean needs_check = FALSE;
|
||||||
|
|
||||||
|
nm_assert (NM_IS_PLATFORM (self));
|
||||||
|
nm_assert (ifindex > 0);
|
||||||
|
|
||||||
|
priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
/* first, expire all for current ifindex... */
|
||||||
|
if (priv->ip4_dev_route_blacklist_hash) {
|
||||||
|
g_hash_table_iter_init (&iter, priv->ip4_dev_route_blacklist_hash);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *) &p_obj, (gpointer *) &p_timeout_ms)) {
|
||||||
|
if (NMP_OBJECT_CAST_IP4_ROUTE (p_obj)->ifindex == ifindex) {
|
||||||
|
/* we could g_hash_table_iter_remove(&iter) the current entry.
|
||||||
|
* Instead, just expire it and let _ip4_dev_route_blacklist_gc_timeout_handle()
|
||||||
|
* handle it.
|
||||||
|
*
|
||||||
|
* The assumption is, that ip4_dev_route_blacklist contains the very same entry
|
||||||
|
* again, with a new timeout. So, we can un-expire it below. */
|
||||||
|
*p_timeout_ms = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ip4_dev_route_blacklist
|
||||||
|
&& ip4_dev_route_blacklist->len > 0) {
|
||||||
|
|
||||||
|
if (!priv->ip4_dev_route_blacklist_hash) {
|
||||||
|
priv->ip4_dev_route_blacklist_hash = g_hash_table_new_full ((GHashFunc) nmp_object_id_hash,
|
||||||
|
(GEqualFunc) nmp_object_id_equal,
|
||||||
|
(GDestroyNotify) nmp_object_unref,
|
||||||
|
nm_g_slice_free_fcn_gint64);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout_ms = nm_utils_get_monotonic_timestamp_ms () + IP4_DEV_ROUTE_BLACKLIST_TIMEOUT_MS;
|
||||||
|
timeout_ms_val = (timeout_ms << 1) | ((gint64) 1);
|
||||||
|
for (i = 0; i < ip4_dev_route_blacklist->len; i++) {
|
||||||
|
const NMPObject *o;
|
||||||
|
|
||||||
|
needs_check = TRUE;
|
||||||
|
o = ip4_dev_route_blacklist->pdata[i];
|
||||||
|
if (g_hash_table_lookup_extended (priv->ip4_dev_route_blacklist_hash,
|
||||||
|
o,
|
||||||
|
(gpointer *) &p_obj,
|
||||||
|
(gpointer *) &p_timeout_ms)) {
|
||||||
|
if (nmp_object_equal (p_obj, o)) {
|
||||||
|
/* un-expire and reuse the entry. */
|
||||||
|
_LOGT ("ip4-dev-route: register %s (update)",
|
||||||
|
nmp_object_to_string (p_obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||||
|
*p_timeout_ms = timeout_ms_val;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_LOGT ("ip4-dev-route: register %s",
|
||||||
|
nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||||
|
p_timeout_ms = g_slice_new (gint64);
|
||||||
|
*p_timeout_ms = timeout_ms_val;
|
||||||
|
g_hash_table_replace (priv->ip4_dev_route_blacklist_hash,
|
||||||
|
(gpointer) nmp_object_ref (o),
|
||||||
|
p_timeout_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ip4_dev_route_blacklist_schedule (self);
|
||||||
|
|
||||||
|
if (needs_check)
|
||||||
|
_ip4_dev_route_blacklist_check_schedule (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
nm_platform_vlan_qos_mapping_to_string (const char *name,
|
nm_platform_vlan_qos_mapping_to_string (const char *name,
|
||||||
const NMVlanQosMapping *map,
|
const NMVlanQosMapping *map,
|
||||||
@@ -5235,6 +5657,11 @@ nm_platform_cache_update_emit_signal (NMPlatform *self,
|
|||||||
|
|
||||||
klass = NMP_OBJECT_GET_CLASS (o);
|
klass = NMP_OBJECT_GET_CLASS (o);
|
||||||
|
|
||||||
|
if ( klass->obj_type == NMP_OBJECT_TYPE_IP4_ROUTE
|
||||||
|
&& NM_PLATFORM_GET_PRIVATE (self)->ip4_dev_route_blacklist_gc_timeout_id
|
||||||
|
&& NM_IN_SET (cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_UPDATED))
|
||||||
|
_ip4_dev_route_blacklist_notify_route (self, o);
|
||||||
|
|
||||||
_LOGt ("emit signal %s %s: %s",
|
_LOGt ("emit signal %s %s: %s",
|
||||||
klass->signal_type,
|
klass->signal_type,
|
||||||
nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op),
|
nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op),
|
||||||
@@ -5284,40 +5711,6 @@ nm_platform_netns_push (NMPlatform *self, NMPNetns **netns)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_vtr_v4_route_add (NMPlatform *self,
|
|
||||||
NMPNlmFlags flags,
|
|
||||||
const NMPlatformIPXRoute *route,
|
|
||||||
int ifindex,
|
|
||||||
gint64 metric)
|
|
||||||
{
|
|
||||||
NMPlatformIP4Route rt = route->r4;
|
|
||||||
|
|
||||||
if (ifindex > 0)
|
|
||||||
rt.ifindex = ifindex;
|
|
||||||
if (metric >= 0)
|
|
||||||
rt.metric = metric;
|
|
||||||
|
|
||||||
return nm_platform_ip4_route_add (self, flags, &rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_vtr_v6_route_add (NMPlatform *self,
|
|
||||||
NMPNlmFlags flags,
|
|
||||||
const NMPlatformIPXRoute *route,
|
|
||||||
int ifindex,
|
|
||||||
gint64 metric)
|
|
||||||
{
|
|
||||||
NMPlatformIP6Route rt = route->r6;
|
|
||||||
|
|
||||||
if (ifindex > 0)
|
|
||||||
rt.ifindex = ifindex;
|
|
||||||
if (metric >= 0)
|
|
||||||
rt.metric = metric;
|
|
||||||
|
|
||||||
return nm_platform_ip6_route_add (self, flags, &rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint32
|
static guint32
|
||||||
_vtr_v4_metric_normalize (guint32 metric)
|
_vtr_v4_metric_normalize (guint32 metric)
|
||||||
{
|
{
|
||||||
@@ -5333,7 +5726,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
|
|||||||
.sizeof_route = sizeof (NMPlatformIP4Route),
|
.sizeof_route = sizeof (NMPlatformIP4Route),
|
||||||
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp,
|
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip4_route_cmp,
|
||||||
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string,
|
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip4_route_to_string,
|
||||||
.route_add = _vtr_v4_route_add,
|
|
||||||
.metric_normalize = _vtr_v4_metric_normalize,
|
.metric_normalize = _vtr_v4_metric_normalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5344,7 +5736,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v6 = {
|
|||||||
.sizeof_route = sizeof (NMPlatformIP6Route),
|
.sizeof_route = sizeof (NMPlatformIP6Route),
|
||||||
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp,
|
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type)) nm_platform_ip6_route_cmp,
|
||||||
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string,
|
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route, char *buf, gsize len)) nm_platform_ip6_route_to_string,
|
||||||
.route_add = _vtr_v6_route_add,
|
|
||||||
.metric_normalize = nm_utils_ip6_route_metric_normalize,
|
.metric_normalize = nm_utils_ip6_route_metric_normalize,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5416,6 +5807,9 @@ finalize (GObject *object)
|
|||||||
NMPlatform *self = NM_PLATFORM (object);
|
NMPlatform *self = NM_PLATFORM (object);
|
||||||
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
NMPlatformPrivate *priv = NM_PLATFORM_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
nm_clear_g_source (&priv->ip4_dev_route_blacklist_check_id);
|
||||||
|
nm_clear_g_source (&priv->ip4_dev_route_blacklist_gc_timeout_id);
|
||||||
|
g_clear_pointer (&priv->ip4_dev_route_blacklist_hash, g_hash_table_unref);
|
||||||
g_clear_object (&self->_netns);
|
g_clear_object (&self->_netns);
|
||||||
nm_dedup_multi_index_unref (priv->multi_idx);
|
nm_dedup_multi_index_unref (priv->multi_idx);
|
||||||
nmp_cache_free (priv->cache);
|
nmp_cache_free (priv->cache);
|
||||||
|
@@ -63,6 +63,8 @@ typedef gboolean (*NMPObjectPredicateFunc) (const NMPObject *obj,
|
|||||||
#define IFA_F_NOPREFIXROUTE 0x200
|
#define IFA_F_NOPREFIXROUTE 0x200
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */
|
||||||
|
|
||||||
/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
|
/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
|
||||||
* that don't define it. */
|
* that don't define it. */
|
||||||
#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
|
#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
|
||||||
@@ -521,11 +523,6 @@ typedef struct {
|
|||||||
gsize sizeof_route;
|
gsize sizeof_route;
|
||||||
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
|
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
|
||||||
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
|
const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
|
||||||
gboolean (*route_add) (NMPlatform *self,
|
|
||||||
NMPNlmFlags flags,
|
|
||||||
const NMPlatformIPXRoute *route,
|
|
||||||
int ifindex,
|
|
||||||
gint64 metric);
|
|
||||||
guint32 (*metric_normalize) (guint32 metric);
|
guint32 (*metric_normalize) (guint32 metric);
|
||||||
} NMPlatformVTableRoute;
|
} NMPlatformVTableRoute;
|
||||||
|
|
||||||
@@ -1128,6 +1125,16 @@ gboolean nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags, const N
|
|||||||
|
|
||||||
gboolean nm_platform_ip_route_delete (NMPlatform *self, const NMPObject *route);
|
gboolean nm_platform_ip_route_delete (NMPlatform *self, const NMPObject *route);
|
||||||
|
|
||||||
|
gboolean nm_platform_ip_route_sync (NMPlatform *self,
|
||||||
|
int addr_family,
|
||||||
|
int ifindex,
|
||||||
|
GPtrArray *routes,
|
||||||
|
NMPObjectPredicateFunc kernel_delete_predicate,
|
||||||
|
gpointer kernel_delete_userdata);
|
||||||
|
gboolean nm_platform_ip_route_flush (NMPlatform *self,
|
||||||
|
int addr_family,
|
||||||
|
int ifindex);
|
||||||
|
|
||||||
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
|
const char *nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len);
|
||||||
const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);
|
const char *nm_platform_lnk_gre_to_string (const NMPlatformLnkGre *lnk, char *buf, gsize len);
|
||||||
const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len);
|
const char *nm_platform_lnk_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len);
|
||||||
@@ -1218,6 +1225,10 @@ gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMS
|
|||||||
gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
|
||||||
gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
|
||||||
|
|
||||||
|
void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self,
|
||||||
|
int ifindex,
|
||||||
|
GPtrArray *ip4_dev_route_blacklist);
|
||||||
|
|
||||||
struct _NMDedupMultiIndex *nm_platform_get_multi_idx (NMPlatform *self);
|
struct _NMDedupMultiIndex *nm_platform_get_multi_idx (NMPlatform *self);
|
||||||
|
|
||||||
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
||||||
|
@@ -1,974 +0,0 @@
|
|||||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2, or (at your option)
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2015 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "nm-default.h"
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <linux/rtnetlink.h>
|
|
||||||
|
|
||||||
#include "platform/nm-platform.h"
|
|
||||||
#include "platform/nm-platform-utils.h"
|
|
||||||
#include "nm-route-manager.h"
|
|
||||||
|
|
||||||
#include "platform/tests/test-common.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int ifindex0, ifindex1;
|
|
||||||
} test_fixture;
|
|
||||||
|
|
||||||
NMRouteManager *route_manager_get (void);
|
|
||||||
|
|
||||||
NM_DEFINE_SINGLETON_GETTER (NMRouteManager, route_manager_get, NM_TYPE_ROUTE_MANAGER);
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_dev0_ip4 (int ifindex, guint mss_of_first_route, guint32 metric_of_second_route)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
||||||
NMPlatformIP4Route route = { 0 };
|
|
||||||
|
|
||||||
route.ifindex = ifindex;
|
|
||||||
route.mss = 0;
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "6.6.6.0", &route.network);
|
|
||||||
route.plen = 24;
|
|
||||||
route.gateway = INADDR_ANY;
|
|
||||||
route.metric = 20;
|
|
||||||
route.mss = mss_of_first_route;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "7.0.0.0", &route.network);
|
|
||||||
route.plen = 8;
|
|
||||||
inet_pton (AF_INET, "6.6.6.1", &route.gateway);
|
|
||||||
route.metric = metric_of_second_route;
|
|
||||||
route.mss = 0;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_dev1_ip4 (int ifindex)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
||||||
NMPlatformIP4Route route = { 0 };
|
|
||||||
|
|
||||||
route.ifindex = ifindex;
|
|
||||||
route.mss = 0;
|
|
||||||
|
|
||||||
/* Add some route outside of route manager. The route manager
|
|
||||||
* should get rid of it upon sync. */
|
|
||||||
nmtstp_ip4_route_add (NM_PLATFORM_GET,
|
|
||||||
route.ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
nmtst_inet4_from_string ("9.0.0.0"),
|
|
||||||
8,
|
|
||||||
INADDR_ANY,
|
|
||||||
0,
|
|
||||||
10,
|
|
||||||
route.mss);
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "6.6.6.0", &route.network);
|
|
||||||
route.plen = 24;
|
|
||||||
route.gateway = INADDR_ANY;
|
|
||||||
route.metric = 20;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "7.0.0.0", &route.network);
|
|
||||||
route.plen = 8;
|
|
||||||
route.gateway = INADDR_ANY;
|
|
||||||
route.metric = 22;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "8.0.0.0", &route.network);
|
|
||||||
route.plen = 8;
|
|
||||||
inet_pton (AF_INET, "6.6.6.2", &route.gateway);
|
|
||||||
route.metric = 22;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_dev0_ip4 (int ifindex)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
||||||
NMPlatformIP4Route route = { 0 };
|
|
||||||
|
|
||||||
route.ifindex = ifindex;
|
|
||||||
route.mss = 0;
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "6.6.6.0", &route.network);
|
|
||||||
route.plen = 24;
|
|
||||||
route.gateway = INADDR_ANY;
|
|
||||||
route.metric = 20;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
|
|
||||||
inet_pton (AF_INET, "7.0.0.0", &route.network);
|
|
||||||
route.plen = 8;
|
|
||||||
route.gateway = INADDR_ANY;
|
|
||||||
route.metric = 21;
|
|
||||||
g_array_append_val (routes, route);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static GArray *
|
|
||||||
ip_routes (test_fixture *fixture, NMPObjectType obj_type)
|
|
||||||
{
|
|
||||||
const NMPClass *klass;
|
|
||||||
GArray *routes;
|
|
||||||
const NMDedupMultiHeadEntry *pl_head_entry;
|
|
||||||
NMDedupMultiIter iter;
|
|
||||||
const NMPObject *plobj = NULL;
|
|
||||||
guint i;
|
|
||||||
|
|
||||||
g_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
|
||||||
|
|
||||||
klass = nmp_class_from_type (obj_type);
|
|
||||||
|
|
||||||
routes = g_array_new (FALSE, FALSE, klass->sizeof_public);
|
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
int ifindex;
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
ifindex = fixture->ifindex0;
|
|
||||||
else
|
|
||||||
ifindex = fixture->ifindex1;
|
|
||||||
|
|
||||||
pl_head_entry = nm_platform_lookup_addrroute (NM_PLATFORM_GET,
|
|
||||||
obj_type,
|
|
||||||
ifindex);
|
|
||||||
nmp_cache_iter_for_each (&iter, pl_head_entry, &plobj) {
|
|
||||||
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (plobj);
|
|
||||||
|
|
||||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
|
|
||||||
continue;
|
|
||||||
if (r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
|
|
||||||
continue;
|
|
||||||
g_assert (r->ifindex == ifindex);
|
|
||||||
g_assert (nmp_object_is_visible (plobj));
|
|
||||||
g_array_append_vals (routes, r, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return routes;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|
||||||
{
|
|
||||||
GArray *routes;
|
|
||||||
|
|
||||||
NMPlatformIP4Route state1[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 1000,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("7.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = nmtst_inet4_from_string ("6.6.6.1"),
|
|
||||||
.metric = 21021,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("7.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("8.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
NMPlatformIP4Route state2[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("7.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("7.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("8.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
NMPlatformIP4Route state3[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("7.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("8.0.0.0"),
|
|
||||||
.plen = 8,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = nmtst_inet4_from_string ("6.6.6.2"),
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = nmtst_inet4_from_string ("6.6.6.0"),
|
|
||||||
.plen = 24,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = INADDR_ANY,
|
|
||||||
/* this is a ghost entry because we synced ifindex0 and restore the route
|
|
||||||
* with metric 20 (above). But we don't remove the metric 21. */
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
.scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
setup_dev0_ip4 (fixture->ifindex0, 1000, 21021);
|
|
||||||
setup_dev1_ip4 (fixture->ifindex1);
|
|
||||||
g_test_assert_expected_messages ();
|
|
||||||
|
|
||||||
/* - 6.6.6.0/24 on dev0 won over 6.6.6.0/24 on dev1
|
|
||||||
* - 6.6.6.0/24 on dev1 has metric bumped.
|
|
||||||
* - 7.0.0.0/8 route, metric 21021 added
|
|
||||||
* - 7.0.0.0/8 route, metric 22 added
|
|
||||||
* - 8.0.0.0/8 could be added. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP4_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
|
||||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
setup_dev1_ip4 (fixture->ifindex1);
|
|
||||||
g_test_assert_expected_messages ();
|
|
||||||
|
|
||||||
setup_dev0_ip4 (fixture->ifindex0, 0, 21);
|
|
||||||
|
|
||||||
/* Ensure nothing changed. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP4_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
|
||||||
state1[0].mss = 0;
|
|
||||||
state1[1].metric = 21;
|
|
||||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
update_dev0_ip4 (fixture->ifindex0);
|
|
||||||
|
|
||||||
/* minor changes in the routes. Quite similar to state1. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP4_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state2));
|
|
||||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state2, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
nm_route_manager_route_flush (route_manager_get (), fixture->ifindex0);
|
|
||||||
|
|
||||||
/* 6.6.6.0/24 is now on dev1
|
|
||||||
* 6.6.6.0/24 is also still on dev1 with bumped metric 21.
|
|
||||||
* 7.0.0.0/8 gone from dev0, still present on dev1
|
|
||||||
* 8.0.0.0/8 is present on dev1
|
|
||||||
* No dev0 routes left. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP4_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state3));
|
|
||||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state3, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
nm_route_manager_route_flush (route_manager_get (), fixture->ifindex1);
|
|
||||||
|
|
||||||
/* No routes left. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP4_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, 0);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_dev0_ip6 (int ifindex)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
|
|
||||||
NMPlatformIP6Route *route;
|
|
||||||
|
|
||||||
/* Add an address so that a route to the gateway below gets added. */
|
|
||||||
nm_platform_ip6_address_add (NM_PLATFORM_GET,
|
|
||||||
ifindex,
|
|
||||||
*nmtst_inet6_from_string ("2001:db8:8086::666"),
|
|
||||||
64,
|
|
||||||
in6addr_any,
|
|
||||||
3600,
|
|
||||||
3600,
|
|
||||||
0);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
20,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
|
|
||||||
64,
|
|
||||||
"2001:db8:8086::1",
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
21,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
nm_route_manager_ip6_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setup_dev1_ip6 (int ifindex)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
|
|
||||||
NMPlatformIP6Route *route;
|
|
||||||
|
|
||||||
/* Add some route outside of route manager. The route manager
|
|
||||||
* should get rid of it upon sync. */
|
|
||||||
nmtstp_ip6_route_add (NM_PLATFORM_GET,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
*nmtst_inet6_from_string ("2001:db8:8088::"),
|
|
||||||
48,
|
|
||||||
in6addr_any,
|
|
||||||
in6addr_any,
|
|
||||||
10,
|
|
||||||
0);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
20,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
1024,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:d34d::",
|
|
||||||
64,
|
|
||||||
"2001:db8:8086::2",
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
20,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
|
|
||||||
64,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
22,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
nm_route_manager_ip6_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_dev0_ip6 (int ifindex)
|
|
||||||
{
|
|
||||||
GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
|
|
||||||
NMPlatformIP6Route *route;
|
|
||||||
|
|
||||||
/* Add an address so that a route to the gateway below gets added. */
|
|
||||||
nm_platform_ip6_address_add (NM_PLATFORM_GET,
|
|
||||||
ifindex,
|
|
||||||
*nmtst_inet6_from_string ("2001:db8:8086::2"),
|
|
||||||
64,
|
|
||||||
in6addr_any,
|
|
||||||
3600,
|
|
||||||
3600,
|
|
||||||
0);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:8086::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
20,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:1337::",
|
|
||||||
48,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
0,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
route = nmtst_platform_ip6_route_full ("2001:db8:abad:c0de::",
|
|
||||||
64,
|
|
||||||
NULL,
|
|
||||||
ifindex,
|
|
||||||
NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
21,
|
|
||||||
0);
|
|
||||||
g_array_append_val (routes, *route);
|
|
||||||
|
|
||||||
nm_route_manager_ip6_route_sync (route_manager_get (), ifindex, routes, TRUE, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|
||||||
{
|
|
||||||
GArray *routes;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
NMPlatformIP6Route state1[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1024,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = *nmtst_inet6_from_string ("2001:db8:8086::1"),
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1025,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:d34d::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = *nmtst_inet6_from_string ("2001:db8:8086::2"),
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
NMPlatformIP6Route state2[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1024,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1025,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:d34d::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = *nmtst_inet6_from_string ("2001:db8:8086::2"),
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
NMPlatformIP6Route state3[] = {
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 22,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1024,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:1337::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 1025,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:8086::"),
|
|
||||||
.plen = 48,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = in6addr_any,
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:d34d::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex1,
|
|
||||||
.gateway = *nmtst_inet6_from_string ("2001:db8:8086::2"),
|
|
||||||
.metric = 20,
|
|
||||||
.mss = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
setup_dev0_ip6 (fixture->ifindex0);
|
|
||||||
setup_dev1_ip6 (fixture->ifindex1);
|
|
||||||
g_test_assert_expected_messages ();
|
|
||||||
|
|
||||||
/* 2001:db8:8086::/48 on dev0 won over 2001:db8:8086::/48 on dev1
|
|
||||||
* 2001:db8:d34d::/64 on dev1 could not be added
|
|
||||||
* 2001:db8:1337::/48 on dev0 won over 2001:db8:1337::/48 on dev1 and has metric 1024
|
|
||||||
* 2001:db8:abad:c0de::/64 routes did not clash */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP6_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
|
||||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
|
|
||||||
setup_dev1_ip6 (fixture->ifindex1);
|
|
||||||
g_test_assert_expected_messages ();
|
|
||||||
setup_dev0_ip6 (fixture->ifindex0);
|
|
||||||
|
|
||||||
/* Ensure nothing changed. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP6_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
|
||||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
update_dev0_ip6 (fixture->ifindex0);
|
|
||||||
|
|
||||||
/* 2001:db8:abad:c0de::/64 on dev0 was updated for gateway removal*/
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP6_ROUTE);
|
|
||||||
if (routes->len != G_N_ELEMENTS (state2)) {
|
|
||||||
NMPlatformIP6Route rr;
|
|
||||||
|
|
||||||
/* hm, seems kernel may wrongly treat IPv6 gateway for `ip route replace`.
|
|
||||||
* See rh#1480427.
|
|
||||||
*
|
|
||||||
* We would expect that `ip route replace` replaces an existing route.
|
|
||||||
* However, kernel may not do so, and instead prepend it.
|
|
||||||
*
|
|
||||||
* Work around that, by checking if such a route exists and accept
|
|
||||||
* it. */
|
|
||||||
g_assert (nmtstp_is_root_test ());
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state2) + 1);
|
|
||||||
rr = ((NMPlatformIP6Route) {
|
|
||||||
.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER),
|
|
||||||
.network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"),
|
|
||||||
.plen = 64,
|
|
||||||
.ifindex = fixture->ifindex0,
|
|
||||||
.gateway = *nmtst_inet6_from_string ("2001:db8:8086::1"),
|
|
||||||
.metric = 21,
|
|
||||||
.mss = 0,
|
|
||||||
});
|
|
||||||
for (i = 0; i < routes->len; i++) {
|
|
||||||
if (nm_platform_ip6_route_cmp (&rr,
|
|
||||||
&g_array_index (routes, NMPlatformIP6Route, i),
|
|
||||||
NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) != 0)
|
|
||||||
continue;
|
|
||||||
g_array_remove_index (routes, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state2, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
nm_route_manager_route_flush (route_manager_get (), fixture->ifindex0);
|
|
||||||
|
|
||||||
/* 2001:db8:abad:c0de::/64 on dev1 is still there, went away from dev0
|
|
||||||
* 2001:db8:8086::/48 is now on dev1
|
|
||||||
* 2001:db8:1337::/48 is now on dev1, metric of 1024 still applies
|
|
||||||
* 2001:db8:d34d::/64 is present now that 2001:db8:8086::/48 is on dev1
|
|
||||||
* No dev0 routes left. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP6_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state3));
|
|
||||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state3, routes->len, TRUE);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
|
|
||||||
nm_route_manager_route_flush (route_manager_get (), fixture->ifindex1);
|
|
||||||
|
|
||||||
/* No routes left. */
|
|
||||||
routes = ip_routes (fixture, NMP_OBJECT_TYPE_IP6_ROUTE);
|
|
||||||
g_assert_cmpint (routes->len, ==, 0);
|
|
||||||
g_array_free (routes, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
_assert_route_check (const NMPlatformVTableRoute *vtable, gboolean has, const NMPlatformIPXRoute *route)
|
|
||||||
{
|
|
||||||
const NMPlatformIPXRoute *r;
|
|
||||||
NMPlatformIPXRoute c;
|
|
||||||
|
|
||||||
g_assert (route);
|
|
||||||
|
|
||||||
if (vtable->is_ip4)
|
|
||||||
r = (const NMPlatformIPXRoute *) nmtstp_ip4_route_get (NM_PLATFORM_GET, route->rx.ifindex, route->r4.network, route->rx.plen, route->rx.metric, route->r4.tos);
|
|
||||||
else
|
|
||||||
r = (const NMPlatformIPXRoute *) nmtstp_ip6_route_get (NM_PLATFORM_GET, route->rx.ifindex, &route->r6.network, route->rx.plen, route->rx.metric, &route->r6.src, route->r6.src_plen);
|
|
||||||
|
|
||||||
if (!has) {
|
|
||||||
g_assert (!r);
|
|
||||||
} else {
|
|
||||||
char buf[sizeof (_nm_utils_to_string_buffer)];
|
|
||||||
|
|
||||||
if (r) {
|
|
||||||
if (vtable->is_ip4)
|
|
||||||
c.r4 = route->r4;
|
|
||||||
else
|
|
||||||
c.r6 = route->r6;
|
|
||||||
c.rx.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (c.rx.rt_source);
|
|
||||||
}
|
|
||||||
if (!r || vtable->route_cmp (r, &c, NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) != 0) {
|
|
||||||
g_error ("Invalid route. Expect %s, has %s",
|
|
||||||
vtable->route_to_string (&c, NULL, 0),
|
|
||||||
vtable->route_to_string (r, buf, sizeof (buf)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
test_ip4_full_sync (test_fixture *fixture, gconstpointer user_data)
|
|
||||||
{
|
|
||||||
const NMPlatformVTableRoute *vtable = &nm_platform_vtable_route_v4;
|
|
||||||
gs_unref_array GArray *routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
||||||
NMPlatformIP4Route r01, r02, r03;
|
|
||||||
|
|
||||||
nm_log_dbg (LOGD_CORE, "TEST start test_ip4_full_sync(): start");
|
|
||||||
|
|
||||||
r01 = *nmtst_platform_ip4_route_full ("12.3.4.0", 24, NULL,
|
|
||||||
fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
100, 0, RT_SCOPE_LINK, NULL);
|
|
||||||
r02 = *nmtst_platform_ip4_route_full ("13.4.5.6", 32, "12.3.4.1",
|
|
||||||
fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
100, 0, RT_SCOPE_UNIVERSE, NULL);
|
|
||||||
r03 = *nmtst_platform_ip4_route_full ("14.5.6.7", 32, "12.3.4.1",
|
|
||||||
fixture->ifindex0, NM_IP_CONFIG_SOURCE_USER,
|
|
||||||
110, 0, RT_SCOPE_UNIVERSE, NULL);
|
|
||||||
g_array_set_size (routes, 2);
|
|
||||||
g_array_index (routes, NMPlatformIP4Route, 0) = r01;
|
|
||||||
g_array_index (routes, NMPlatformIP4Route, 1) = r02;
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE);
|
|
||||||
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);
|
|
||||||
_assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03);
|
|
||||||
|
|
||||||
vtable->route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, (const NMPlatformIPXRoute *) &r03, 0, -1);
|
|
||||||
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE);
|
|
||||||
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r02);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03);
|
|
||||||
|
|
||||||
g_array_set_size (routes, 1);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), fixture->ifindex0, routes, TRUE, FALSE);
|
|
||||||
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
|
||||||
_assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02);
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r03);
|
|
||||||
|
|
||||||
nm_route_manager_ip4_route_sync (route_manager_get (), fixture->ifindex0, routes, TRUE, TRUE);
|
|
||||||
|
|
||||||
_assert_route_check (vtable, TRUE, (const NMPlatformIPXRoute *) &r01);
|
|
||||||
_assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r02);
|
|
||||||
_assert_route_check (vtable, FALSE, (const NMPlatformIPXRoute *) &r03);
|
|
||||||
|
|
||||||
nm_log_dbg (LOGD_CORE, "TEST test_ip4_full_sync(): done");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
static void
|
|
||||||
fixture_setup (test_fixture *fixture, gconstpointer user_data)
|
|
||||||
{
|
|
||||||
SignalData *link_added;
|
|
||||||
|
|
||||||
link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
|
||||||
NM_PLATFORM_SIGNAL_ADDED,
|
|
||||||
link_callback,
|
|
||||||
"nm-test-device0");
|
|
||||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device0"));
|
|
||||||
g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "nm-test-device0"));
|
|
||||||
g_assert (nm_platform_link_dummy_add (NM_PLATFORM_GET, "nm-test-device0", NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
|
||||||
accept_signal (link_added);
|
|
||||||
free_signal (link_added);
|
|
||||||
fixture->ifindex0 = nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device0");
|
|
||||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex0, NULL));
|
|
||||||
|
|
||||||
link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
|
||||||
NM_PLATFORM_SIGNAL_ADDED,
|
|
||||||
link_callback,
|
|
||||||
"nm-test-device1");
|
|
||||||
nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device1"));
|
|
||||||
g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, "nm-test-device1"));
|
|
||||||
g_assert (nm_platform_link_dummy_add (NM_PLATFORM_GET, "nm-test-device1", NULL) == NM_PLATFORM_ERROR_SUCCESS);
|
|
||||||
accept_signal (link_added);
|
|
||||||
free_signal (link_added);
|
|
||||||
fixture->ifindex1 = nm_platform_link_get_ifindex (NM_PLATFORM_GET, "nm-test-device1");
|
|
||||||
g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, fixture->ifindex1, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
fixture_teardown (test_fixture *fixture, gconstpointer user_data)
|
|
||||||
{
|
|
||||||
nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex0);
|
|
||||||
nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
|
|
||||||
NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP;
|
|
||||||
|
|
||||||
void
|
|
||||||
_nmtstp_init_tests (int *argc, char ***argv)
|
|
||||||
{
|
|
||||||
nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
_nmtstp_setup_tests (void)
|
|
||||||
{
|
|
||||||
g_test_add ("/route-manager/ip4", test_fixture, NULL, fixture_setup, test_ip4, fixture_teardown);
|
|
||||||
g_test_add ("/route-manager/ip6", test_fixture, NULL, fixture_setup, test_ip6, fixture_teardown);
|
|
||||||
g_test_add ("/route-manager/ip4-full-sync", test_fixture, NULL, fixture_setup, test_ip4_full_sync, fixture_teardown);
|
|
||||||
}
|
|
@@ -45,7 +45,6 @@
|
|||||||
#include "nm-core-internal.h"
|
#include "nm-core-internal.h"
|
||||||
#include "nm-pacrunner-manager.h"
|
#include "nm-pacrunner-manager.h"
|
||||||
#include "nm-default-route-manager.h"
|
#include "nm-default-route-manager.h"
|
||||||
#include "nm-route-manager.h"
|
|
||||||
#include "nm-firewall-manager.h"
|
#include "nm-firewall-manager.h"
|
||||||
#include "nm-config.h"
|
#include "nm-config.h"
|
||||||
#include "nm-vpn-plugin-info.h"
|
#include "nm-vpn-plugin-info.h"
|
||||||
@@ -394,9 +393,11 @@ vpn_cleanup (NMVpnConnection *self, NMDevice *parent_dev)
|
|||||||
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
|
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
|
||||||
|
|
||||||
if (priv->ip_ifindex) {
|
if (priv->ip_ifindex) {
|
||||||
nm_platform_link_set_down (nm_netns_get_platform (priv->netns), priv->ip_ifindex);
|
NMPlatform *platform = nm_netns_get_platform (priv->netns);
|
||||||
nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), priv->ip_ifindex);
|
|
||||||
nm_platform_ip_address_flush (nm_netns_get_platform (priv->netns), AF_UNSPEC, priv->ip_ifindex);
|
nm_platform_link_set_down (platform, priv->ip_ifindex);
|
||||||
|
nm_platform_ip_route_flush (platform, AF_UNSPEC, priv->ip_ifindex);
|
||||||
|
nm_platform_ip_address_flush (platform, AF_UNSPEC, priv->ip_ifindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_parent_device_config (self, parent_dev);
|
remove_parent_device_config (self, parent_dev);
|
||||||
@@ -1104,21 +1105,17 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
|
|||||||
nm_platform_link_set_up (nm_netns_get_platform (priv->netns), priv->ip_ifindex, NULL);
|
nm_platform_link_set_up (nm_netns_get_platform (priv->netns), priv->ip_ifindex, NULL);
|
||||||
|
|
||||||
if (priv->ip4_config) {
|
if (priv->ip4_config) {
|
||||||
|
nm_assert (priv->ip_ifindex == nm_ip4_config_get_ifindex (priv->ip4_config));
|
||||||
if (!nm_ip4_config_commit (priv->ip4_config,
|
if (!nm_ip4_config_commit (priv->ip4_config,
|
||||||
nm_netns_get_platform (priv->netns),
|
nm_netns_get_platform (priv->netns),
|
||||||
nm_netns_get_route_manager (priv->netns),
|
|
||||||
priv->ip_ifindex,
|
|
||||||
TRUE,
|
|
||||||
nm_vpn_connection_get_ip4_route_metric (self)))
|
nm_vpn_connection_get_ip4_route_metric (self)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->ip6_config) {
|
if (priv->ip6_config) {
|
||||||
|
nm_assert (priv->ip_ifindex == nm_ip6_config_get_ifindex (priv->ip6_config));
|
||||||
if (!nm_ip6_config_commit (priv->ip6_config,
|
if (!nm_ip6_config_commit (priv->ip6_config,
|
||||||
nm_netns_get_platform (priv->netns),
|
nm_netns_get_platform (priv->netns)))
|
||||||
nm_netns_get_route_manager (priv->netns),
|
|
||||||
priv->ip_ifindex,
|
|
||||||
TRUE))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user