mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-26 11:10:09 +01:00
platform: merge branch 'th/platform-route-pt3'
Continue with the routing rework. Get rid of NMRouteManager and configure non-exclusive routes. https://github.com/NetworkManager/NetworkManager/pull/25
This commit is contained in:
commit
f4d88630b0
42 changed files with 2207 additions and 3287 deletions
27
Makefile.am
27
Makefile.am
|
|
@ -1323,9 +1323,6 @@ src_libNetworkManagerBase_la_SOURCES = \
|
|||
src/nm-ip6-config.c \
|
||||
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.h \
|
||||
src/dhcp/nm-dhcp-client-logging.h \
|
||||
|
|
@ -2961,8 +2958,6 @@ check_programs += \
|
|||
src/tests/test-general-with-expect \
|
||||
src/tests/test-ip4-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-systemd \
|
||||
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_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_LDADD = \
|
||||
src/libsystemd-nm.la \
|
||||
|
|
|
|||
|
|
@ -78,6 +78,26 @@ G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_nm_g_slice_free_fcn (void)
|
||||
{
|
||||
gpointer p;
|
||||
|
||||
p = g_slice_new (gint64);
|
||||
(nm_g_slice_free_fcn (gint64)) (p);
|
||||
|
||||
p = g_slice_new (gint32);
|
||||
(nm_g_slice_free_fcn (gint32)) (p);
|
||||
|
||||
p = g_slice_new (gint);
|
||||
(nm_g_slice_free_fcn (gint)) (p);
|
||||
|
||||
p = g_slice_new (gint64);
|
||||
nm_g_slice_free_fcn_gint64 (p);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int val;
|
||||
int idx;
|
||||
|
|
@ -6177,6 +6197,7 @@ int main (int argc, char **argv)
|
|||
{
|
||||
nmtst_init (&argc, &argv, TRUE);
|
||||
|
||||
g_test_add_func ("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn);
|
||||
g_test_add_func ("/core/general/test_c_list_sort", test_c_list_sort);
|
||||
g_test_add_func ("/core/general/test_dedup_multi", test_dedup_multi);
|
||||
g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ nm_dedup_multi_idx_type_init (NMDedupMultiIdxType *idx_type,
|
|||
/*****************************************************************************/
|
||||
|
||||
static NMDedupMultiEntry *
|
||||
_entry_lookup_obj (NMDedupMultiIndex *self,
|
||||
_entry_lookup_obj (const NMDedupMultiIndex *self,
|
||||
const NMDedupMultiIdxType *idx_type,
|
||||
const NMDedupMultiObj *obj)
|
||||
{
|
||||
|
|
@ -92,7 +92,7 @@ _entry_lookup_obj (NMDedupMultiIndex *self,
|
|||
}
|
||||
|
||||
static NMDedupMultiHeadEntry *
|
||||
_entry_lookup_head (NMDedupMultiIndex *self,
|
||||
_entry_lookup_head (const NMDedupMultiIndex *self,
|
||||
const NMDedupMultiIdxType *idx_type,
|
||||
const NMDedupMultiObj *obj)
|
||||
{
|
||||
|
|
@ -253,6 +253,8 @@ _add (NMDedupMultiIndex *self,
|
|||
}));
|
||||
|
||||
if (entry) {
|
||||
gboolean changed = FALSE;
|
||||
|
||||
nm_dedup_multi_entry_set_dirty (entry, FALSE);
|
||||
|
||||
nm_assert (!head_existing || entry->head == head_existing);
|
||||
|
|
@ -270,11 +272,13 @@ _add (NMDedupMultiIndex *self,
|
|||
&& entry->lst_entries.next != &entry_order->lst_entries) {
|
||||
c_list_unlink (&entry->lst_entries);
|
||||
c_list_link_before ((CList *) &entry_order->lst_entries, &entry->lst_entries);
|
||||
changed = TRUE;
|
||||
}
|
||||
} else {
|
||||
if (entry->lst_entries.prev != &entry->head->lst_entries_head) {
|
||||
c_list_unlink (&entry->lst_entries);
|
||||
c_list_link_front ((CList *) &entry->head->lst_entries_head, &entry->lst_entries);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -284,11 +288,13 @@ _add (NMDedupMultiIndex *self,
|
|||
&& entry->lst_entries.prev != &entry_order->lst_entries) {
|
||||
c_list_unlink (&entry->lst_entries);
|
||||
c_list_link_after ((CList *) &entry_order->lst_entries, &entry->lst_entries);
|
||||
changed = TRUE;
|
||||
}
|
||||
} else {
|
||||
if (entry->lst_entries.next != &entry->head->lst_entries_head) {
|
||||
c_list_unlink (&entry->lst_entries);
|
||||
c_list_link_tail ((CList *) &entry->head->lst_entries_head, &entry->lst_entries);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -303,7 +309,7 @@ _add (NMDedupMultiIndex *self,
|
|||
entry->obj)) {
|
||||
NM_SET_OUT (out_entry, entry);
|
||||
NM_SET_OUT (out_obj_old, nm_dedup_multi_obj_ref (entry->obj));
|
||||
return FALSE;
|
||||
return changed;
|
||||
}
|
||||
|
||||
obj_new = nm_dedup_multi_index_obj_intern (self, obj);
|
||||
|
|
@ -620,13 +626,22 @@ nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
|
|||
guint
|
||||
nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
|
||||
NMDedupMultiIdxType *idx_type,
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj)
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj,
|
||||
/*const NMDedupMultiObj ** */ gconstpointer *out_obj)
|
||||
{
|
||||
const NMDedupMultiEntry *entry;
|
||||
|
||||
entry = nm_dedup_multi_index_lookup_obj (self, idx_type, obj);
|
||||
if (!entry)
|
||||
if (!entry) {
|
||||
NM_SET_OUT (out_obj, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* since we are about to remove the object, we obviously pass
|
||||
* a reference to @out_obj, the caller MUST unref the object,
|
||||
* if he chooses to provide @out_obj. */
|
||||
NM_SET_OUT (out_obj, nm_dedup_multi_obj_ref (entry->obj));
|
||||
|
||||
_remove_entry (self, (NMDedupMultiEntry *) entry, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -667,7 +682,7 @@ nm_dedup_multi_index_remove_idx (NMDedupMultiIndex *self,
|
|||
* Returns: the cache entry or %NULL if the entry wasn't found.
|
||||
*/
|
||||
const NMDedupMultiEntry *
|
||||
nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
|
||||
nm_dedup_multi_index_lookup_obj (const NMDedupMultiIndex *self,
|
||||
const NMDedupMultiIdxType *idx_type,
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj)
|
||||
{
|
||||
|
|
@ -693,7 +708,7 @@ nm_dedup_multi_index_lookup_obj (NMDedupMultiIndex *self,
|
|||
* Returns: the cache entry or %NULL if the entry wasn't found.
|
||||
*/
|
||||
const NMDedupMultiHeadEntry *
|
||||
nm_dedup_multi_index_lookup_head (NMDedupMultiIndex *self,
|
||||
nm_dedup_multi_index_lookup_head (const NMDedupMultiIndex *self,
|
||||
const NMDedupMultiIdxType *idx_type,
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -278,11 +278,11 @@ gboolean nm_dedup_multi_index_add (NMDedupMultiIndex *self,
|
|||
const NMDedupMultiEntry **out_entry,
|
||||
/* 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 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 NMDedupMultiObj * */ gconstpointer obj);
|
||||
|
||||
|
|
@ -291,7 +291,8 @@ guint nm_dedup_multi_index_remove_entry (NMDedupMultiIndex *self,
|
|||
|
||||
guint nm_dedup_multi_index_remove_obj (NMDedupMultiIndex *self,
|
||||
NMDedupMultiIdxType *idx_type,
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj);
|
||||
/*const NMDedupMultiObj * */ gconstpointer obj,
|
||||
/*const NMDedupMultiObj ** */ gconstpointer *out_obj);
|
||||
|
||||
guint nm_dedup_multi_index_remove_head (NMDedupMultiIndex *self,
|
||||
NMDedupMultiIdxType *idx_type,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,53 @@ gint _nm_utils_ascii_str_to_bool (const char *str,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _nm_g_slice_free_fcn_define(mem_size) \
|
||||
static inline void \
|
||||
_nm_g_slice_free_fcn_##mem_size (gpointer mem_block) \
|
||||
{ \
|
||||
g_slice_free1 (mem_size, mem_block); \
|
||||
}
|
||||
|
||||
_nm_g_slice_free_fcn_define (1)
|
||||
_nm_g_slice_free_fcn_define (2)
|
||||
_nm_g_slice_free_fcn_define (4)
|
||||
_nm_g_slice_free_fcn_define (8)
|
||||
_nm_g_slice_free_fcn_define (16)
|
||||
|
||||
#define _nm_g_slice_free_fcn1(mem_size) \
|
||||
({ \
|
||||
void (*_fcn) (gpointer); \
|
||||
\
|
||||
/* If mem_size is a compile time constant, the compiler
|
||||
* will be able to optimize this. Hence, you don't want
|
||||
* to call this with a non-constant size argument. */ \
|
||||
switch (mem_size) { \
|
||||
case 1: _fcn = _nm_g_slice_free_fcn_1; break; \
|
||||
case 2: _fcn = _nm_g_slice_free_fcn_2; break; \
|
||||
case 4: _fcn = _nm_g_slice_free_fcn_4; break; \
|
||||
case 8: _fcn = _nm_g_slice_free_fcn_8; break; \
|
||||
case 16: _fcn = _nm_g_slice_free_fcn_16; break; \
|
||||
default: g_assert_not_reached (); _fcn = NULL; break; \
|
||||
} \
|
||||
_fcn; \
|
||||
})
|
||||
|
||||
/**
|
||||
* nm_g_slice_free_fcn:
|
||||
* @type: type argument for sizeof() operator that you would
|
||||
* pass to g_slice_new().
|
||||
*
|
||||
* Returns: a function pointer with GDestroyNotify signature
|
||||
* for g_slice_free(type,*).
|
||||
*
|
||||
* Only certain types are implemented. You'll get an assertion
|
||||
* using the wrong type. */
|
||||
#define nm_g_slice_free_fcn(type) (_nm_g_slice_free_fcn1 (sizeof (type)))
|
||||
|
||||
#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn (gint64))
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* NMUtilsError:
|
||||
* @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create bond interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create bridge interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create dummy interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
|
||||
nm_device_get_iface (device),
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -324,7 +324,7 @@ unrealize (NMDevice *device, GError **error)
|
|||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to remove InfiniBand P_Key interface '%s': %s",
|
||||
nm_device_get_iface (device),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create GRE interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
|
@ -670,10 +670,10 @@ create_and_realize (NMDevice *device,
|
|||
plerr = nm_platform_link_sit_add (nm_device_get_platform (device), iface, &lnk_sit, out_plink);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create SIT interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
"Failed to create SIT interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
|
@ -696,10 +696,10 @@ create_and_realize (NMDevice *device,
|
|||
plerr = nm_platform_link_ipip_add (nm_device_get_platform (device), iface, &lnk_ipip, out_plink);
|
||||
if (plerr != NM_PLATFORM_ERROR_SUCCESS) {
|
||||
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
|
||||
"Failed to create IPIP interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
"Failed to create IPIP interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
|
@ -728,7 +728,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create IPIP interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -720,7 +720,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create macsec interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ create_and_realize (NMDevice *device,
|
|||
lnk.tap ? "macvtap" : "macvlan",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create TUN/TAP interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create VLAN interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create VXLAN interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@
|
|||
#include "dns/nm-dns-manager.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-default-route-manager.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "systemd/nm-sd.h"
|
||||
#include "nm-lldp-listener.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,
|
||||
NMIP4Config *config,
|
||||
guint32 default_route_metric,
|
||||
gboolean commit,
|
||||
gboolean routes_full_sync);
|
||||
gboolean commit);
|
||||
static gboolean ip4_config_merge_and_apply (NMDevice *self,
|
||||
NMIP4Config *config,
|
||||
gboolean commit);
|
||||
|
||||
static gboolean nm_device_set_ip6_config (NMDevice *self,
|
||||
NMIP6Config *config,
|
||||
gboolean commit,
|
||||
gboolean routes_full_sync);
|
||||
gboolean commit);
|
||||
static gboolean ip6_config_merge_and_apply (NMDevice *self,
|
||||
gboolean commit);
|
||||
|
||||
|
|
@ -2767,6 +2764,101 @@ 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)
|
||||
|| r->table_coerced)
|
||||
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)
|
||||
|| r->table_coerced)
|
||||
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
|
||||
ip4_rp_filter_update (NMDevice *self)
|
||||
{
|
||||
|
|
@ -2792,20 +2884,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
|
||||
link_changed (NMDevice *self, const NMPlatformLink *pllink)
|
||||
{
|
||||
|
|
@ -3846,8 +3924,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_INET, FALSE, TRUE);
|
||||
_update_default_route (self, AF_INET6, FALSE, TRUE);
|
||||
nm_device_set_ip4_config (self, NULL, 0, FALSE, FALSE);
|
||||
nm_device_set_ip6_config (self, NULL, FALSE, FALSE);
|
||||
nm_device_set_ip4_config (self, NULL, 0, FALSE);
|
||||
nm_device_set_ip6_config (self, NULL, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5461,9 +5539,9 @@ _device_get_default_route_from_platform (NMDevice *self, int addr_family, NMPlat
|
|||
guint32 m;
|
||||
const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (plobj);
|
||||
|
||||
if (r->ifindex != ifindex)
|
||||
continue;
|
||||
if (r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
|
||||
if ( r->ifindex != ifindex
|
||||
|| r->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL
|
||||
|| r->table_coerced)
|
||||
continue;
|
||||
|
||||
/* if there are several default routes, find the one with the best metric */
|
||||
|
|
@ -5582,7 +5660,6 @@ ip4_config_merge_and_apply (NMDevice *self,
|
|||
const guint32 default_route_metric = nm_device_get_ip4_route_metric (self);
|
||||
guint32 gateway;
|
||||
gboolean connection_has_default_route, connection_is_never_default;
|
||||
gboolean routes_full_sync;
|
||||
gboolean ignore_auto_routes = FALSE;
|
||||
gboolean ignore_auto_dns = FALSE;
|
||||
gboolean auto_method = FALSE;
|
||||
|
|
@ -5749,11 +5826,7 @@ END_ADD_DEFAULT_ROUTE:
|
|||
NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite);
|
||||
}
|
||||
|
||||
routes_full_sync = 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);
|
||||
success = nm_device_set_ip4_config (self, composite, default_route_metric, commit);
|
||||
g_object_unref (composite);
|
||||
|
||||
if (commit)
|
||||
|
|
@ -6308,7 +6381,6 @@ ip6_config_merge_and_apply (NMDevice *self,
|
|||
gboolean has_direct_route;
|
||||
const struct in6_addr *gateway;
|
||||
gboolean connection_has_default_route, connection_is_never_default;
|
||||
gboolean routes_full_sync;
|
||||
gboolean ignore_auto_routes = FALSE;
|
||||
gboolean ignore_auto_dns = FALSE;
|
||||
gboolean auto_method = FALSE;
|
||||
|
|
@ -6497,11 +6569,7 @@ END_ADD_DEFAULT_ROUTE:
|
|||
}
|
||||
}
|
||||
|
||||
routes_full_sync = 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);
|
||||
success = nm_device_set_ip6_config (self, composite, commit);
|
||||
g_object_unref (composite);
|
||||
if (commit)
|
||||
priv->v6_commit_first_time = FALSE;
|
||||
|
|
@ -7319,26 +7387,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
{
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int i;
|
||||
int system_support;
|
||||
guint32 ifa_flags = 0x00;
|
||||
|
||||
/*
|
||||
* Check, whether kernel is recent enough to help user space handling RA.
|
||||
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
||||
* addresses as /128. The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address.
|
||||
**/
|
||||
system_support = nm_platform_check_support_kernel_extended_ifa_flags (nm_device_get_platform (self));
|
||||
|
||||
if (system_support)
|
||||
ifa_flags = IFA_F_NOPREFIXROUTE;
|
||||
if ( priv->ndisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
|| priv->ndisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
{
|
||||
/* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
}
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (priv->act_request);
|
||||
|
||||
|
|
@ -7354,49 +7403,35 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_addresses (priv->ac_ip6_config);
|
||||
guint8 plen;
|
||||
guint32 ifa_flags;
|
||||
|
||||
/* ndisc->addresses contains at most max_addresses entries.
|
||||
* This is different from what the kernel does, which
|
||||
* also counts static and temporary addresses when checking
|
||||
* max_addresses.
|
||||
**/
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
NMPlatformIP6Address address;
|
||||
/* Check, whether kernel is recent enough to help user space handling RA.
|
||||
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
||||
* addresses as /128. The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address. */
|
||||
ifa_flags = 0;
|
||||
if (nm_platform_check_support_kernel_extended_ifa_flags (nm_device_get_platform (self))) {
|
||||
ifa_flags |= IFA_F_NOPREFIXROUTE;
|
||||
if (NM_IN_SET (priv->ndisc_use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
plen = 64;
|
||||
} else
|
||||
plen = 128;
|
||||
|
||||
memset (&address, 0, sizeof (address));
|
||||
address.address = discovered_address->address;
|
||||
address.plen = system_support ? 64 : 128;
|
||||
address.timestamp = discovered_address->timestamp;
|
||||
address.lifetime = discovered_address->lifetime;
|
||||
address.preferred = discovered_address->preferred;
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
address.n_ifa_flags = ifa_flags;
|
||||
|
||||
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
||||
}
|
||||
nm_ip6_config_reset_addresses_ndisc (priv->ac_ip6_config,
|
||||
rdata->addresses,
|
||||
rdata->addresses_n,
|
||||
plen,
|
||||
ifa_flags);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_routes (priv->ac_ip6_config);
|
||||
|
||||
for (i = 0; i < rdata->routes_n; i++) {
|
||||
const NMNDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMPlatformIP6Route route = {
|
||||
.network = discovered_route->network,
|
||||
.plen = discovered_route->plen,
|
||||
.gateway = discovered_route->gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||
.metric = nm_device_get_ip6_route_metric (self),
|
||||
};
|
||||
|
||||
nm_ip6_config_add_route (priv->ac_ip6_config, &route);
|
||||
}
|
||||
nm_ip6_config_reset_routes_ndisc (priv->ac_ip6_config,
|
||||
rdata->routes,
|
||||
rdata->routes_n,
|
||||
nm_device_get_ip6_route_metric (self));
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
|
||||
|
|
@ -7696,7 +7731,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable)
|
|||
LOGD_IP6,
|
||||
"failed to %s userspace IPv6LL address handling (%s)",
|
||||
detail,
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
|
|
@ -9853,46 +9888,35 @@ static gboolean
|
|||
nm_device_set_ip4_config (NMDevice *self,
|
||||
NMIP4Config *new_config,
|
||||
guint32 default_route_metric,
|
||||
gboolean commit,
|
||||
gboolean routes_full_sync)
|
||||
gboolean commit)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMIP4Config *old_config = NULL;
|
||||
gboolean has_changes = FALSE;
|
||||
gboolean success = TRUE;
|
||||
gboolean def_route_changed;
|
||||
int ip_ifindex, config_ifindex;
|
||||
int ip_ifindex = 0;
|
||||
|
||||
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)",
|
||||
commit, routes_full_sync, new_config);
|
||||
_LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)",
|
||||
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);
|
||||
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;
|
||||
|
||||
/* Always commit to nm-platform to update lifetimes */
|
||||
if (commit && new_config) {
|
||||
gboolean assumed = nm_device_sys_iface_state_is_external_or_assume (self);
|
||||
|
||||
_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,
|
||||
nm_device_get_platform (self),
|
||||
nm_netns_get_route_manager (priv->netns),
|
||||
ip_ifindex,
|
||||
routes_full_sync,
|
||||
assumed ? (gint64) -1 : (gint64) default_route_metric);
|
||||
default_route_metric);
|
||||
}
|
||||
|
||||
if (new_config) {
|
||||
|
|
@ -10031,29 +10055,26 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config)
|
|||
static gboolean
|
||||
nm_device_set_ip6_config (NMDevice *self,
|
||||
NMIP6Config *new_config,
|
||||
gboolean commit,
|
||||
gboolean routes_full_sync)
|
||||
gboolean commit)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMIP6Config *old_config = NULL;
|
||||
gboolean has_changes = FALSE;
|
||||
gboolean success = TRUE;
|
||||
gboolean def_route_changed;
|
||||
int ip_ifindex, config_ifindex;
|
||||
int ip_ifindex = 0;
|
||||
|
||||
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)",
|
||||
commit, routes_full_sync, new_config);
|
||||
_LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)",
|
||||
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);
|
||||
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;
|
||||
|
||||
|
|
@ -10061,10 +10082,7 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
if (commit && new_config) {
|
||||
_commit_mtu (self, priv->ip4_config);
|
||||
success = nm_ip6_config_commit (new_config,
|
||||
nm_device_get_platform (self),
|
||||
nm_netns_get_route_manager (priv->netns),
|
||||
ip_ifindex,
|
||||
routes_full_sync);
|
||||
nm_device_get_platform (self));
|
||||
}
|
||||
|
||||
if (new_config) {
|
||||
|
|
@ -10900,6 +10918,11 @@ queued_ip4_config_change (gpointer user_data)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -12105,8 +12128,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||
/* Clean up IP configs; this does not actually deconfigure the
|
||||
* interface; the caller must flush routes and addresses explicitly.
|
||||
*/
|
||||
nm_device_set_ip4_config (self, NULL, 0, TRUE, TRUE);
|
||||
nm_device_set_ip6_config (self, NULL, TRUE, TRUE);
|
||||
nm_device_set_ip4_config (self, NULL, 0, TRUE);
|
||||
nm_device_set_ip6_config (self, NULL, TRUE);
|
||||
g_clear_object (&priv->proxy_config);
|
||||
g_clear_object (&priv->con_ip4_config);
|
||||
g_clear_object (&priv->dev_ip4_config);
|
||||
|
|
@ -12194,18 +12217,24 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean
|
|||
if (NM_DEVICE_GET_CLASS (self)->deactivate)
|
||||
NM_DEVICE_GET_CLASS (self)->deactivate (self);
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (self);
|
||||
|
||||
if (cleanup_type == CLEANUP_TYPE_DECONFIGURE) {
|
||||
/* master: release slaves */
|
||||
nm_device_master_release_slaves (self);
|
||||
|
||||
/* 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) {
|
||||
nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), ifindex);
|
||||
nm_platform_address_flush (nm_device_get_platform (self), ifindex);
|
||||
NMPlatform *platform = nm_device_get_platform (self);
|
||||
|
||||
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 */
|
||||
if ( priv->master
|
||||
&& nm_platform_link_get_master (nm_device_get_platform (self), priv->ifindex) <= 0)
|
||||
|
|
@ -13370,7 +13399,7 @@ handle_fail:
|
|||
_NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN,
|
||||
LOGD_DEVICE, "set-hw-addr: failed to %s MAC address to %s (%s) (%s)",
|
||||
operation, addr, detail,
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
}
|
||||
|
||||
if (was_up) {
|
||||
|
|
@ -13851,9 +13880,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_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);
|
||||
g_assert (priv->settings);
|
||||
|
||||
|
|
@ -13894,9 +13920,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 (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);
|
||||
priv->arping.dad_list = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -774,7 +774,7 @@ create_and_realize (NMDevice *device,
|
|||
"Failed to create team master interface '%s' for '%s': %s",
|
||||
iface,
|
||||
nm_connection_get_id (connection),
|
||||
nm_platform_error_to_string (plerr));
|
||||
nm_platform_error_to_string_a (plerr));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include "nm-setting-connection.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "devices/nm-device-private.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "nm-netns.h"
|
||||
#include "nm-act-request.h"
|
||||
#include "nm-ip4-config.h"
|
||||
|
|
@ -1066,10 +1065,11 @@ deactivate_cleanup (NMModem *self, NMDevice *device)
|
|||
priv->ip6_method == NM_MODEM_IP_METHOD_AUTO) {
|
||||
ifindex = nm_device_get_ip_ifindex (device);
|
||||
if (ifindex > 0) {
|
||||
nm_route_manager_route_flush (nm_netns_get_route_manager (nm_device_get_netns (device)),
|
||||
ifindex);
|
||||
nm_platform_address_flush (nm_device_get_platform (device), ifindex);
|
||||
nm_platform_link_set_down (nm_device_get_platform (device), ifindex);
|
||||
NMPlatform *platform = nm_device_get_platform (device);
|
||||
|
||||
nm_platform_ip_route_flush (platform, AF_UNSPEC, ifindex);
|
||||
nm_platform_ip_address_flush (platform, AF_UNSPEC, ifindex);
|
||||
nm_platform_link_set_down (platform, ifindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,22 +69,24 @@ typedef struct {
|
|||
NMNDiscPreference preference;
|
||||
} NMNDiscGateway;
|
||||
|
||||
typedef struct {
|
||||
struct _NMNDiscAddress {
|
||||
struct in6_addr address;
|
||||
guint8 dad_counter;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
} NMNDiscAddress;
|
||||
};
|
||||
typedef struct _NMNDiscAddress NMNDiscAddress;
|
||||
|
||||
typedef struct {
|
||||
struct _NMNDiscRoute {
|
||||
struct in6_addr network;
|
||||
guint8 plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
NMNDiscPreference preference;
|
||||
} NMNDiscRoute;
|
||||
};
|
||||
typedef struct _NMNDiscRoute NMNDiscRoute;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
|
|
|
|||
|
|
@ -2146,7 +2146,7 @@ monotonic_timestamp_get (struct timespec *tp)
|
|||
break;
|
||||
case 2:
|
||||
/* fallback, return CLOCK_MONOTONIC. Kernels prior to 2.6.39
|
||||
* don't support CLOCK_BOOTTIME. */
|
||||
* (released on 18 May, 2011) don't support CLOCK_BOOTTIME. */
|
||||
err = clock_gettime (CLOCK_MONOTONIC, tp);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,7 +304,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip4_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt);
|
||||
success = (nm_platform_ip4_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
} else {
|
||||
NMPlatformIP6Route rt = entry->route.r6;
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
rt.plen = 0;
|
||||
rt.metric = entry->effective_metric;
|
||||
|
||||
success = nm_platform_ip6_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt);
|
||||
success = (nm_platform_ip6_route_add (priv->platform, NMP_NLM_FLAG_REPLACE, &rt) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
}
|
||||
if (!success) {
|
||||
_LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u",
|
||||
|
|
@ -334,7 +334,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
|
||||
routes = nm_platform_lookup_route_default_clone (priv->platform,
|
||||
vtable->vt->obj_type,
|
||||
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL);
|
||||
if (!routes)
|
||||
return FALSE;
|
||||
|
|
@ -515,7 +515,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
|
|||
|
||||
routes = nm_platform_lookup_route_default_clone (priv->platform,
|
||||
vtable->vt->obj_type,
|
||||
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL);
|
||||
|
||||
assumed_metrics = _get_assumed_interface_metrics (vtable, self, routes);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@
|
|||
#include "nm-utils.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "systemd/nm-sd.h"
|
||||
#include "nm-route-manager.h"
|
||||
|
||||
#if !defined(NM_DIST_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
|
||||
dhcp4_state_changed (NMDhcpClient *client,
|
||||
NMDhcpState state,
|
||||
|
|
@ -122,13 +115,17 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
switch (state) {
|
||||
case NM_DHCP_STATE_BOUND:
|
||||
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),
|
||||
NM_PLATFORM_GET, gl.ifindex, FALSE);
|
||||
if (last_config)
|
||||
nm_ip4_config_subtract (existing, last_config);
|
||||
|
||||
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");
|
||||
|
||||
if (last_config)
|
||||
|
|
@ -157,27 +154,6 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
NMNDiscConfigMap changed = changed_int;
|
||||
static NMIP6Config *ndisc_config = NULL;
|
||||
NMIP6Config *existing;
|
||||
int system_support;
|
||||
guint32 ifa_flags = 0x00;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Check, whether kernel is recent enough, to help user space handling RA.
|
||||
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
||||
* addresses as /128.
|
||||
* The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address.
|
||||
**/
|
||||
system_support = nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET);
|
||||
|
||||
if (system_support)
|
||||
ifa_flags = IFA_F_NOPREFIXROUTE;
|
||||
if (global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
|| global_opt.tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
{
|
||||
/* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
}
|
||||
|
||||
existing = nm_ip6_config_capture (nm_platform_get_multi_idx (NM_PLATFORM_GET),
|
||||
NM_PLATFORM_GET, gl.ifindex, FALSE, global_opt.tempaddr);
|
||||
|
|
@ -197,49 +173,35 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_addresses (ndisc_config);
|
||||
guint8 plen;
|
||||
guint32 ifa_flags;
|
||||
|
||||
/* ndisc->addresses contains at most max_addresses entries.
|
||||
* This is different from what the kernel does, which
|
||||
* also counts static and temporary addresses when checking
|
||||
* max_addresses.
|
||||
**/
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
NMPlatformIP6Address address;
|
||||
/* Check, whether kernel is recent enough to help user space handling RA.
|
||||
* If it's not supported, we have no ipv6-privacy and must add autoconf
|
||||
* addresses as /128. The reason for the /128 is to prevent the kernel
|
||||
* from adding a prefix route for this address. */
|
||||
ifa_flags = 0;
|
||||
if (nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET)) {
|
||||
ifa_flags |= IFA_F_NOPREFIXROUTE;
|
||||
if (NM_IN_SET (global_opt.tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
plen = 64;
|
||||
} else
|
||||
plen = 128;
|
||||
|
||||
memset (&address, 0, sizeof (address));
|
||||
address.address = discovered_address->address;
|
||||
address.plen = system_support ? 64 : 128;
|
||||
address.timestamp = discovered_address->timestamp;
|
||||
address.lifetime = discovered_address->lifetime;
|
||||
address.preferred = discovered_address->preferred;
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
address.n_ifa_flags = ifa_flags;
|
||||
|
||||
nm_ip6_config_add_address (ndisc_config, &address);
|
||||
}
|
||||
nm_ip6_config_reset_addresses_ndisc (ndisc_config,
|
||||
rdata->addresses,
|
||||
rdata->addresses_n,
|
||||
plen,
|
||||
ifa_flags);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_routes (ndisc_config);
|
||||
|
||||
for (i = 0; i < rdata->routes_n; i++) {
|
||||
const NMNDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMPlatformIP6Route route = {
|
||||
.network = discovered_route->network,
|
||||
.plen = discovered_route->plen,
|
||||
.gateway = discovered_route->gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||
.metric = global_opt.priority_v6,
|
||||
};
|
||||
|
||||
nm_ip6_config_add_route (ndisc_config, &route);
|
||||
}
|
||||
nm_ip6_config_reset_routes_ndisc (ndisc_config,
|
||||
rdata->routes,
|
||||
rdata->routes_n,
|
||||
global_opt.priority_v6);
|
||||
}
|
||||
|
||||
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
||||
|
|
@ -257,7 +219,7 @@ ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_in
|
|||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
#include "platform/nm-platform.h"
|
||||
#include "platform/nm-platform-utils.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "nm-core-internal.h"
|
||||
|
||||
#include "introspection/org.freedesktop.NetworkManager.IP4Config.h"
|
||||
|
|
@ -164,7 +163,9 @@ _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
|
|||
NMIPConfigDedupMultiIdxType *idx_type,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformObject *pl_new)
|
||||
const NMPlatformObject *pl_new,
|
||||
gboolean merge,
|
||||
gboolean append_force)
|
||||
{
|
||||
NMPObject obj_new_stackinit;
|
||||
const NMDedupMultiEntry *entry_old;
|
||||
|
|
@ -201,58 +202,62 @@ _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
|
|||
const NMPObject *obj_old = entry_old->obj;
|
||||
|
||||
if (nmp_object_equal (obj_new, obj_old))
|
||||
return FALSE;
|
||||
goto append_force_and_out;
|
||||
|
||||
switch (idx_type->obj_type) {
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
/* we want to keep the maximum addr_source. But since we expect
|
||||
* that usually we already add the maxiumum right away, we first try to
|
||||
* add the new address (replacing the old one). Only if we later
|
||||
* find out that addr_source is now lower, we fix it.
|
||||
*/
|
||||
if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
|
||||
modified = TRUE;
|
||||
/* if @merge, we merge the new object with the existing one.
|
||||
* Otherwise, we replace it entirely. */
|
||||
if (merge) {
|
||||
switch (idx_type->obj_type) {
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
/* we want to keep the maximum addr_source. But since we expect
|
||||
* that usually we already add the maxiumum right away, we first try to
|
||||
* add the new address (replacing the old one). Only if we later
|
||||
* find out that addr_source is now lower, we fix it.
|
||||
*/
|
||||
if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
|
||||
modified = TRUE;
|
||||
}
|
||||
|
||||
/* for addresses that we read from the kernel, we keep the timestamps as defined
|
||||
* by the previous source (item_old). The reason is, that the other source configured the lifetimes
|
||||
* with "what should be" and the kernel values are "what turned out after configuring it".
|
||||
*
|
||||
* For other sources, the longer lifetime wins. */
|
||||
if ( ( obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
|
||||
&& obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
|
||||
|| nm_platform_ip_address_cmp_expiry (NMP_OBJECT_CAST_IP_ADDRESS (obj_old), NMP_OBJECT_CAST_IP_ADDRESS(obj_new)) > 0) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.timestamp = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->timestamp;
|
||||
obj_new_stackinit.ip_address.lifetime = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->lifetime;
|
||||
obj_new_stackinit.ip_address.preferred = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->preferred;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
/* we want to keep the maximum rt_source. But since we expect
|
||||
* that usually we already add the maxiumum right away, we first try to
|
||||
* add the new route (replacing the old one). Only if we later
|
||||
* find out that rt_source is now lower, we fix it.
|
||||
*/
|
||||
if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* for addresses that we read from the kernel, we keep the timestamps as defined
|
||||
* by the previous source (item_old). The reason is, that the other source configured the lifetimes
|
||||
* with "what should be" and the kernel values are "what turned out after configuring it".
|
||||
*
|
||||
* For other sources, the longer lifetime wins. */
|
||||
if ( ( obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
|
||||
&& obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
|
||||
|| nm_platform_ip_address_cmp_expiry (NMP_OBJECT_CAST_IP_ADDRESS (obj_old), NMP_OBJECT_CAST_IP_ADDRESS(obj_new)) > 0) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_address.timestamp = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->timestamp;
|
||||
obj_new_stackinit.ip_address.lifetime = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->lifetime;
|
||||
obj_new_stackinit.ip_address.preferred = NMP_OBJECT_CAST_IP_ADDRESS (obj_old)->preferred;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
/* we want to keep the maximum rt_source. But since we expect
|
||||
* that usually we already add the maxiumum right away, we first try to
|
||||
* add the new route (replacing the old one). Only if we later
|
||||
* find out that rt_source is now lower, we fix it.
|
||||
*/
|
||||
if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
|
||||
obj_new = nmp_object_stackinit_obj (&obj_new_stackinit, obj_new);
|
||||
obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
|
||||
modified = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
break;
|
||||
if ( modified
|
||||
&& nmp_object_equal (obj_new, obj_old))
|
||||
goto append_force_and_out;
|
||||
}
|
||||
|
||||
if ( modified
|
||||
&& nmp_object_equal (obj_new, obj_old))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_dedup_multi_index_add_full (multi_idx,
|
||||
|
|
@ -269,6 +274,55 @@ _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
|
|||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
append_force_and_out:
|
||||
if (append_force) {
|
||||
if (nm_dedup_multi_entry_reorder (entry_old, NULL, TRUE))
|
||||
return TRUE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -339,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_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Route *new);
|
||||
static const NMDedupMultiEntry *_lookup_route (const NMIP4Config *self,
|
||||
const NMPObject *needle,
|
||||
NMPlatformIPRouteCmpType cmp_type);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -624,16 +681,6 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
continue;
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
|
||||
continue;
|
||||
|
||||
if ( priv->has_gateway
|
||||
&& route->plen == 32
|
||||
&& route->network == priv->gateway
|
||||
&& route->gateway == 0) {
|
||||
/* If there is a host route to the gateway, ignore that route. It is
|
||||
* automatically added by NetworkManager when needed.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
_add_route (self, plobj, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -656,92 +703,122 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
}
|
||||
|
||||
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;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
|
||||
int ifindex;
|
||||
guint i;
|
||||
gboolean success = TRUE;
|
||||
|
||||
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 (self != NULL, FALSE);
|
||||
|
||||
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
|
||||
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 */
|
||||
{
|
||||
guint i;
|
||||
gs_unref_array GArray *routes = NULL;
|
||||
gs_unref_array GArray *device_route_purge_list = NULL;
|
||||
const CList *iter;
|
||||
if (addresses) {
|
||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4, add it here shortly before syncing
|
||||
* the routes. */
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
const NMPObject *o = addresses->pdata[i];
|
||||
const NMPlatformIP4Address *addr;
|
||||
nm_auto_nmpobj NMPObject *r = NULL;
|
||||
NMPlatformIP4Route *route;
|
||||
in_addr_t network;
|
||||
|
||||
head_entry = nm_ip4_config_lookup_routes (self);
|
||||
if (!o)
|
||||
continue;
|
||||
|
||||
routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), head_entry ? head_entry->len : 0);
|
||||
addr = NMP_OBJECT_CAST_IP4_ADDRESS (o);
|
||||
if (addr->plen == 0)
|
||||
continue;
|
||||
|
||||
if ( default_route_metric >= 0
|
||||
&& addresses) {
|
||||
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
|
||||
* As we don't do that for IPv4, add it here shortly before syncing
|
||||
* the routes. For NMRouteManager these routes are very much important. */
|
||||
for (i = 0; i < addresses->len; i++) {
|
||||
const NMPObject *o = addresses->pdata[i];
|
||||
const NMPlatformIP4Address *addr;
|
||||
NMPlatformIP4Route route = { 0 };
|
||||
nm_assert (addr->plen <= 32);
|
||||
|
||||
if (!o)
|
||||
continue;
|
||||
/* The destination network depends on the peer-address. */
|
||||
network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
||||
|
||||
addr = NMP_OBJECT_CAST_IP4_ADDRESS (o);
|
||||
if (addr->plen == 0)
|
||||
continue;
|
||||
if (_ipv4_is_zeronet (network)) {
|
||||
/* Kernel doesn't add device-routes for destinations that
|
||||
* start with 0.x.y.z. Skip them. */
|
||||
continue;
|
||||
}
|
||||
|
||||
nm_assert (addr->plen <= 32);
|
||||
r = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r);
|
||||
|
||||
route.ifindex = ifindex;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
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);
|
||||
|
||||
/* The destination network depends on the peer-address. */
|
||||
route.network = nm_utils_ip4_address_clear_host_address (addr->peer_address, addr->plen);
|
||||
nm_platform_ip_route_normalize (AF_INET, (NMPlatformIPRoute *) route);
|
||||
|
||||
if (_ipv4_is_zeronet (route.network)) {
|
||||
/* Kernel doesn't add device-routes for destinations that
|
||||
* start with 0.x.y.z. Skip them. */
|
||||
continue;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
route.plen = addr->plen;
|
||||
route.pref_src = addr->address;
|
||||
route.metric = default_route_metric;
|
||||
if (default_route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
||||
nm_auto_nmpobj NMPObject *r_dev = NULL;
|
||||
|
||||
g_array_append_val (routes, route);
|
||||
r_dev = nmp_object_clone (r, FALSE);
|
||||
route = NMP_OBJECT_CAST_IP4_ROUTE (r_dev);
|
||||
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)
|
||||
device_route_purge_list = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
||||
route.metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
|
||||
g_array_append_val (device_route_purge_list, route);
|
||||
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) {
|
||||
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_route_manager_ip4_route_sync (route_manager, ifindex, routes,
|
||||
default_route_metric < 0, routes_full_sync))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
nm_platform_ip4_address_sync (platform, ifindex, addresses);
|
||||
|
||||
if (!nm_platform_ip_route_sync (platform,
|
||||
AF_INET,
|
||||
ifindex,
|
||||
routes,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL))
|
||||
success = FALSE;
|
||||
|
||||
nm_platform_ip4_dev_route_blacklist_set (platform,
|
||||
ifindex,
|
||||
ip4_dev_route_blacklist);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -841,6 +918,11 @@ nm_ip4_config_merge_setting (NMIP4Config *self, NMSettingIPConfig *setting, guin
|
|||
NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
|
||||
NMPlatformIP4Route route;
|
||||
|
||||
if (nm_ip_route_get_family (s_route) != AF_INET) {
|
||||
nm_assert_not_reached ();
|
||||
continue;
|
||||
}
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
nm_ip_route_get_dest_binary (s_route, &route.network);
|
||||
|
||||
|
|
@ -1228,7 +1310,8 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||
nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &a) {
|
||||
if (nm_dedup_multi_index_remove_obj (priv_dst->multi_idx,
|
||||
&priv_dst->idx_ip4_addresses,
|
||||
NMP_OBJECT_UP_CAST (a)))
|
||||
NMP_OBJECT_UP_CAST (a),
|
||||
NULL))
|
||||
changed = TRUE;
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1256,7 +1339,8 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|||
nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
|
||||
if (nm_dedup_multi_index_remove_obj (priv_dst->multi_idx,
|
||||
&priv_dst->idx_ip4_routes,
|
||||
NMP_OBJECT_UP_CAST (r)))
|
||||
NMP_OBJECT_UP_CAST (r),
|
||||
NULL))
|
||||
changed = TRUE;
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1885,7 +1969,9 @@ _add_address (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Ad
|
|||
&priv->idx_ip4_addresses_,
|
||||
priv->ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) new))
|
||||
(const NMPlatformObject *) new,
|
||||
TRUE,
|
||||
FALSE))
|
||||
_notify_addresses (self);
|
||||
}
|
||||
|
||||
|
|
@ -1921,7 +2007,8 @@ _nmtst_nm_ip4_config_del_address (NMIP4Config *self, guint i)
|
|||
|
||||
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
|
||||
&priv->idx_ip4_addresses,
|
||||
NMP_OBJECT_UP_CAST (a)) != 1)
|
||||
NMP_OBJECT_UP_CAST (a),
|
||||
NULL) != 1)
|
||||
g_return_if_reached ();
|
||||
_notify_addresses (self);
|
||||
}
|
||||
|
|
@ -1975,12 +2062,30 @@ nm_ip4_config_address_exists (const NMIP4Config *self,
|
|||
needle->plen,
|
||||
needle->peer_address);
|
||||
return !!nm_dedup_multi_index_lookup_obj (priv->multi_idx,
|
||||
&priv->idx_ip4_routes,
|
||||
&priv->idx_ip4_addresses,
|
||||
&obj_stack);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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
|
||||
nm_ip4_config_reset_routes (NMIP4Config *self)
|
||||
{
|
||||
|
|
@ -2004,7 +2109,9 @@ _add_route (NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Rout
|
|||
&priv->idx_ip4_routes_,
|
||||
priv->ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) new))
|
||||
(const NMPlatformObject *) new,
|
||||
TRUE,
|
||||
FALSE))
|
||||
_notify_routes (self);
|
||||
}
|
||||
|
||||
|
|
@ -2040,7 +2147,8 @@ _nmtst_nm_ip4_config_del_route (NMIP4Config *self, guint i)
|
|||
|
||||
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
|
||||
&priv->idx_ip4_routes,
|
||||
NMP_OBJECT_UP_CAST (r)) != 1)
|
||||
NMP_OBJECT_UP_CAST (r),
|
||||
NULL) != 1)
|
||||
g_return_if_reached ();
|
||||
_notify_routes (self);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,14 @@ gboolean _nm_ip_config_add_obj (NMDedupMultiIndex *multi_idx,
|
|||
NMIPConfigDedupMultiIdxType *idx_type,
|
||||
int ifindex,
|
||||
const NMPObject *obj_new,
|
||||
const NMPlatformObject *pl_new);
|
||||
const NMPlatformObject *pl_new,
|
||||
gboolean merge,
|
||||
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);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -135,7 +142,9 @@ int nm_ip4_config_get_ifindex (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);
|
||||
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);
|
||||
NMSetting *nm_ip4_config_create_setting (const NMIP4Config *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@
|
|||
#include "platform/nmp-object.h"
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nm-platform-utils.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-ip4-config.h"
|
||||
#include "ndisc/nm-ndisc.h"
|
||||
|
||||
#include "introspection/org.freedesktop.NetworkManager.IP6Config.h"
|
||||
|
||||
|
|
@ -483,15 +483,6 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
|
||||
continue;
|
||||
|
||||
if ( has_gateway
|
||||
&& route->plen == 128
|
||||
&& IN6_ARE_ADDR_EQUAL (&route->network, &priv->gateway)
|
||||
&& IN6_IS_ADDR_UNSPECIFIED (&route->gateway)) {
|
||||
/* If there is a host route to the gateway, ignore that route. It is
|
||||
* automatically added by NetworkManager when needed.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
_add_route (self, plobj, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -516,45 +507,33 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
|
|||
|
||||
gboolean
|
||||
nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
NMRouteManager *route_manager,
|
||||
int ifindex,
|
||||
gboolean routes_full_sync)
|
||||
NMPlatform *platform)
|
||||
{
|
||||
gs_unref_ptrarray GPtrArray *addresses = NULL;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
gs_unref_ptrarray GPtrArray *routes = NULL;
|
||||
int ifindex;
|
||||
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 (self != NULL, FALSE);
|
||||
|
||||
/* Addresses */
|
||||
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
|
||||
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);
|
||||
|
||||
/* Routes */
|
||||
{
|
||||
gs_unref_array GArray *routes = NULL;
|
||||
const CList *iter;
|
||||
if (!nm_platform_ip_route_sync (platform,
|
||||
AF_INET6,
|
||||
ifindex,
|
||||
routes,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL))
|
||||
success = FALSE;
|
||||
|
||||
head_entry = nm_ip6_config_lookup_routes (self);
|
||||
|
||||
routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), head_entry ? head_entry->len : 0);
|
||||
|
||||
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;
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -668,6 +647,11 @@ nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guin
|
|||
NMIPRoute *s_route = nm_setting_ip_config_get_route (setting, i);
|
||||
NMPlatformIP6Route route;
|
||||
|
||||
if (nm_ip_route_get_family (s_route) != AF_INET6) {
|
||||
nm_assert_not_reached ();
|
||||
continue;
|
||||
}
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
nm_ip_route_get_dest_binary (s_route, &route.network);
|
||||
|
||||
|
|
@ -1025,7 +1009,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
|||
nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &a) {
|
||||
if (nm_dedup_multi_index_remove_obj (priv_dst->multi_idx,
|
||||
&priv_dst->idx_ip6_addresses,
|
||||
NMP_OBJECT_UP_CAST (a)))
|
||||
NMP_OBJECT_UP_CAST (a),
|
||||
NULL))
|
||||
changed = TRUE;
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1054,7 +1039,8 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
|
|||
nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
|
||||
if (nm_dedup_multi_index_remove_obj (priv_dst->multi_idx,
|
||||
&priv_dst->idx_ip6_routes,
|
||||
NMP_OBJECT_UP_CAST (r)))
|
||||
NMP_OBJECT_UP_CAST (r),
|
||||
NULL))
|
||||
changed = TRUE;
|
||||
}
|
||||
if (changed)
|
||||
|
|
@ -1200,6 +1186,8 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
|
|||
dst_priv = NM_IP6_CONFIG_GET_PRIVATE (dst);
|
||||
src_priv = NM_IP6_CONFIG_GET_PRIVATE (src);
|
||||
|
||||
g_return_val_if_fail (src_priv->ifindex > 0, FALSE);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (dst));
|
||||
|
||||
/* ifindex */
|
||||
|
|
@ -1259,12 +1247,13 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
|
|||
has_minor_changes = TRUE;
|
||||
nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_addresses);
|
||||
nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
|
||||
nm_dedup_multi_index_add (dst_priv->multi_idx,
|
||||
&dst_priv->idx_ip6_addresses,
|
||||
ipconf_iter_src.current->obj,
|
||||
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
|
||||
NULL,
|
||||
NULL);
|
||||
_nm_ip_config_add_obj (dst_priv->multi_idx,
|
||||
&dst_priv->idx_ip6_addresses_,
|
||||
dst_priv->ifindex,
|
||||
ipconf_iter_src.current->obj,
|
||||
NULL,
|
||||
FALSE,
|
||||
TRUE);
|
||||
}
|
||||
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_addresses, FALSE);
|
||||
_notify_addresses (dst);
|
||||
|
|
@ -1303,12 +1292,13 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
|
|||
has_minor_changes = TRUE;
|
||||
nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes);
|
||||
nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
|
||||
nm_dedup_multi_index_add (dst_priv->multi_idx,
|
||||
&dst_priv->idx_ip6_routes,
|
||||
ipconf_iter_src.current->obj,
|
||||
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
|
||||
NULL,
|
||||
NULL);
|
||||
_nm_ip_config_add_obj (dst_priv->multi_idx,
|
||||
&dst_priv->idx_ip6_routes_,
|
||||
dst_priv->ifindex,
|
||||
ipconf_iter_src.current->obj,
|
||||
NULL,
|
||||
FALSE,
|
||||
TRUE);
|
||||
}
|
||||
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, FALSE);
|
||||
_notify_routes (dst);
|
||||
|
|
@ -1529,6 +1519,58 @@ nm_ip6_config_get_route_metric (const NMIP6Config *self)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_ip6_config_reset_addresses_ndisc (NMIP6Config *self,
|
||||
const NMNDiscAddress *addresses,
|
||||
guint addresses_n,
|
||||
guint8 plen,
|
||||
guint32 ifa_flags)
|
||||
{
|
||||
NMIP6ConfigPrivate *priv;
|
||||
guint i;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (NM_IS_IP6_CONFIG (self));
|
||||
|
||||
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (priv->ifindex > 0);
|
||||
|
||||
nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_addresses);
|
||||
|
||||
for (i = 0; i < addresses_n; i++) {
|
||||
const NMNDiscAddress *ndisc_addr = &addresses[i];
|
||||
NMPObject obj;
|
||||
NMPlatformIP6Address *a;
|
||||
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
|
||||
a = NMP_OBJECT_CAST_IP6_ADDRESS (&obj);
|
||||
a->ifindex = priv->ifindex;
|
||||
a->address = ndisc_addr->address;
|
||||
a->plen = plen;
|
||||
a->timestamp = ndisc_addr->timestamp;
|
||||
a->lifetime = ndisc_addr->lifetime;
|
||||
a->preferred = MIN (ndisc_addr->lifetime, ndisc_addr->preferred);
|
||||
a->addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
a->n_ifa_flags = ifa_flags;
|
||||
|
||||
if (_nm_ip_config_add_obj (priv->multi_idx,
|
||||
&priv->idx_ip6_addresses_,
|
||||
priv->ifindex,
|
||||
&obj,
|
||||
NULL,
|
||||
FALSE,
|
||||
TRUE))
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_addresses, FALSE) > 0)
|
||||
changed = TRUE;
|
||||
|
||||
if (changed)
|
||||
_notify_addresses (self);
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip6_config_reset_addresses (NMIP6Config *self)
|
||||
{
|
||||
|
|
@ -1550,7 +1592,9 @@ _add_address (NMIP6Config *self,
|
|||
&priv->idx_ip6_addresses_,
|
||||
priv->ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) new))
|
||||
(const NMPlatformObject *) new,
|
||||
TRUE,
|
||||
FALSE))
|
||||
_notify_addresses (self);
|
||||
}
|
||||
|
||||
|
|
@ -1586,7 +1630,8 @@ _nmtst_nm_ip6_config_del_address (NMIP6Config *self, guint i)
|
|||
|
||||
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
|
||||
&priv->idx_ip6_addresses,
|
||||
NMP_OBJECT_UP_CAST (a)) != 1)
|
||||
NMP_OBJECT_UP_CAST (a),
|
||||
NULL) != 1)
|
||||
g_return_if_reached ();
|
||||
_notify_addresses (self);
|
||||
}
|
||||
|
|
@ -1704,6 +1749,55 @@ nm_ip6_config_has_any_dad_pending (const NMIP6Config *self,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
||||
const NMNDiscRoute *routes,
|
||||
guint routes_n,
|
||||
guint32 metric)
|
||||
{
|
||||
NMIP6ConfigPrivate *priv;
|
||||
guint i;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
g_return_if_fail (NM_IS_IP6_CONFIG (self));
|
||||
|
||||
priv = NM_IP6_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
g_return_if_fail (priv->ifindex > 0);
|
||||
|
||||
nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_routes);
|
||||
|
||||
for (i = 0; i < routes_n; i++) {
|
||||
const NMNDiscRoute *ndisc_route = &routes[i];
|
||||
NMPObject obj;
|
||||
NMPlatformIP6Route *r;
|
||||
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
r = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
|
||||
r->ifindex = priv->ifindex;
|
||||
r->network = ndisc_route->network;
|
||||
r->plen = ndisc_route->plen;
|
||||
r->gateway = ndisc_route->gateway;
|
||||
r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
r->metric = metric;
|
||||
|
||||
if (_nm_ip_config_add_obj (priv->multi_idx,
|
||||
&priv->idx_ip6_routes_,
|
||||
priv->ifindex,
|
||||
&obj,
|
||||
NULL,
|
||||
FALSE,
|
||||
TRUE))
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
|
||||
changed = TRUE;
|
||||
|
||||
if (changed)
|
||||
_notify_routes (self);
|
||||
}
|
||||
|
||||
void
|
||||
nm_ip6_config_reset_routes (NMIP6Config *self)
|
||||
{
|
||||
|
|
@ -1727,7 +1821,9 @@ _add_route (NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Rout
|
|||
&priv->idx_ip6_routes_,
|
||||
priv->ifindex,
|
||||
obj_new,
|
||||
(const NMPlatformObject *) new))
|
||||
(const NMPlatformObject *) new,
|
||||
TRUE,
|
||||
FALSE))
|
||||
_notify_routes (self);
|
||||
}
|
||||
|
||||
|
|
@ -1763,7 +1859,8 @@ _nmtst_ip6_config_del_route (NMIP6Config *self, guint i)
|
|||
|
||||
if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
|
||||
&priv->idx_ip6_routes,
|
||||
NMP_OBJECT_UP_CAST (r)) != 1)
|
||||
NMP_OBJECT_UP_CAST (r),
|
||||
NULL) != 1)
|
||||
g_return_if_reached ();
|
||||
_notify_routes (self);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
gboolean capture_resolv_conf, NMSettingIP6ConfigPrivacy use_temporary);
|
||||
gboolean nm_ip6_config_commit (const NMIP6Config *self,
|
||||
NMPlatform *platform,
|
||||
NMRouteManager *route_manager,
|
||||
int ifindex,
|
||||
gboolean routes_full_sync);
|
||||
NMPlatform *platform);
|
||||
void nm_ip6_config_merge_setting (NMIP6Config *self, NMSettingIPConfig *setting, guint32 default_route_metric);
|
||||
NMSetting *nm_ip6_config_create_setting (const NMIP6Config *self);
|
||||
|
||||
|
|
@ -194,6 +191,18 @@ gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b);
|
|||
|
||||
void nm_ip6_config_set_privacy (NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy);
|
||||
|
||||
struct _NMNDiscAddress;
|
||||
void nm_ip6_config_reset_addresses_ndisc (NMIP6Config *self,
|
||||
const struct _NMNDiscAddress *addresses,
|
||||
guint addresses_n,
|
||||
guint8 plen,
|
||||
guint32 ifa_flags);
|
||||
struct _NMNDiscRoute;
|
||||
void nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
|
||||
const struct _NMNDiscRoute *routes,
|
||||
guint routes_n,
|
||||
guint32 metric);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Testing-only functions */
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include "platform/nm-platform.h"
|
||||
#include "platform/nmp-netns.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "nm-default-route-manager.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
|
@ -40,7 +39,6 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
|
|||
typedef struct {
|
||||
NMPlatform *platform;
|
||||
NMPNetns *platform_netns;
|
||||
NMRouteManager *route_manager;
|
||||
NMDefaultRouteManager *default_route_manager;
|
||||
bool log_with_ptr;
|
||||
} NMNetnsPrivate;
|
||||
|
|
@ -88,12 +86,6 @@ nm_netns_get_default_route_manager (NMNetns *self)
|
|||
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
|
||||
|
|
@ -137,7 +129,6 @@ constructed (GObject *object)
|
|||
log_with_ptr = nm_platform_get_log_with_ptr (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);
|
||||
|
||||
G_OBJECT_CLASS (nm_netns_parent_class)->constructed (object);
|
||||
|
|
@ -157,7 +148,6 @@ dispose (GObject *object)
|
|||
NMNetns *self = NM_NETNS (object);
|
||||
NMNetnsPrivate *priv = NM_NETNS_GET_PRIVATE (self);
|
||||
|
||||
g_clear_object (&priv->route_manager);
|
||||
g_clear_object (&priv->default_route_manager);
|
||||
g_clear_object (&priv->platform);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ NMNetns *nm_netns_new (NMPlatform *platform);
|
|||
|
||||
NMPlatform *nm_netns_get_platform (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);
|
||||
|
||||
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 _NMRfkillManager NMRfkillManager;
|
||||
typedef struct _NMPacrunnerManager NMPacrunnerManager;
|
||||
typedef struct _NMRouteManager NMRouteManager;
|
||||
typedef struct _NMSessionMonitor NMSessionMonitor;
|
||||
typedef struct _NMSleepMonitor NMSleepMonitor;
|
||||
typedef struct _NMLldpListener NMLldpListener;
|
||||
|
|
|
|||
|
|
@ -1199,7 +1199,7 @@ ip_route_delete (NMPlatform *platform, const NMPObject *obj)
|
|||
return ipx_route_delete (platform, AF_UNSPEC, -1, obj);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static NMPlatformError
|
||||
ip_route_add (NMPlatform *platform,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
|
|
@ -1223,6 +1223,8 @@ ip_route_add (NMPlatform *platform,
|
|||
|
||||
g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
|
||||
flags = NM_FLAGS_UNSET (flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE);
|
||||
|
||||
/* currently, only replace is implemented. */
|
||||
g_assert (flags == NMP_NLM_FLAG_REPLACE);
|
||||
|
||||
|
|
@ -1230,24 +1232,17 @@ ip_route_add (NMPlatform *platform,
|
|||
? NMP_OBJECT_TYPE_IP4_ROUTE
|
||||
: NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
(const NMPlatformObject *) route);
|
||||
r = &obj->ip_route;
|
||||
r = NMP_OBJECT_CAST_IP_ROUTE (obj);
|
||||
nm_platform_ip_route_normalize (addr_family, r);
|
||||
|
||||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
r4 = NMP_OBJECT_CAST_IP4_ROUTE (obj);
|
||||
r4->network = nm_utils_ip4_address_clear_host_address (r4->network, r4->plen);
|
||||
r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r4->rt_source),
|
||||
r4->scope_inv = nm_platform_route_scope_inv (!r4->gateway
|
||||
? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
||||
if (r4->gateway)
|
||||
has_gateway = TRUE;
|
||||
break;
|
||||
case AF_INET6:
|
||||
r6 = NMP_OBJECT_CAST_IP6_ROUTE (obj);
|
||||
nm_utils_ip6_address_clear_host_address (&r6->network, &r6->network, r6->plen);
|
||||
r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r6->rt_source),
|
||||
r6->metric = nm_utils_ip6_route_metric_normalize (r6->metric);
|
||||
nm_utils_ip6_address_clear_host_address (&r6->src, &r6->src, r6->src_plen);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&r6->gateway))
|
||||
has_gateway = TRUE;
|
||||
break;
|
||||
|
|
@ -1291,7 +1286,7 @@ ip_route_add (NMPlatform *platform,
|
|||
nm_log_warn (LOGD_PLATFORM, "Fake platform: failure adding ip6-route '%d: %s/%d %d': Network Unreachable",
|
||||
r->ifindex, nm_utils_inet6_ntop (&r6->network, NULL), r->plen, r->metric);
|
||||
}
|
||||
return FALSE;
|
||||
return NM_PLATFORM_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1353,7 +1348,7 @@ ip_route_add (NMPlatform *platform,
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -265,6 +265,16 @@ static gboolean event_handler_read_netlink (NMPlatform *platform, gboolean wait_
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMPlatformError
|
||||
wait_for_nl_response_to_plerr (WaitForNlResponseResult seq_result)
|
||||
{
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
return NM_PLATFORM_ERROR_SUCCESS;
|
||||
if (seq_result < 0)
|
||||
return (NMPlatformError) seq_result;
|
||||
return NM_PLATFORM_ERROR_NETLINK;
|
||||
}
|
||||
|
||||
static const char *
|
||||
wait_for_nl_response_to_string (WaitForNlResponseResult seq_result, char *buf, gsize buf_size)
|
||||
{
|
||||
|
|
@ -290,35 +300,83 @@ wait_for_nl_response_to_string (WaitForNlResponseResult seq_result, char *buf, g
|
|||
return buf0;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
/*****************************************************************************
|
||||
* Support IFLA_INET6_ADDR_GEN_MODE
|
||||
******************************************************************/
|
||||
*****************************************************************************/
|
||||
|
||||
static int _support_user_ipv6ll = 0;
|
||||
#define _support_user_ipv6ll_still_undecided() (G_UNLIKELY (_support_user_ipv6ll == 0))
|
||||
|
||||
static void
|
||||
_support_user_ipv6ll_detect (struct nlattr **tb)
|
||||
{
|
||||
gboolean supported;
|
||||
|
||||
nm_assert (_support_user_ipv6ll_still_undecided ());
|
||||
|
||||
/* IFLA_INET6_ADDR_GEN_MODE was added in kernel 3.17, dated 5 October, 2014. */
|
||||
supported = !!tb[IFLA_INET6_ADDR_GEN_MODE];
|
||||
_support_user_ipv6ll = supported ? 1 : -1;
|
||||
_LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s",
|
||||
supported ? "detected" : "not detected");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_support_user_ipv6ll_get (void)
|
||||
{
|
||||
if (_support_user_ipv6ll_still_undecided ()) {
|
||||
_support_user_ipv6ll = -1;
|
||||
_LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s", "failed to detect; assume no support");
|
||||
return FALSE;
|
||||
_support_user_ipv6ll = 1;
|
||||
_LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s", "failed to detect; assume support");
|
||||
}
|
||||
return _support_user_ipv6ll > 0;
|
||||
|
||||
return _support_user_ipv6ll >= 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_support_user_ipv6ll_detect (struct nlattr **tb)
|
||||
{
|
||||
if (_support_user_ipv6ll_still_undecided ()) {
|
||||
gboolean supported = !!tb[IFLA_INET6_ADDR_GEN_MODE];
|
||||
/*****************************************************************************
|
||||
* extended IFA_FLAGS support
|
||||
*****************************************************************************/
|
||||
|
||||
_support_user_ipv6ll = supported ? 1 : -1;
|
||||
_LOG2D ("kernel-support: IFLA_INET6_ADDR_GEN_MODE: %s",
|
||||
supported ? "detected" : "not detected");
|
||||
static int _support_kernel_extended_ifa_flags = 0;
|
||||
|
||||
#define _support_kernel_extended_ifa_flags_still_undecided() (G_UNLIKELY (_support_kernel_extended_ifa_flags == 0))
|
||||
|
||||
static void
|
||||
_support_kernel_extended_ifa_flags_detect (struct nl_msg *msg)
|
||||
{
|
||||
struct nlmsghdr *msg_hdr;
|
||||
gboolean support;
|
||||
|
||||
nm_assert (_support_kernel_extended_ifa_flags_still_undecided ());
|
||||
nm_assert (msg);
|
||||
|
||||
msg_hdr = nlmsg_hdr (msg);
|
||||
|
||||
nm_assert (msg_hdr && msg_hdr->nlmsg_type == RTM_NEWADDR);
|
||||
|
||||
/* IFA_FLAGS is set for IPv4 and IPv6 addresses. It was added first to IPv6,
|
||||
* but if we encounter an IPv4 address with IFA_FLAGS, we surely have support. */
|
||||
if (NM_IN_SET (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family, AF_INET, AF_INET6))
|
||||
return;
|
||||
|
||||
/* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
|
||||
* we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
|
||||
* and IFA_F_NOPREFIXROUTE for IPv6. They were added together in kernel 3.14,
|
||||
* dated 30 March, 2014.
|
||||
*
|
||||
* For IPv4, IFA_F_NOPREFIXROUTE was added later, but there is no easy
|
||||
* way to detect kernel support. */
|
||||
support = !!nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), IFA_FLAGS);
|
||||
_support_kernel_extended_ifa_flags = support ? 1 : -1;
|
||||
_LOG2D ("kernel-support: extended-ifa-flags: %s", support ? "detected" : "not detected");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_support_kernel_extended_ifa_flags_get (void)
|
||||
{
|
||||
if (_support_kernel_extended_ifa_flags_still_undecided ()) {
|
||||
_LOG2D ("kernel-support: extended-ifa-flags: %s", "unable to detect kernel support for handling IPv6 temporary addresses. Assume support");
|
||||
_support_kernel_extended_ifa_flags = 1;
|
||||
}
|
||||
return _support_kernel_extended_ifa_flags >= 0;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
|
@ -778,6 +836,31 @@ _linktype_get_type (NMPlatform *platform,
|
|||
* libnl unility functions and wrappers
|
||||
******************************************************************/
|
||||
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
/* copied from iproute2's addattr_l(). */
|
||||
static gboolean
|
||||
_nl_addattr_l (struct nlmsghdr *n,
|
||||
int maxlen,
|
||||
int type,
|
||||
const void *data,
|
||||
int alen)
|
||||
{
|
||||
int len = RTA_LENGTH (alen);
|
||||
struct rtattr *rta;
|
||||
|
||||
if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen)
|
||||
return FALSE;
|
||||
|
||||
rta = NLMSG_TAIL (n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
memcpy (RTA_DATA (rta), data, alen);
|
||||
n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define nm_auto_nlmsg __attribute__((cleanup(_nm_auto_nl_msg_cleanup)))
|
||||
static void
|
||||
_nm_auto_nl_msg_cleanup (void *ptr)
|
||||
|
|
@ -936,7 +1019,8 @@ _parse_af_inet6 (NMPlatform *platform,
|
|||
/* Hack to detect support addrgenmode of the kernel. We only parse
|
||||
* netlink messages that we receive from kernel, hence this check
|
||||
* is valid. */
|
||||
_support_user_ipv6ll_detect (tb);
|
||||
if (_support_user_ipv6ll_still_undecided ())
|
||||
_support_user_ipv6ll_detect (tb);
|
||||
|
||||
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
|
||||
i6_addr_gen_mode_inv = _nm_platform_uint8_inv (nla_get_u8 (tb[IFLA_INET6_ADDR_GEN_MODE]));
|
||||
|
|
@ -1946,8 +2030,6 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
table = tb[RTA_TABLE]
|
||||
? nla_get_u32 (tb[RTA_TABLE])
|
||||
: (guint32) rtm->rtm_table;
|
||||
if (table != RT_TABLE_MAIN)
|
||||
goto errout;
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
|
|
@ -2064,6 +2146,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
|
|||
|
||||
obj = nmp_object_new (is_v4 ? NMP_OBJECT_TYPE_IP4_ROUTE : NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
|
||||
|
||||
obj->ip_route.table_coerced = nm_platform_route_table_coerce (table);
|
||||
obj->ip_route.ifindex = nh.ifindex;
|
||||
|
||||
if (_check_addr_or_errout (tb, RTA_DST, addr_len))
|
||||
|
|
@ -2501,19 +2584,20 @@ ip_route_get_lock_flag (const NMPlatformIPRoute *route)
|
|||
/* Copied and modified from libnl3's build_route_msg() and rtnl_route_build_msg(). */
|
||||
static struct nl_msg *
|
||||
_nl_msg_new_route (int nlmsg_type,
|
||||
NMPNlmFlags nlmsgflags,
|
||||
guint16 nlmsgflags,
|
||||
const NMPObject *obj)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
const NMPClass *klass = NMP_OBJECT_GET_CLASS (obj);
|
||||
gboolean is_v4 = klass->addr_family == AF_INET;
|
||||
const guint32 lock = ip_route_get_lock_flag (NMP_OBJECT_CAST_IP_ROUTE (obj));
|
||||
const guint32 table = nm_platform_route_table_coerce (NMP_OBJECT_CAST_IP_ROUTE (obj)->table_coerced);
|
||||
struct rtmsg rtmsg = {
|
||||
.rtm_family = klass->addr_family,
|
||||
.rtm_tos = is_v4
|
||||
? obj->ip4_route.tos
|
||||
: 0,
|
||||
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
|
||||
.rtm_table = table <= 0xFF ? table : RT_TABLE_UNSPEC,
|
||||
.rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source),
|
||||
.rtm_scope = is_v4
|
||||
? nm_platform_route_scope_inv (obj->ip4_route.scope_inv)
|
||||
|
|
@ -2531,7 +2615,6 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
|
||||
|
||||
nm_assert (((NMPNlmFlags) ((int) nlmsgflags)) == nlmsgflags);
|
||||
msg = nlmsg_alloc_simple (nlmsg_type, (int) nlmsgflags);
|
||||
if (!msg)
|
||||
g_return_val_if_reached (NULL);
|
||||
|
|
@ -2555,6 +2638,9 @@ _nl_msg_new_route (int nlmsg_type,
|
|||
|
||||
NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
|
||||
|
||||
if (table > 0xFF)
|
||||
NLA_PUT_U32 (msg, RTA_TABLE, table);
|
||||
|
||||
if (is_v4) {
|
||||
if (NMP_OBJECT_CAST_IP4_ROUTE (obj)->pref_src)
|
||||
NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src);
|
||||
|
|
@ -2610,56 +2696,27 @@ nla_put_failure:
|
|||
g_return_val_if_reached (NULL);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static int _support_kernel_extended_ifa_flags = -1;
|
||||
|
||||
#define _support_kernel_extended_ifa_flags_still_undecided() (G_UNLIKELY (_support_kernel_extended_ifa_flags == -1))
|
||||
|
||||
static void
|
||||
_support_kernel_extended_ifa_flags_detect (struct nl_msg *msg)
|
||||
{
|
||||
struct nlmsghdr *msg_hdr;
|
||||
|
||||
if (!_support_kernel_extended_ifa_flags_still_undecided ())
|
||||
return;
|
||||
|
||||
msg_hdr = nlmsg_hdr (msg);
|
||||
if (msg_hdr->nlmsg_type != RTM_NEWADDR)
|
||||
return;
|
||||
|
||||
/* the extended address flags are only set for AF_INET6 */
|
||||
if (((struct ifaddrmsg *) nlmsg_data (msg_hdr))->ifa_family != AF_INET6)
|
||||
return;
|
||||
|
||||
/* see if the nl_msg contains the IFA_FLAGS attribute. If it does,
|
||||
* we assume, that the kernel supports extended flags, IFA_F_MANAGETEMPADDR
|
||||
* and IFA_F_NOPREFIXROUTE (they were added together).
|
||||
**/
|
||||
_support_kernel_extended_ifa_flags = !!nlmsg_find_attr (msg_hdr, sizeof (struct ifaddrmsg), IFA_FLAGS);
|
||||
_LOG2D ("kernel-support: extended-ifa-flags: %s", _support_kernel_extended_ifa_flags ? "detected" : "not detected");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_support_kernel_extended_ifa_flags_get (void)
|
||||
{
|
||||
if (_support_kernel_extended_ifa_flags_still_undecided ()) {
|
||||
_LOG2D ("kernel-support: extended-ifa-flags: %s", "unable to detect kernel support for handling IPv6 temporary addresses. Assume support");
|
||||
_support_kernel_extended_ifa_flags = 1;
|
||||
}
|
||||
return _support_kernel_extended_ifa_flags;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* NMPlatform types and functions
|
||||
******************************************************************/
|
||||
|
||||
typedef enum {
|
||||
DELAYED_ACTION_RESPONSE_TYPE_VOID = 0,
|
||||
DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS = 1,
|
||||
DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET = 2,
|
||||
} DelayedActionWaitForNlResponseType;
|
||||
|
||||
typedef struct {
|
||||
guint32 seq_number;
|
||||
WaitForNlResponseResult seq_result;
|
||||
DelayedActionWaitForNlResponseType response_type;
|
||||
gint64 timeout_abs_ns;
|
||||
WaitForNlResponseResult *out_seq_result;
|
||||
gint *out_refresh_all_in_progess;
|
||||
union {
|
||||
gint *out_refresh_all_in_progess;
|
||||
NMPObject **out_route_get;
|
||||
gpointer out_data;
|
||||
} response;
|
||||
} DelayedActionWaitForNlResponseData;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -2990,7 +3047,7 @@ sysctl_get (NMPlatform *platform, const char *pathid, int dirfd, const char *pat
|
|||
static gboolean
|
||||
check_support_kernel_extended_ifa_flags (NMPlatform *platform)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE);
|
||||
nm_assert (NM_IS_LINUX_PLATFORM (platform));
|
||||
|
||||
return _support_kernel_extended_ifa_flags_get ();
|
||||
}
|
||||
|
|
@ -2998,7 +3055,7 @@ check_support_kernel_extended_ifa_flags (NMPlatform *platform)
|
|||
static gboolean
|
||||
check_support_user_ipv6ll (NMPlatform *platform)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), FALSE);
|
||||
nm_assert (NM_IS_LINUX_PLATFORM (platform));
|
||||
|
||||
return _support_user_ipv6ll_get ();
|
||||
}
|
||||
|
|
@ -3078,11 +3135,12 @@ delayed_action_to_string_full (DelayedActionType action_type, gpointer user_data
|
|||
gint64 timeout = data->timeout_abs_ns - nm_utils_get_monotonic_timestamp_ns ();
|
||||
char b[255];
|
||||
|
||||
nm_utils_strbuf_append (&buf, &buf_size, " (seq %u, timeout in %s%"G_GINT64_FORMAT".%09"G_GINT64_FORMAT"%s%s)",
|
||||
nm_utils_strbuf_append (&buf, &buf_size, " (seq %u, timeout in %s%"G_GINT64_FORMAT".%09"G_GINT64_FORMAT", response-type %d%s%s)",
|
||||
data->seq_number,
|
||||
timeout < 0 ? "-" : "",
|
||||
(timeout < 0 ? -timeout : timeout) / NM_UTILS_NS_PER_SECOND,
|
||||
(timeout < 0 ? -timeout : timeout) % NM_UTILS_NS_PER_SECOND,
|
||||
(int) data->response_type,
|
||||
data->seq_result ? ", " : "",
|
||||
data->seq_result ? wait_for_nl_response_to_string (data->seq_result, b, sizeof (b)) : "");
|
||||
} else
|
||||
|
|
@ -3144,9 +3202,22 @@ delayed_action_wait_for_nl_response_complete (NMPlatform *platform,
|
|||
priv->delayed_action.flags &= ~DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE;
|
||||
if (data->out_seq_result)
|
||||
*data->out_seq_result = seq_result;
|
||||
if (data->out_refresh_all_in_progess) {
|
||||
nm_assert (*data->out_refresh_all_in_progess > 0);
|
||||
*data->out_refresh_all_in_progess -= 1;
|
||||
switch (data->response_type) {
|
||||
case DELAYED_ACTION_RESPONSE_TYPE_VOID:
|
||||
break;
|
||||
case DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS:
|
||||
if (data->response.out_refresh_all_in_progess) {
|
||||
nm_assert (*data->response.out_refresh_all_in_progess > 0);
|
||||
*data->response.out_refresh_all_in_progess -= 1;
|
||||
data->response.out_refresh_all_in_progess = NULL;
|
||||
}
|
||||
break;
|
||||
case DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET:
|
||||
if (data->response.out_route_get) {
|
||||
nm_assert (!*data->response.out_route_get);
|
||||
data->response.out_route_get = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
g_array_remove_index_fast (priv->delayed_action.list_wait_for_nl_response, idx);
|
||||
|
|
@ -3356,13 +3427,15 @@ static void
|
|||
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform,
|
||||
guint32 seq_number,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
gint *out_refresh_all_in_progess)
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
DelayedActionWaitForNlResponseData data = {
|
||||
.seq_number = seq_number,
|
||||
.timeout_abs_ns = nm_utils_get_monotonic_timestamp_ns () + (200 * (NM_UTILS_NS_PER_SECOND / 1000)),
|
||||
.out_seq_result = out_seq_result,
|
||||
.out_refresh_all_in_progess = out_refresh_all_in_progess,
|
||||
.response_type = response_type,
|
||||
.response.out_data = response_out_data,
|
||||
};
|
||||
|
||||
delayed_action_schedule (platform,
|
||||
|
|
@ -3647,30 +3720,111 @@ cache_on_change (NMPlatform *platform,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint32
|
||||
_nlh_seq_next_get (NMLinuxPlatformPrivate *priv)
|
||||
{
|
||||
/* generate a new sequence number, but skip zero. */
|
||||
return priv->nlh_seq_next++ ?: priv->nlh_seq_next++;
|
||||
}
|
||||
|
||||
/**
|
||||
* _nl_send_nlmsghdr:
|
||||
* @platform:
|
||||
* @nlhdr:
|
||||
* @out_seq_result:
|
||||
* @response_type:
|
||||
* @response_out_data:
|
||||
*
|
||||
* Returns: 0 on success or a negative errno. Beware, it's an errno, not nlerror.
|
||||
*/
|
||||
static int
|
||||
_nl_send_auto_with_seq (NMPlatform *platform,
|
||||
struct nl_msg *nlmsg,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
gint *out_refresh_all_in_progess)
|
||||
_nl_send_nlmsghdr (NMPlatform *platform,
|
||||
struct nlmsghdr *nlhdr,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
guint32 seq;
|
||||
int nle;
|
||||
|
||||
/* complete the message with a sequence number (ensuring it's not zero). */
|
||||
seq = priv->nlh_seq_next++ ?: priv->nlh_seq_next++;
|
||||
nm_assert (nlhdr);
|
||||
|
||||
nlmsg_hdr (nlmsg)->nlmsg_seq = seq;
|
||||
seq = _nlh_seq_next_get (priv);
|
||||
nlhdr->nlmsg_seq = seq;
|
||||
|
||||
{
|
||||
struct sockaddr_nl nladdr = {
|
||||
.nl_family = AF_NETLINK,
|
||||
};
|
||||
struct iovec iov = {
|
||||
.iov_base = nlhdr,
|
||||
.iov_len = nlhdr->nlmsg_len
|
||||
};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &nladdr,
|
||||
.msg_namelen = sizeof(nladdr),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
int try_count;
|
||||
|
||||
if (!nlhdr->nlmsg_pid)
|
||||
nlhdr->nlmsg_pid = nl_socket_get_local_port (priv->nlh);
|
||||
nlhdr->nlmsg_flags |= (NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
||||
try_count = 0;
|
||||
again:
|
||||
nle = sendmsg (nl_socket_get_fd (priv->nlh), &msg, 0);
|
||||
if (nle < 0) {
|
||||
nle = errno;
|
||||
if (nle == EINTR && try_count++ < 100)
|
||||
goto again;
|
||||
_LOGD ("netlink: nl-send-nlmsghdr: failed sending message: %s (%d)", g_strerror (nle), nle);
|
||||
return -nle;
|
||||
}
|
||||
}
|
||||
|
||||
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result,
|
||||
response_type, response_out_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _nl_send_nlmsg:
|
||||
* @platform:
|
||||
* @nlmsg:
|
||||
* @out_seq_result:
|
||||
* @response_type:
|
||||
* @response_out_data:
|
||||
*
|
||||
* Returns: 0 on success, or a negative libnl3 error code (beware, it's not an errno).
|
||||
*/
|
||||
static int
|
||||
_nl_send_nlmsg (NMPlatform *platform,
|
||||
struct nl_msg *nlmsg,
|
||||
WaitForNlResponseResult *out_seq_result,
|
||||
DelayedActionWaitForNlResponseType response_type,
|
||||
gpointer response_out_data)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
struct nlmsghdr *nlhdr;
|
||||
guint32 seq;
|
||||
int nle;
|
||||
|
||||
nlhdr = nlmsg_hdr (nlmsg);
|
||||
seq = _nlh_seq_next_get (priv);
|
||||
nlhdr->nlmsg_seq = seq;
|
||||
|
||||
nle = nl_send_auto (priv->nlh, nlmsg);
|
||||
if (nle < 0) {
|
||||
_LOGD ("netlink: nl-send-nlmsg: failed sending message: %s (%d)", nl_geterror (nle), nle);
|
||||
return nle;
|
||||
}
|
||||
|
||||
if (nle >= 0) {
|
||||
nle = 0;
|
||||
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result, out_refresh_all_in_progess);
|
||||
} else
|
||||
_LOGD ("netlink: send: failed sending message: %s (%d)", nl_geterror (nle), nle);
|
||||
|
||||
return nle;
|
||||
delayed_action_schedule_WAIT_FOR_NL_RESPONSE (platform, seq, out_seq_result,
|
||||
response_type, response_out_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3705,7 +3859,7 @@ do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const cha
|
|||
0,
|
||||
0);
|
||||
if (nlmsg)
|
||||
_nl_send_auto_with_seq (platform, nlmsg, NULL, NULL);
|
||||
_nl_send_nlmsg (platform, nlmsg, NULL, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3767,7 +3921,7 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
|
|||
if (nle < 0)
|
||||
continue;
|
||||
|
||||
if (_nl_send_auto_with_seq (platform, nlmsg, NULL, out_refresh_all_in_progess) < 0) {
|
||||
if (_nl_send_nlmsg (platform, nlmsg, NULL, DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS, out_refresh_all_in_progess) < 0) {
|
||||
nm_assert (*out_refresh_all_in_progess > 0);
|
||||
*out_refresh_all_in_progess -= 1;
|
||||
}
|
||||
|
|
@ -3797,13 +3951,12 @@ event_seq_check_refresh_all (NMPlatform *platform, guint32 seq_number)
|
|||
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) {
|
||||
data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
||||
|
||||
if (data->seq_number == priv->nlh_seq_last_seen) {
|
||||
if (data->out_refresh_all_in_progess) {
|
||||
nm_assert (*data->out_refresh_all_in_progess > 0);
|
||||
*data->out_refresh_all_in_progess -= 1;
|
||||
data->out_refresh_all_in_progess = NULL;
|
||||
break;
|
||||
}
|
||||
if ( data->response_type == DELAYED_ACTION_RESPONSE_TYPE_REFRESH_ALL_IN_PROGRESS
|
||||
&& data->response.out_refresh_all_in_progess
|
||||
&& data->seq_number == priv->nlh_seq_last_seen) {
|
||||
*data->response.out_refresh_all_in_progess -= 1;
|
||||
data->response.out_refresh_all_in_progess = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3851,6 +4004,7 @@ event_seq_check (NMPlatform *platform, guint32 seq_number, WaitForNlResponseResu
|
|||
static void
|
||||
event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_events)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv;
|
||||
nm_auto_nmpobj NMPObject *obj = NULL;
|
||||
NMPCacheOpsType cache_op;
|
||||
struct nlmsghdr *msghdr;
|
||||
|
|
@ -3861,7 +4015,8 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
|||
|
||||
msghdr = nlmsg_hdr (msg);
|
||||
|
||||
if (_support_kernel_extended_ifa_flags_still_undecided () && msghdr->nlmsg_type == RTM_NEWADDR)
|
||||
if ( _support_kernel_extended_ifa_flags_still_undecided ()
|
||||
&& msghdr->nlmsg_type == RTM_NEWADDR)
|
||||
_support_kernel_extended_ifa_flags_detect (msg);
|
||||
|
||||
if (!handle_events)
|
||||
|
|
@ -3919,6 +4074,30 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
|||
gboolean resync_required = FALSE;
|
||||
gboolean only_dirty = FALSE;
|
||||
|
||||
if (obj->ip_route.rt_cloned) {
|
||||
/* a cloned route might be a response for RTM_GETROUTE. Check, whether it is. */
|
||||
nm_assert (!nmp_object_is_alive (obj));
|
||||
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
if (NM_FLAGS_HAS (priv->delayed_action.flags, DELAYED_ACTION_TYPE_WAIT_FOR_NL_RESPONSE)) {
|
||||
guint i;
|
||||
|
||||
nm_assert (priv->delayed_action.list_wait_for_nl_response->len > 0);
|
||||
for (i = 0; i < priv->delayed_action.list_wait_for_nl_response->len; i++) {
|
||||
DelayedActionWaitForNlResponseData *data = &g_array_index (priv->delayed_action.list_wait_for_nl_response, DelayedActionWaitForNlResponseData, i);
|
||||
|
||||
if ( data->response_type == DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET
|
||||
&& data->response.out_route_get) {
|
||||
nm_assert (!*data->response.out_route_get);
|
||||
if (data->seq_number == nlmsg_hdr (msg)->nlmsg_seq) {
|
||||
*data->response.out_route_get = nmp_object_clone (obj, FALSE);
|
||||
data->response.out_route_get = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cache_op = nmp_cache_update_netlink_route (cache,
|
||||
obj,
|
||||
is_dump,
|
||||
|
|
@ -4006,26 +4185,13 @@ do_add_link_with_lookup (NMPlatform *platform,
|
|||
|
||||
event_handler_read_netlink (platform, FALSE);
|
||||
|
||||
if (nmp_cache_lookup_link_full (cache, 0, name, FALSE, NM_LINK_TYPE_NONE, NULL, NULL)) {
|
||||
/* hm, a link with such a name already exists. Try reloading first. */
|
||||
do_request_link (platform, 0, name);
|
||||
|
||||
obj = nmp_cache_lookup_link_full (cache, 0, name, FALSE, NM_LINK_TYPE_NONE, NULL, NULL);
|
||||
if (obj) {
|
||||
_LOGE ("do-add-link[%s/%s]: link already exists: %s",
|
||||
name,
|
||||
nm_link_type_to_string (link_type),
|
||||
nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ID, NULL, 0));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
|
||||
nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL);
|
||||
if (nle < 0) {
|
||||
_LOGE ("do-add-link[%s/%s]: failed sending netlink request \"%s\" (%d)",
|
||||
name,
|
||||
nm_link_type_to_string (link_type),
|
||||
nl_geterror (nle), -nle);
|
||||
NM_SET_OUT (out_link, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -4035,35 +4201,29 @@ do_add_link_with_lookup (NMPlatform *platform,
|
|||
|
||||
_NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK
|
||||
? LOGL_DEBUG
|
||||
: LOGL_ERR,
|
||||
: LOGL_WARN,
|
||||
"do-add-link[%s/%s]: %s",
|
||||
name,
|
||||
nm_link_type_to_string (link_type),
|
||||
wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)));
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
|
||||
obj = nmp_cache_lookup_link_full (cache, 0, name, FALSE, link_type, NULL, NULL);
|
||||
|
||||
if (!obj) {
|
||||
/* either kernel signaled failure, or it signaled success and the link object
|
||||
* is not (yet) in the cache. Try to reload it... */
|
||||
do_request_link (platform, 0, name);
|
||||
if (out_link) {
|
||||
obj = nmp_cache_lookup_link_full (cache, 0, name, FALSE, link_type, NULL, NULL);
|
||||
*out_link = NMP_OBJECT_CAST_LINK (obj);
|
||||
}
|
||||
|
||||
if (out_link)
|
||||
*out_link = obj ? &obj->link : NULL;
|
||||
return !!obj;
|
||||
return seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *nlmsg)
|
||||
static NMPlatformError
|
||||
do_add_addrroute (NMPlatform *platform,
|
||||
const NMPObject *obj_id,
|
||||
struct nl_msg *nlmsg,
|
||||
gboolean suppress_netlink_failure)
|
||||
{
|
||||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
const NMPObject *obj;
|
||||
NMPCache *cache = nm_platform_get_cache (platform);
|
||||
|
||||
nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id),
|
||||
NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS,
|
||||
|
|
@ -4071,45 +4231,43 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
|
|||
|
||||
event_handler_read_netlink (platform, FALSE);
|
||||
|
||||
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
|
||||
nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL);
|
||||
if (nle < 0) {
|
||||
_LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)",
|
||||
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
|
||||
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
|
||||
nl_geterror (nle), -nle);
|
||||
return FALSE;
|
||||
return NM_PLATFORM_ERROR_NETLINK;
|
||||
}
|
||||
|
||||
delayed_action_handle_all (platform, FALSE);
|
||||
|
||||
nm_assert (seq_result);
|
||||
|
||||
_NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK
|
||||
_NMLOG (( seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK
|
||||
|| ( suppress_netlink_failure
|
||||
&& seq_result < 0))
|
||||
? LOGL_DEBUG
|
||||
: LOGL_ERR,
|
||||
: LOGL_WARN,
|
||||
"do-add-%s[%s]: %s",
|
||||
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
|
||||
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
|
||||
wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)));
|
||||
|
||||
/* In rare cases, the object is not yet ready as we received the ACK from
|
||||
* kernel. Need to refetch.
|
||||
*
|
||||
* We want to safe the expensive refetch, thus we look first into the cache
|
||||
* whether the object exists.
|
||||
*
|
||||
* FIXME: if the object already existed previously, we might not notice a
|
||||
* missing update. It's not clear how to fix that reliably without refechting
|
||||
* all the time. */
|
||||
obj = nmp_cache_lookup_obj (cache, obj_id);
|
||||
if (!obj) {
|
||||
do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id));
|
||||
obj = nmp_cache_lookup_obj (cache, obj_id);
|
||||
if (NMP_OBJECT_GET_TYPE (obj_id) == NMP_OBJECT_TYPE_IP6_ADDRESS) {
|
||||
/* In rare cases, the object is not yet ready as we received the ACK from
|
||||
* kernel. Need to refetch.
|
||||
*
|
||||
* We want to safe the expensive refetch, thus we look first into the cache
|
||||
* whether the object exists.
|
||||
*
|
||||
* rh#1484434 */
|
||||
if (!nmp_cache_lookup_obj (nm_platform_get_cache (platform),
|
||||
obj_id))
|
||||
do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id));
|
||||
}
|
||||
|
||||
/* Adding is only successful, if kernel reported success *and* we have the
|
||||
* expected object in cache afterwards. */
|
||||
return obj && seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
|
||||
return wait_for_nl_response_to_plerr (seq_result);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -4118,25 +4276,25 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
|
|||
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
int nle;
|
||||
char s_buf[256];
|
||||
gboolean success = TRUE;
|
||||
gboolean success;
|
||||
const char *log_detail = "";
|
||||
NMPCache *cache = nm_platform_get_cache (platform);
|
||||
|
||||
event_handler_read_netlink (platform, FALSE);
|
||||
|
||||
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
|
||||
nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL);
|
||||
if (nle < 0) {
|
||||
_LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
|
||||
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
|
||||
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
|
||||
nl_geterror (nle), -nle);
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
delayed_action_handle_all (platform, FALSE);
|
||||
|
||||
nm_assert (seq_result);
|
||||
|
||||
success = TRUE;
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) {
|
||||
/* ok */
|
||||
} else if (NM_IN_SET (-((int) seq_result), ESRCH, ENOENT))
|
||||
|
|
@ -4151,21 +4309,14 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
|
|||
else
|
||||
success = FALSE;
|
||||
|
||||
_NMLOG (success ? LOGL_DEBUG : LOGL_ERR,
|
||||
_NMLOG (success ? LOGL_DEBUG : LOGL_WARN,
|
||||
"do-delete-%s[%s]: %s%s",
|
||||
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
|
||||
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
|
||||
wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)),
|
||||
log_detail);
|
||||
|
||||
out:
|
||||
if (!nmp_cache_lookup_obj (cache, obj_id))
|
||||
return TRUE;
|
||||
|
||||
/* such an object still exists in the cache. To be sure, refetch it (and
|
||||
* hope it's gone) */
|
||||
do_request_one_type (platform, NMP_OBJECT_GET_TYPE (obj_id));
|
||||
return !nmp_cache_lookup_obj (cache, obj_id);
|
||||
return success;
|
||||
}
|
||||
|
||||
static WaitForNlResponseResult
|
||||
|
|
@ -4181,7 +4332,7 @@ do_change_link_request (NMPlatform *platform,
|
|||
return WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
|
||||
retry:
|
||||
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
|
||||
nle = _nl_send_nlmsg (platform, nlmsg, &seq_result, DELAYED_ACTION_RESPONSE_TYPE_VOID, NULL);
|
||||
if (nle < 0) {
|
||||
_LOGE ("do-change-link[%d]: failure sending netlink request \"%s\" (%d)",
|
||||
ifindex,
|
||||
|
|
@ -4226,7 +4377,7 @@ do_change_link_result (NMPlatform *platform,
|
|||
log_level = LOGL_DEBUG;
|
||||
result = NM_PLATFORM_ERROR_NOT_FOUND;
|
||||
} else {
|
||||
log_level = LOGL_ERR;
|
||||
log_level = LOGL_WARN;
|
||||
result = NM_PLATFORM_ERROR_UNSPECIFIED;
|
||||
}
|
||||
_NMLOG (log_level,
|
||||
|
|
@ -4421,15 +4572,15 @@ link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enable
|
|||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
guint8 mode = enabled ? NM_IN6_ADDR_GEN_MODE_NONE : NM_IN6_ADDR_GEN_MODE_EUI64;
|
||||
|
||||
_LOGD ("link: change %d: user-ipv6ll: set IPv6 address generation mode to %s",
|
||||
ifindex,
|
||||
nm_platform_link_inet6_addrgenmode2str (mode, NULL, 0));
|
||||
|
||||
if (!_support_user_ipv6ll_get ()) {
|
||||
_LOGD ("link: change %d: user-ipv6ll: not supported", ifindex);
|
||||
return NM_PLATFORM_ERROR_OPNOTSUPP;
|
||||
}
|
||||
|
||||
_LOGD ("link: change %d: user-ipv6ll: set IPv6 address generation mode to %s",
|
||||
ifindex,
|
||||
nm_platform_link_inet6_addrgenmode2str (mode, NULL, 0));
|
||||
|
||||
nlmsg = _nl_msg_new_link (RTM_NEWLINK,
|
||||
0,
|
||||
ifindex,
|
||||
|
|
@ -5743,7 +5894,7 @@ ip4_address_add (NMPlatform *platform,
|
|||
label);
|
||||
|
||||
nmp_object_stackinit_id_ip4_address (&obj_id, ifindex, addr, plen, peer_addr);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg, FALSE) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5773,7 +5924,7 @@ ip6_address_add (NMPlatform *platform,
|
|||
NULL);
|
||||
|
||||
nmp_object_stackinit_id_ip6_address (&obj_id, ifindex, &addr);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg);
|
||||
return do_add_addrroute (platform, &obj_id, nlmsg, FALSE) == NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5828,7 +5979,7 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
static NMPlatformError
|
||||
ip_route_add (NMPlatform *platform,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
|
|
@ -5836,34 +5987,27 @@ ip_route_add (NMPlatform *platform,
|
|||
{
|
||||
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
|
||||
NMPObject obj;
|
||||
NMPlatformIP4Route *r4;
|
||||
NMPlatformIP6Route *r6;
|
||||
|
||||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route);
|
||||
r4 = NMP_OBJECT_CAST_IP4_ROUTE (&obj);
|
||||
r4->network = nm_utils_ip4_address_clear_host_address (r4->network, r4->plen);
|
||||
r4->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r4->rt_source),
|
||||
r4->scope_inv = nm_platform_route_scope_inv (!r4->gateway
|
||||
? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
|
||||
break;
|
||||
case AF_INET6:
|
||||
nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route);
|
||||
r6 = NMP_OBJECT_CAST_IP6_ROUTE (&obj);
|
||||
nm_utils_ip6_address_clear_host_address (&r6->network, &r6->network, r6->plen);
|
||||
r6->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (r6->rt_source),
|
||||
r6->metric = nm_utils_ip6_route_metric_normalize (r6->metric);
|
||||
nm_utils_ip6_address_clear_host_address (&r6->src, &r6->src, r6->src_plen);
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE, flags, &obj);
|
||||
nm_platform_ip_route_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (&obj));
|
||||
|
||||
nlmsg = _nl_msg_new_route (RTM_NEWROUTE, flags & NMP_NLM_FLAG_FMASK, &obj);
|
||||
if (!nlmsg)
|
||||
g_return_val_if_reached (FALSE);
|
||||
return do_add_addrroute (platform, &obj, nlmsg);
|
||||
g_return_val_if_reached (NM_PLATFORM_ERROR_BUG);
|
||||
return do_add_addrroute (platform,
|
||||
&obj,
|
||||
nlmsg,
|
||||
NM_FLAGS_HAS (flags, NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5887,6 +6031,77 @@ ip_route_delete (NMPlatform *platform,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMPlatformError
|
||||
ip_route_get (NMPlatform *platform,
|
||||
int addr_family,
|
||||
gconstpointer address,
|
||||
NMPObject **out_route)
|
||||
{
|
||||
const gboolean is_v4 = (addr_family == AF_INET);
|
||||
const int addr_len = is_v4 ? 4 : 16;
|
||||
int try_count = 0;
|
||||
WaitForNlResponseResult seq_result;
|
||||
int nle;
|
||||
nm_auto_nlmsg NMPObject *route = NULL;
|
||||
|
||||
nm_assert (NM_IS_LINUX_PLATFORM (platform));
|
||||
nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));
|
||||
nm_assert (address);
|
||||
|
||||
do {
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct rtmsg r;
|
||||
char buf[64];
|
||||
} req = {
|
||||
.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)),
|
||||
.n.nlmsg_flags = NLM_F_REQUEST,
|
||||
.n.nlmsg_type = RTM_GETROUTE,
|
||||
.r.rtm_family = addr_family,
|
||||
.r.rtm_tos = 0,
|
||||
.r.rtm_dst_len = is_v4 ? 32 : 128,
|
||||
.r.rtm_flags = 0x1000 /* RTM_F_LOOKUP_TABLE */,
|
||||
};
|
||||
|
||||
g_clear_pointer (&route, nmp_object_unref);
|
||||
|
||||
if (!_nl_addattr_l (&req.n, sizeof (req), RTA_DST, address, addr_len))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
|
||||
nle = _nl_send_nlmsghdr (platform, &req.n, &seq_result, DELAYED_ACTION_RESPONSE_TYPE_ROUTE_GET, &route);
|
||||
if (nle < 0) {
|
||||
_LOGE ("get-route: failure sending netlink request \"%s\" (%d)",
|
||||
g_strerror (-nle), -nle);
|
||||
return NM_PLATFORM_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
delayed_action_handle_all (platform, FALSE);
|
||||
|
||||
/* Retry, if we failed due to a cache resync. That can happen when the netlink
|
||||
* socket fills up and we lost the response. */
|
||||
} while ( seq_result == WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC
|
||||
&& ++try_count < 10);
|
||||
|
||||
if (seq_result < 0) {
|
||||
/* negative seq_result is an errno from kernel. Map it to negative
|
||||
* NMPlatformError (which are also errno). */
|
||||
return (NMPlatformError) seq_result;
|
||||
}
|
||||
|
||||
if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) {
|
||||
if (route) {
|
||||
NM_SET_OUT (out_route, g_steal_pointer (&route));
|
||||
return NM_PLATFORM_ERROR_SUCCESS;
|
||||
}
|
||||
seq_result = WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_UNKNOWN;
|
||||
}
|
||||
|
||||
return NM_PLATFORM_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI))
|
||||
#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL))
|
||||
#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP))
|
||||
|
|
@ -6616,6 +6831,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|||
|
||||
platform_class->ip_route_add = ip_route_add;
|
||||
platform_class->ip_route_delete = ip_route_delete;
|
||||
platform_class->ip_route_get = ip_route_get;
|
||||
|
||||
platform_class->check_support_kernel_extended_ifa_flags = check_support_kernel_extended_ifa_flags;
|
||||
platform_class->check_support_user_ipv6ll = check_support_user_ipv6ll;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -52,6 +52,9 @@
|
|||
|
||||
struct udev_device;
|
||||
|
||||
typedef gboolean (*NMPObjectPredicateFunc) (const NMPObject *obj,
|
||||
gpointer user_data);
|
||||
|
||||
/* workaround for older libnl version, that does not define these flags. */
|
||||
#ifndef IFA_F_MANAGETEMPADDR
|
||||
#define IFA_F_MANAGETEMPADDR 0x100
|
||||
|
|
@ -60,6 +63,8 @@ struct udev_device;
|
|||
#define IFA_F_NOPREFIXROUTE 0x200
|
||||
#endif
|
||||
|
||||
#define NM_RT_SCOPE_LINK 253 /* RT_SCOPE_LINK */
|
||||
|
||||
/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
|
||||
* that don't define it. */
|
||||
#define NM_IN6_ADDR_GEN_MODE_UNKNOWN 255 /* no corresponding value. */
|
||||
|
|
@ -81,6 +86,15 @@ typedef enum {
|
|||
NMP_NLM_FLAG_F_CREATE = 0x400, /* NLM_F_CREATE, Create, if it does not exist */
|
||||
NMP_NLM_FLAG_F_APPEND = 0x800, /* NLM_F_APPEND, Add to end of list */
|
||||
|
||||
NMP_NLM_FLAG_FMASK = 0xFFFF, /* a mask for all NMP_NLM_FLAG_F_* flags */
|
||||
|
||||
/* instructs NM to suppress logging an error message for any failures
|
||||
* received from kernel.
|
||||
*
|
||||
* It will still log with debug-level, and it will still log
|
||||
* other failures aside the kernel response. */
|
||||
NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE = 0x10000,
|
||||
|
||||
/* the following aliases correspond to iproute2's `ip route CMD` for
|
||||
* RTM_NEWROUTE, with CMD being one of add, change, replace, prepend,
|
||||
* append and test. */
|
||||
|
|
@ -153,6 +167,7 @@ typedef enum { /*< skip >*/
|
|||
NM_PLATFORM_ERROR_NOT_SLAVE,
|
||||
NM_PLATFORM_ERROR_NO_FIRMWARE,
|
||||
NM_PLATFORM_ERROR_OPNOTSUPP,
|
||||
NM_PLATFORM_ERROR_NETLINK,
|
||||
} NMPlatformError;
|
||||
|
||||
#define NM_PLATFORM_LINK_OTHER_NETNS (-1)
|
||||
|
|
@ -409,6 +424,13 @@ typedef union {
|
|||
/* RTA_PRIORITY (iproute2: metric) */ \
|
||||
guint32 metric; \
|
||||
\
|
||||
/* rtm_table, RTA_TABLE.
|
||||
*
|
||||
* This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and
|
||||
* zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main
|
||||
* table. Use nm_platform_route_table_coerce(). */ \
|
||||
guint32 table_coerced; \
|
||||
\
|
||||
/*end*/
|
||||
|
||||
|
||||
|
|
@ -420,8 +442,23 @@ typedef struct {
|
|||
};
|
||||
} NMPlatformIPRoute;
|
||||
|
||||
#if _NM_CC_SUPPORT_GENERIC
|
||||
#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
|
||||
(_Generic ((route), \
|
||||
const NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
NMPlatformIPRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
const NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
NMPlatformIPXRoute *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
const NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
NMPlatformIP4Route *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
const NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
NMPlatformIP6Route *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
const void *: ((const NMPlatformIPRoute *) (route))->plen, \
|
||||
void *: ((const NMPlatformIPRoute *) (route))->plen) == 0)
|
||||
#else
|
||||
#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
|
||||
( ((const NMPlatformIPRoute *) (route))->plen <= 0 )
|
||||
#endif
|
||||
|
||||
struct _NMPlatformIP4Route {
|
||||
__NMPlatformIPRoute_COMMON;
|
||||
|
|
@ -503,11 +540,6 @@ typedef struct {
|
|||
gsize sizeof_route;
|
||||
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
|
||||
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);
|
||||
} NMPlatformVTableRoute;
|
||||
|
||||
|
|
@ -782,12 +814,17 @@ typedef struct {
|
|||
gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
|
||||
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
|
||||
|
||||
gboolean (*ip_route_add) (NMPlatform *,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
const NMPlatformIPRoute *route);
|
||||
NMPlatformError (*ip_route_add) (NMPlatform *,
|
||||
NMPNlmFlags flags,
|
||||
int addr_family,
|
||||
const NMPlatformIPRoute *route);
|
||||
gboolean (*ip_route_delete) (NMPlatform *, const NMPObject *obj);
|
||||
|
||||
NMPlatformError (*ip_route_get) (NMPlatform *self,
|
||||
int addr_family,
|
||||
gconstpointer address,
|
||||
NMPObject **out_route);
|
||||
|
||||
gboolean (*check_support_kernel_extended_ifa_flags) (NMPlatform *);
|
||||
gboolean (*check_support_user_ipv6ll) (NMPlatform *);
|
||||
} NMPlatformClass;
|
||||
|
|
@ -822,6 +859,27 @@ NMPlatform *nm_platform_get (void);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
* nm_platform_route_table_coerce:
|
||||
* @table: the route table, either its original value, or its coerced.
|
||||
*
|
||||
* Returns: returns the coerced table id. If the table id is like
|
||||
* RTA_TABLE, it returns a value for NMPlatformIPRoute.table_coerced
|
||||
* and vice versa.
|
||||
*/
|
||||
static inline guint32
|
||||
nm_platform_route_table_coerce (guint32 table)
|
||||
{
|
||||
switch (table) {
|
||||
case 0 /* RT_TABLE_UNSPEC */:
|
||||
return 254;
|
||||
case 254 /* RT_TABLE_MAIN */:
|
||||
return 0;
|
||||
default:
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_route_scope_inv:
|
||||
* @scope: the route scope, either its original value, or its inverse.
|
||||
|
|
@ -847,8 +905,11 @@ gboolean nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns);
|
|||
|
||||
const char *nm_link_type_to_string (NMLinkType link_type);
|
||||
|
||||
const char *_nm_platform_error_to_string (NMPlatformError error);
|
||||
#define nm_platform_error_to_string(error) NM_UTILS_LOOKUP_STR (_nm_platform_error_to_string, error)
|
||||
const char *nm_platform_error_to_string (NMPlatformError error,
|
||||
char *buf,
|
||||
gsize buf_len);
|
||||
#define nm_platform_error_to_string_a(error) \
|
||||
(nm_platform_error_to_string ((error), g_alloca (30), 30))
|
||||
|
||||
#define NMP_SYSCTL_PATHID_ABSOLUTE(path) \
|
||||
((const char *) NULL), -1, (path)
|
||||
|
|
@ -897,12 +958,14 @@ struct _NMPLookup;
|
|||
const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *platform,
|
||||
const struct _NMPLookup *lookup);
|
||||
|
||||
gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
|
||||
gpointer user_data);
|
||||
gboolean nm_platform_lookup_predicate_routes_skip_rtprot_kernel (const NMPObject *obj,
|
||||
gpointer user_data);
|
||||
|
||||
GPtrArray *nm_platform_lookup_clone (NMPlatform *platform,
|
||||
const struct _NMPLookup *lookup,
|
||||
gboolean (*predicate) (const NMPObject *obj, gpointer user_data),
|
||||
NMPObjectPredicateFunc predicate,
|
||||
gpointer user_data);
|
||||
|
||||
/* convienience methods to lookup the link and access fields of NMPlatformLink. */
|
||||
|
|
@ -1095,13 +1158,36 @@ gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_
|
|||
gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
|
||||
gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, GPtrArray *known_addresse);
|
||||
gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GPtrArray *known_addresses, gboolean keep_link_local);
|
||||
gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
|
||||
gboolean nm_platform_ip_address_flush (NMPlatform *self,
|
||||
int addr_family,
|
||||
int ifindex);
|
||||
|
||||
gboolean nm_platform_ip4_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route);
|
||||
gboolean nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *route);
|
||||
void nm_platform_ip_route_normalize (int addr_family,
|
||||
NMPlatformIPRoute *route);
|
||||
|
||||
NMPlatformError nm_platform_ip_route_add (NMPlatform *self,
|
||||
NMPNlmFlags flags,
|
||||
const NMPObject *route);
|
||||
NMPlatformError nm_platform_ip4_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP4Route *route);
|
||||
NMPlatformError nm_platform_ip6_route_add (NMPlatform *self, NMPNlmFlags flags, const NMPlatformIP6Route *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);
|
||||
|
||||
NMPlatformError nm_platform_ip_route_get (NMPlatform *self,
|
||||
int addr_family,
|
||||
gconstpointer address,
|
||||
NMPObject **out_route);
|
||||
|
||||
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_infiniband_to_string (const NMPlatformLnkInfiniband *lnk, char *buf, gsize len);
|
||||
|
|
@ -1192,6 +1278,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_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);
|
||||
|
||||
#endif /* __NETWORKMANAGER_PLATFORM_H__ */
|
||||
|
|
|
|||
|
|
@ -676,11 +676,11 @@ ASSERT_nmp_cache_ops (const NMPCache *cache,
|
|||
|
||||
const NMDedupMultiHeadEntry *nm_platform_lookup_all (NMPlatform *platform,
|
||||
NMPCacheIdType cache_id_type,
|
||||
NMPObject *obj);
|
||||
const NMPObject *obj);
|
||||
|
||||
const NMDedupMultiEntry *nm_platform_lookup_entry (NMPlatform *platform,
|
||||
NMPCacheIdType cache_id_type,
|
||||
NMPObject *obj);
|
||||
const NMPObject *obj);
|
||||
|
||||
static inline const NMDedupMultiHeadEntry *
|
||||
nm_platform_lookup_obj_type (NMPlatform *platform,
|
||||
|
|
@ -717,7 +717,7 @@ static inline GPtrArray *
|
|||
nm_platform_lookup_addrroute_clone (NMPlatform *platform,
|
||||
NMPObjectType obj_type,
|
||||
int ifindex,
|
||||
gboolean (*predicate) (const NMPObject *obj, gpointer user_data),
|
||||
NMPObjectPredicateFunc predicate,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPLookup lookup;
|
||||
|
|
@ -739,7 +739,7 @@ nm_platform_lookup_route_default (NMPlatform *platform,
|
|||
static inline GPtrArray *
|
||||
nm_platform_lookup_route_default_clone (NMPlatform *platform,
|
||||
NMPObjectType obj_type,
|
||||
gboolean (*predicate) (const NMPObject *obj, gpointer user_data),
|
||||
NMPObjectPredicateFunc predicate,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPLookup lookup;
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,7 @@ void nmtstp_ip4_route_add (NMPlatform *platform,
|
|||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_REPLACE, &route));
|
||||
g_assert_cmpint (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_REPLACE, &route), ==, NM_PLATFORM_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
void nmtstp_ip6_route_add (NMPlatform *platform,
|
||||
|
|
@ -1033,7 +1033,7 @@ void nmtstp_ip6_route_add (NMPlatform *platform,
|
|||
route.metric = metric;
|
||||
route.mss = mss;
|
||||
|
||||
g_assert (nm_platform_ip6_route_add (platform, NMP_NLM_FLAG_REPLACE, &route));
|
||||
g_assert_cmpint (nm_platform_ip6_route_add (platform, NMP_NLM_FLAG_REPLACE, &route), ==, NM_PLATFORM_ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ nmtstp_ip4_route_get_all (NMPlatform *platform,
|
|||
return nm_platform_lookup_addrroute_clone (platform,
|
||||
NMP_OBJECT_TYPE_IP4_ROUTE,
|
||||
ifindex,
|
||||
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +241,7 @@ nmtstp_ip6_route_get_all (NMPlatform *platform,
|
|||
return nm_platform_lookup_addrroute_clone (platform,
|
||||
NMP_OBJECT_TYPE_IP6_ROUTE,
|
||||
ifindex,
|
||||
nm_platform_lookup_predicate_routes_skip_rtprot_kernel,
|
||||
nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -791,7 +791,7 @@ test_software_detect (gconstpointer user_data)
|
|||
* namespaced, the creation can fail if a macvtap in another namespace
|
||||
* has the same index. Try to detect this situation and skip already
|
||||
* used indexes.
|
||||
* http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=17af2bce88d31e65ed73d638bb752d2e13c66ced
|
||||
* The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016.
|
||||
*/
|
||||
for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) {
|
||||
snprintf (buf, sizeof (buf), "/sys/class/macvtap/tap%d", i);
|
||||
|
|
@ -1728,8 +1728,8 @@ test_nl_bugs_veth (void)
|
|||
pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0);
|
||||
g_assert (pllink_veth0);
|
||||
if (pllink_veth0->parent == 0) {
|
||||
/* pre-4.1 kernels don't support exposing the veth peer as IFA_LINK. skip the remainder
|
||||
* of the test. */
|
||||
/* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer
|
||||
* as IFA_LINK. skip the remainder of the test. */
|
||||
goto out;
|
||||
}
|
||||
g_assert_cmpint (pllink_veth0->parent, ==, ifindex_veth1);
|
||||
|
|
@ -2023,8 +2023,8 @@ test_netns_general (gpointer fixture, gconstpointer test_data)
|
|||
_sysctl_assert_eq (platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6", NULL);
|
||||
_sysctl_assert_eq (platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6", NULL);
|
||||
|
||||
/* older kernels (Ubuntu 12.04) don't support ethtool -i for dummy devices. Work around that and
|
||||
* skip asserts that are known to fail. */
|
||||
/* Kernels prior to 3.19 dated 8 February, 2015 don't support ethtool -i for dummy devices.
|
||||
* Work around that and skip asserts that are known to fail. */
|
||||
ethtool_support = nmtstp_run_command ("ethtool -i dummy1_ > /dev/null") == 0;
|
||||
if (ethtool_support) {
|
||||
g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info));
|
||||
|
|
|
|||
|
|
@ -388,6 +388,43 @@ test_ip6_route (void)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_ip_route_get (void)
|
||||
{
|
||||
int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME);
|
||||
in_addr_t a;
|
||||
NMPlatformError result;
|
||||
nm_auto_nmpobj NMPObject *route = NULL;
|
||||
const NMPlatformIP4Route *r;
|
||||
|
||||
nmtstp_run_command_check ("ip route add 1.2.3.0/24 dev %s", DEVICE_NAME);
|
||||
|
||||
NMTST_WAIT_ASSERT (100, {
|
||||
nmtstp_wait_for_signal (NM_PLATFORM_GET, 10);
|
||||
if (nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.0"), 24, 0, 0))
|
||||
break;
|
||||
});
|
||||
|
||||
a = nmtst_inet4_from_string ("1.2.3.1");
|
||||
result = nm_platform_ip_route_get (NM_PLATFORM_GET,
|
||||
AF_INET,
|
||||
&a,
|
||||
&route);
|
||||
|
||||
g_assert (result == NM_PLATFORM_ERROR_SUCCESS);
|
||||
g_assert (NMP_OBJECT_GET_TYPE (route) == NMP_OBJECT_TYPE_IP4_ROUTE);
|
||||
g_assert (!NMP_OBJECT_IS_STACKINIT (route));
|
||||
g_assert (route->parent._ref_count == 1);
|
||||
r = NMP_OBJECT_CAST_IP4_ROUTE (route);
|
||||
g_assert (r->rt_cloned);
|
||||
g_assert (r->network == a);
|
||||
g_assert (r->plen == 32);
|
||||
|
||||
nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME);
|
||||
|
||||
nmtstp_wait_for_signal (NM_PLATFORM_GET, 50);
|
||||
}
|
||||
|
||||
static void
|
||||
test_ip4_zero_gateway (void)
|
||||
{
|
||||
|
|
@ -432,7 +469,7 @@ test_ip4_route_options (void)
|
|||
route.mtu = 1350;
|
||||
route.lock_cwnd = TRUE;
|
||||
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route));
|
||||
g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
|
||||
/* Test route listing */
|
||||
routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex);
|
||||
|
|
@ -560,7 +597,7 @@ test_ip6_route_options (gconstpointer test_data)
|
|||
_wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6);
|
||||
|
||||
for (i = 0; i < rts_n; i++)
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]));
|
||||
g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
|
||||
routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX);
|
||||
switch (TEST_IDX) {
|
||||
|
|
@ -666,7 +703,7 @@ again_find_idx:
|
|||
order_idx[order_len++] = idx;
|
||||
|
||||
r->ifindex = iface_data[idx].ifindex;
|
||||
g_assert (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_APPEND, r));
|
||||
g_assert (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_APPEND, r) == NM_PLATFORM_ERROR_SUCCESS);
|
||||
} else {
|
||||
i = nmtst_get_rand_int () % order_len;
|
||||
idx = order_idx[i];
|
||||
|
|
@ -739,6 +776,7 @@ _nmtstp_setup_tests (void)
|
|||
|
||||
if (nmtstp_is_root_test ()) {
|
||||
add_test_func_data ("/route/ip/1", test_ip, GINT_TO_POINTER (1));
|
||||
add_test_func ("/route/ip_route_get", test_ip_route_get);
|
||||
add_test_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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-pacrunner-manager.h"
|
||||
#include "nm-default-route-manager.h"
|
||||
#include "nm-route-manager.h"
|
||||
#include "nm-firewall-manager.h"
|
||||
#include "nm-config.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);
|
||||
|
||||
if (priv->ip_ifindex) {
|
||||
nm_platform_link_set_down (nm_netns_get_platform (priv->netns), priv->ip_ifindex);
|
||||
nm_route_manager_route_flush (nm_netns_get_route_manager (priv->netns), priv->ip_ifindex);
|
||||
nm_platform_address_flush (nm_netns_get_platform (priv->netns), priv->ip_ifindex);
|
||||
NMPlatform *platform = nm_netns_get_platform (priv->netns);
|
||||
|
||||
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);
|
||||
|
|
@ -704,41 +705,55 @@ device_state_changed (NMActiveConnection *active,
|
|||
}
|
||||
|
||||
static void
|
||||
add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32 vpn_gw)
|
||||
add_ip4_vpn_gateway_route (NMIP4Config *config,
|
||||
NMDevice *parent_device,
|
||||
in_addr_t vpn_gw,
|
||||
NMPlatform *platform)
|
||||
{
|
||||
NMIP4Config *parent_config;
|
||||
guint32 parent_gw;
|
||||
NMPlatformIP4Route route;
|
||||
guint32 route_metric;
|
||||
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
|
||||
|
||||
g_return_if_fail (NM_IS_IP4_CONFIG (config));
|
||||
g_return_if_fail (NM_IS_DEVICE (parent_device));
|
||||
g_return_if_fail (vpn_gw != 0);
|
||||
nm_assert (nm_ip4_config_get_ifindex (config) > 0);
|
||||
|
||||
/* Set up a route to the VPN gateway's public IP address through the default
|
||||
* network device if the VPN gateway is on a different subnet.
|
||||
*/
|
||||
parent_config = nm_device_get_ip4_config (parent_device);
|
||||
g_return_if_fail (parent_config != NULL);
|
||||
|
||||
parent_gw = nm_ip4_config_get_gateway (parent_config);
|
||||
|
||||
/* If the VPN gateway is in the same subnet as one of the parent device's
|
||||
* IP addresses, don't add the host route to it, but a route through the
|
||||
* parent device.
|
||||
*/
|
||||
if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32))
|
||||
parent_gw = 0;
|
||||
|
||||
/* actually, let's ask kernel how to reach @vpn_gw. If (and only if)
|
||||
* the destination is on @parent_device, then we take that @parent_gw. */
|
||||
if (nm_platform_ip_route_get (platform,
|
||||
AF_INET,
|
||||
&vpn_gw,
|
||||
(NMPObject **) &route_resolved) == NM_PLATFORM_ERROR_SUCCESS) {
|
||||
const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (route_resolved);
|
||||
|
||||
if (r->ifindex == nm_ip4_config_get_ifindex (config))
|
||||
parent_gw = r->gateway;
|
||||
}
|
||||
|
||||
route_metric = nm_device_get_ip4_route_metric (parent_device);
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.network = vpn_gw;
|
||||
route.plen = 32;
|
||||
route.gateway = parent_gw;
|
||||
/* Set up a device route if the parent device has no gateway */
|
||||
if (!parent_gw)
|
||||
route.ifindex = nm_device_get_ip_ifindex (parent_device);
|
||||
|
||||
/* If the VPN gateway is in the same subnet as one of the parent device's
|
||||
* IP addresses, don't add the host route to it, but a route through the
|
||||
* parent device.
|
||||
*/
|
||||
if (nm_ip4_config_destination_is_direct (parent_config, vpn_gw, 32))
|
||||
route.gateway = 0;
|
||||
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
route.metric = route_metric;
|
||||
nm_ip4_config_add_route (config, &route);
|
||||
|
|
@ -754,7 +769,6 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
|
|||
route.plen = 32;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
route.metric = route_metric;
|
||||
|
||||
nm_ip4_config_add_route (config, &route);
|
||||
}
|
||||
}
|
||||
|
|
@ -762,37 +776,54 @@ add_ip4_vpn_gateway_route (NMIP4Config *config, NMDevice *parent_device, guint32
|
|||
static void
|
||||
add_ip6_vpn_gateway_route (NMIP6Config *config,
|
||||
NMDevice *parent_device,
|
||||
const struct in6_addr *vpn_gw)
|
||||
const struct in6_addr *vpn_gw,
|
||||
NMPlatform *platform)
|
||||
{
|
||||
NMIP6Config *parent_config;
|
||||
const struct in6_addr *parent_gw;
|
||||
NMPlatformIP6Route route;
|
||||
guint32 route_metric;
|
||||
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
|
||||
|
||||
g_return_if_fail (NM_IS_IP6_CONFIG (config));
|
||||
g_return_if_fail (NM_IS_DEVICE (parent_device));
|
||||
g_return_if_fail (vpn_gw != NULL);
|
||||
nm_assert (nm_ip6_config_get_ifindex (config) > 0);
|
||||
|
||||
parent_config = nm_device_get_ip6_config (parent_device);
|
||||
g_return_if_fail (parent_config != NULL);
|
||||
|
||||
/* we add a direct route to the VPN gateway, but we only do that
|
||||
* on the @parent_device. That is probably not correct in every case... */
|
||||
parent_gw = nm_ip6_config_get_gateway (parent_config);
|
||||
if (!parent_gw)
|
||||
return;
|
||||
|
||||
/* If the VPN gateway is in the same subnet as one of the parent device's
|
||||
* IP addresses, don't add the host route to it, but a route through the
|
||||
* parent device.
|
||||
*/
|
||||
if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128))
|
||||
parent_gw = &in6addr_any;
|
||||
|
||||
/* actually, let's ask kernel how to reach @vpn_gw. If (and only if)
|
||||
* the destination is on @parent_device, then we take that @parent_gw. */
|
||||
if (nm_platform_ip_route_get (platform,
|
||||
AF_INET6,
|
||||
vpn_gw,
|
||||
(NMPObject **) &route_resolved) == NM_PLATFORM_ERROR_SUCCESS) {
|
||||
const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (route_resolved);
|
||||
|
||||
if (r->ifindex == nm_ip6_config_get_ifindex (config))
|
||||
parent_gw = &r->gateway;
|
||||
}
|
||||
|
||||
route_metric = nm_device_get_ip6_route_metric (parent_device);
|
||||
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.network = *vpn_gw;
|
||||
route.plen = 128;
|
||||
route.gateway = *parent_gw;
|
||||
|
||||
/* If the VPN gateway is in the same subnet as one of the parent device's
|
||||
* IP addresses, don't add the host route to it, but a route through the
|
||||
* parent device.
|
||||
*/
|
||||
if (nm_ip6_config_destination_is_direct (parent_config, vpn_gw, 128))
|
||||
route.gateway = in6addr_any;
|
||||
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
route.metric = route_metric;
|
||||
nm_ip6_config_add_route (config, &route);
|
||||
|
|
@ -802,13 +833,14 @@ add_ip6_vpn_gateway_route (NMIP6Config *config,
|
|||
* routes include a subnet that matches the parent device's subnet,
|
||||
* the parent device's gateway would get routed through the VPN and fail.
|
||||
*/
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.network = *parent_gw;
|
||||
route.plen = 128;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
route.metric = route_metric;
|
||||
|
||||
nm_ip6_config_add_route (config, &route);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (parent_gw)) {
|
||||
memset (&route, 0, sizeof (route));
|
||||
route.network = *parent_gw;
|
||||
route.plen = 128;
|
||||
route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
|
||||
route.metric = route_metric;
|
||||
nm_ip6_config_add_route (config, &route);
|
||||
}
|
||||
}
|
||||
|
||||
NMVpnConnection *
|
||||
|
|
@ -1067,24 +1099,36 @@ apply_parent_device_config (NMVpnConnection *self)
|
|||
* vpn-config. Instead we tell NMDefaultRouteManager directly about the
|
||||
* default route. */
|
||||
ifindex = nm_device_get_ip_ifindex (parent_dev);
|
||||
if (priv->ip4_config) {
|
||||
vpn4_parent_config = nm_ip4_config_new (nm_netns_get_multi_idx (priv->netns),
|
||||
ifindex);
|
||||
nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS);
|
||||
}
|
||||
if (priv->ip6_config) {
|
||||
vpn6_parent_config = nm_ip6_config_new (nm_netns_get_multi_idx (priv->netns),
|
||||
ifindex);
|
||||
nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS);
|
||||
nm_ip6_config_set_gateway (vpn6_parent_config, NULL);
|
||||
if (ifindex > 0) {
|
||||
if (priv->ip4_config) {
|
||||
vpn4_parent_config = nm_ip4_config_new (nm_netns_get_multi_idx (priv->netns),
|
||||
ifindex);
|
||||
nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS);
|
||||
}
|
||||
if (priv->ip6_config) {
|
||||
vpn6_parent_config = nm_ip6_config_new (nm_netns_get_multi_idx (priv->netns),
|
||||
ifindex);
|
||||
nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS);
|
||||
nm_ip6_config_set_gateway (vpn6_parent_config, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add any explicit route to the VPN gateway through the parent device */
|
||||
if (vpn4_parent_config && priv->ip4_external_gw)
|
||||
add_ip4_vpn_gateway_route (vpn4_parent_config, parent_dev, priv->ip4_external_gw);
|
||||
if (vpn6_parent_config && priv->ip6_external_gw)
|
||||
add_ip6_vpn_gateway_route (vpn6_parent_config, parent_dev, priv->ip6_external_gw);
|
||||
if ( vpn4_parent_config
|
||||
&& priv->ip4_external_gw) {
|
||||
add_ip4_vpn_gateway_route (vpn4_parent_config,
|
||||
parent_dev,
|
||||
priv->ip4_external_gw,
|
||||
nm_netns_get_platform (priv->netns));
|
||||
}
|
||||
if ( vpn6_parent_config
|
||||
&& priv->ip6_external_gw) {
|
||||
add_ip6_vpn_gateway_route (vpn6_parent_config,
|
||||
parent_dev,
|
||||
priv->ip6_external_gw,
|
||||
nm_netns_get_platform (priv->netns));
|
||||
}
|
||||
|
||||
nm_device_replace_vpn4_config (parent_dev, priv->last_device_ip4_config, vpn4_parent_config);
|
||||
g_clear_object (&priv->last_device_ip4_config);
|
||||
|
|
@ -1104,21 +1148,17 @@ nm_vpn_connection_apply_config (NMVpnConnection *self)
|
|||
nm_platform_link_set_up (nm_netns_get_platform (priv->netns), priv->ip_ifindex, NULL);
|
||||
|
||||
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,
|
||||
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)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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,
|
||||
nm_netns_get_platform (priv->netns),
|
||||
nm_netns_get_route_manager (priv->netns),
|
||||
priv->ip_ifindex,
|
||||
TRUE))
|
||||
nm_netns_get_platform (priv->netns)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue