mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-01 03:18:06 +02:00
route-manager: merge branch 'th/route-manager-bgo740064'
https://bugzilla.gnome.org/show_bug.cgi?id=740064
This commit is contained in:
commit
3c240a6d0b
24 changed files with 1024 additions and 407 deletions
|
|
@ -169,7 +169,7 @@ nmtst_free (void)
|
|||
}
|
||||
|
||||
inline static void
|
||||
__nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_level, const char *log_domains)
|
||||
__nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_level, const char *log_domains, gboolean *out_set_logging)
|
||||
{
|
||||
const char *nmtst_debug;
|
||||
gboolean is_debug = FALSE;
|
||||
|
|
@ -178,6 +178,11 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
GArray *debug_messages = g_array_new (TRUE, FALSE, sizeof (char *));
|
||||
int i;
|
||||
gboolean no_expect_message = FALSE;
|
||||
gboolean _out_set_logging;
|
||||
|
||||
if (!out_set_logging)
|
||||
out_set_logging = &_out_set_logging;
|
||||
*out_set_logging = FALSE;
|
||||
|
||||
g_assert (!nmtst_initialized ());
|
||||
|
||||
|
|
@ -275,6 +280,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
gboolean success = TRUE;
|
||||
#ifdef __NETWORKMANAGER_LOGGING_H__
|
||||
success = nm_logging_setup (log_level, log_domains, NULL, NULL);
|
||||
*out_set_logging = TRUE;
|
||||
#endif
|
||||
g_assert (success);
|
||||
} else if (__nmtst_internal.no_expect_message) {
|
||||
|
|
@ -291,6 +297,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
gboolean success;
|
||||
|
||||
success = nm_logging_setup (log_level, log_domains, NULL, NULL);
|
||||
*out_set_logging = TRUE;
|
||||
g_assert (success);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -306,7 +313,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
}
|
||||
|
||||
if ((!__nmtst_internal.assert_logging || (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message)) &&
|
||||
(is_debug || (log_level && !g_ascii_strcasecmp (log_level, "DEBUG"))) &&
|
||||
(is_debug || (c_log_level && (!g_ascii_strcasecmp (c_log_level, "DEBUG") || !g_ascii_strcasecmp (c_log_level, "TRACE")))) &&
|
||||
!g_getenv ("G_MESSAGES_DEBUG"))
|
||||
{
|
||||
/* if we are @is_debug or @log_level=="DEBUG" and
|
||||
|
|
@ -336,18 +343,27 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_
|
|||
inline static void
|
||||
nmtst_init_with_logging (int *argc, char ***argv, const char *log_level, const char *log_domains)
|
||||
{
|
||||
__nmtst_init (argc, argv, FALSE, log_level, log_domains);
|
||||
__nmtst_init (argc, argv, FALSE, log_level, log_domains, NULL);
|
||||
}
|
||||
inline static void
|
||||
nmtst_init_assert_logging (int *argc, char ***argv)
|
||||
nmtst_init_assert_logging (int *argc, char ***argv, const char *log_level, const char *log_domains)
|
||||
{
|
||||
__nmtst_init (argc, argv, TRUE, NULL, NULL);
|
||||
gboolean set_logging;
|
||||
|
||||
__nmtst_init (argc, argv, TRUE, NULL, NULL, &set_logging);
|
||||
|
||||
if (!set_logging) {
|
||||
gboolean success;
|
||||
|
||||
success = nm_logging_setup (log_level, log_domains, NULL, NULL);
|
||||
g_assert (success);
|
||||
}
|
||||
}
|
||||
#else
|
||||
inline static void
|
||||
nmtst_init (int *argc, char ***argv, gboolean assert_logging)
|
||||
{
|
||||
__nmtst_init (argc, argv, assert_logging, NULL, NULL);
|
||||
__nmtst_init (argc, argv, assert_logging, NULL, NULL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -394,7 +410,7 @@ nmtst_get_rand (void)
|
|||
gint64 i;
|
||||
|
||||
i = g_ascii_strtoll (str, &s, 0);
|
||||
g_assert (s[0] == '\0' && i >= 0 && i < G_MAXINT32);
|
||||
g_assert (s[0] == '\0' && i >= 0 && i < G_MAXUINT32);
|
||||
|
||||
seed = i;
|
||||
__nmtst_internal.rand = g_rand_new_with_seed (seed);
|
||||
|
|
@ -406,7 +422,7 @@ nmtst_get_rand (void)
|
|||
}
|
||||
__nmtst_internal.rand_seed = seed;
|
||||
|
||||
__NMTST_LOG (g_message, ">> initialize nmtst_get_rand() with seed=%u", seed);
|
||||
__NMTST_LOG (g_message, ">> initialize nmtst_get_rand() with NMTST_SEED_RAND=%u", seed);
|
||||
}
|
||||
return __nmtst_internal.rand;
|
||||
}
|
||||
|
|
@ -670,14 +686,28 @@ nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gate
|
|||
return route;
|
||||
}
|
||||
|
||||
inline static int
|
||||
_nmtst_platform_ip4_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip4_route_cmp ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len)
|
||||
nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len, gboolean ignore_order)
|
||||
{
|
||||
gsize i;
|
||||
gs_free const NMPlatformIP4Route *c_a = NULL, *c_b = NULL;
|
||||
|
||||
g_assert (a);
|
||||
g_assert (b);
|
||||
|
||||
if (ignore_order) {
|
||||
a = c_a = g_memdup (a, sizeof (NMPlatformIP4Route) * len);
|
||||
b = c_b = g_memdup (b, sizeof (NMPlatformIP4Route) * len);
|
||||
g_qsort_with_data (c_a, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
|
||||
g_qsort_with_data (c_b, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) {
|
||||
g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (long unsigned) i,
|
||||
|
|
@ -691,14 +721,28 @@ nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP
|
|||
}
|
||||
}
|
||||
|
||||
inline static int
|
||||
_nmtst_platform_ip6_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
|
||||
{
|
||||
return nm_platform_ip6_route_cmp ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b);
|
||||
}
|
||||
|
||||
inline static void
|
||||
nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len)
|
||||
nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len, gboolean ignore_order)
|
||||
{
|
||||
gsize i;
|
||||
gs_free const NMPlatformIP6Route *c_a = NULL, *c_b = NULL;
|
||||
|
||||
g_assert (a);
|
||||
g_assert (b);
|
||||
|
||||
if (ignore_order) {
|
||||
a = c_a = g_memdup (a, sizeof (NMPlatformIP6Route) * len);
|
||||
b = c_b = g_memdup (b, sizeof (NMPlatformIP6Route) * len);
|
||||
g_qsort_with_data (c_a, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
|
||||
g_qsort_with_data (c_b, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) {
|
||||
g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (long unsigned) i,
|
||||
|
|
|
|||
|
|
@ -150,6 +150,80 @@ nm_utils_ip6_address_clear_host_address (struct in6_addr *dst, const struct in6_
|
|||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len)
|
||||
{
|
||||
gsize elt_size;
|
||||
guint index_to_delete;
|
||||
guint i_src;
|
||||
guint mm_src, mm_dst, mm_len;
|
||||
gsize i_itd;
|
||||
guint res_length;
|
||||
|
||||
g_return_if_fail (array);
|
||||
if (!len)
|
||||
return;
|
||||
g_return_if_fail (indexes_to_delete);
|
||||
|
||||
elt_size = g_array_get_element_size (array);
|
||||
|
||||
i_itd = 0;
|
||||
index_to_delete = indexes_to_delete[0];
|
||||
if (index_to_delete >= array->len)
|
||||
g_return_if_reached ();
|
||||
|
||||
res_length = array->len - 1;
|
||||
|
||||
mm_dst = index_to_delete;
|
||||
mm_src = index_to_delete;
|
||||
mm_len = 0;
|
||||
|
||||
for (i_src = index_to_delete; i_src < array->len; i_src++) {
|
||||
if (i_src < index_to_delete)
|
||||
mm_len++;
|
||||
else {
|
||||
/* we require indexes_to_delete to contain non-repeated, ascending
|
||||
* indexes. Otherwise we would need to presort the indexes. */
|
||||
while (TRUE) {
|
||||
guint dd;
|
||||
|
||||
if (i_itd + 1 >= len) {
|
||||
index_to_delete = G_MAXUINT;
|
||||
break;
|
||||
}
|
||||
|
||||
dd = indexes_to_delete[++i_itd];
|
||||
if (dd > index_to_delete) {
|
||||
if (dd >= array->len)
|
||||
g_warn_if_reached ();
|
||||
else {
|
||||
g_assert (res_length > 0);
|
||||
res_length--;
|
||||
}
|
||||
index_to_delete = dd;
|
||||
break;
|
||||
}
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
if (mm_len) {
|
||||
memmove (&array->data[mm_dst * elt_size],
|
||||
&array->data[mm_src * elt_size],
|
||||
mm_len * elt_size);
|
||||
mm_dst += mm_len;
|
||||
mm_src += mm_len + 1;
|
||||
mm_len = 0;
|
||||
} else
|
||||
mm_src++;
|
||||
}
|
||||
}
|
||||
if (mm_len) {
|
||||
memmove (&array->data[mm_dst * elt_size],
|
||||
&array->data[mm_src * elt_size],
|
||||
mm_len * elt_size);
|
||||
}
|
||||
g_array_set_size (array, res_length);
|
||||
}
|
||||
|
||||
int
|
||||
nm_spawn_process (const char *args, GError **error)
|
||||
|
|
|
|||
|
|
@ -183,6 +183,8 @@ void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
|
|||
GVariant *nm_utils_connection_hash_to_dict (GHashTable *hash);
|
||||
GHashTable *nm_utils_connection_dict_to_hash (GVariant *dict);
|
||||
|
||||
void nm_utils_array_remove_at_indexes (GArray *array, const guint *indexes_to_delete, gsize len);
|
||||
|
||||
void nm_utils_setpgid (gpointer unused);
|
||||
|
||||
#endif /* __NETWORKMANAGER_UTILS_H__ */
|
||||
|
|
|
|||
|
|
@ -694,8 +694,7 @@ NMTST_DEFINE ();
|
|||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nm_logging_setup ("WARN", "DEFAULT", NULL, NULL);
|
||||
nmtst_init_assert_logging (&argc, &argv, "WARN", "DEFAULT");
|
||||
|
||||
g_test_add_func ("/dhcp/generic-options", test_generic_options);
|
||||
g_test_add_func ("/dhcp/wins-options", test_wins_options);
|
||||
|
|
|
|||
|
|
@ -64,10 +64,11 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get,
|
|||
|
||||
#define _LOG(level, addr_family, ...) \
|
||||
G_STMT_START { \
|
||||
int __addr_family = (addr_family); \
|
||||
guint64 __domain = __addr_family == AF_INET ? LOGD_IP4 : LOGD_IP6; \
|
||||
const int __addr_family = (addr_family); \
|
||||
const NMLogLevel __level = (level); \
|
||||
const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \
|
||||
\
|
||||
if (nm_logging_enabled ((level), (__domain))) { \
|
||||
if (nm_logging_enabled (__level, __domain)) { \
|
||||
char __ch = __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'); \
|
||||
char __prefix[30] = "default-route"; \
|
||||
\
|
||||
|
|
@ -75,7 +76,7 @@ NM_DEFINE_SINGLETON_GETTER (NMDefaultRouteManager, nm_default_route_manager_get,
|
|||
g_snprintf (__prefix, sizeof (__prefix), "default-route%c[%p]", __ch, (self)); \
|
||||
else \
|
||||
__prefix[STRLEN ("default-route")] = __ch; \
|
||||
nm_log ((level), (__domain), \
|
||||
nm_log (__level, __domain, \
|
||||
"%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
__prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
|
|
@ -141,22 +142,16 @@ typedef struct {
|
|||
} Entry;
|
||||
|
||||
typedef struct {
|
||||
int addr_family;
|
||||
const NMPlatformVTableRoute *vt;
|
||||
GPtrArray *(*get_entries) (NMDefaultRouteManagerPrivate *priv);
|
||||
const char *(*platform_route_to_string) (const NMPlatformIPRoute *route);
|
||||
GArray *(*platform_route_get_all) (int ifindex, NMPlatformGetRouteMode mode);
|
||||
gboolean (*platform_route_delete_default) (int ifindex, guint32 metric);
|
||||
guint32 (*route_metric_normalize) (guint32 metric);
|
||||
} VTableIP;
|
||||
|
||||
static const VTableIP vtable_ip4, vtable_ip6;
|
||||
|
||||
#define VTABLE_IS_IP4 (vtable->addr_family == AF_INET)
|
||||
|
||||
static NMPlatformIPRoute *
|
||||
_vt_route_index (const VTableIP *vtable, GArray *routes, guint index)
|
||||
{
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
return (NMPlatformIPRoute *) &g_array_index (routes, NMPlatformIP4Route, index);
|
||||
else
|
||||
return (NMPlatformIPRoute *) &g_array_index (routes, NMPlatformIP6Route, index);
|
||||
|
|
@ -170,7 +165,7 @@ _vt_routes_has_entry (const VTableIP *vtable, GArray *routes, const Entry *entry
|
|||
|
||||
route.rx.metric = entry->effective_metric;
|
||||
|
||||
if (VTABLE_IS_IP4) {
|
||||
if (vtable->vt->is_ip4) {
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
NMPlatformIP4Route *r = &g_array_index (routes, NMPlatformIP4Route, i);
|
||||
|
||||
|
|
@ -260,7 +255,7 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
if (!entry)
|
||||
return FALSE;
|
||||
|
||||
if (VTABLE_IS_IP4) {
|
||||
if (vtable->vt->is_ip4) {
|
||||
success = nm_platform_ip4_route_add (entry->route.rx.ifindex,
|
||||
entry->route.rx.source,
|
||||
0,
|
||||
|
|
@ -279,8 +274,8 @@ _platform_route_sync_add (const VTableIP *vtable, NMDefaultRouteManager *self, g
|
|||
entry->route.rx.mss);
|
||||
}
|
||||
if (!success) {
|
||||
_LOGW (vtable->addr_family, "failed to add default route %s with effective metric %u",
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) entry->effective_metric);
|
||||
_LOGW (vtable->vt->addr_family, "failed to add default route %s with effective metric %u",
|
||||
vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -295,7 +290,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
gboolean changed = FALSE;
|
||||
|
||||
/* prune all other default routes from this device. */
|
||||
routes = vtable->platform_route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
|
||||
routes = vtable->vt->route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
|
||||
|
||||
for (i = 0; i < routes->len; i++) {
|
||||
const NMPlatformIPRoute *route;
|
||||
|
|
@ -327,7 +322,7 @@ _platform_route_sync_flush (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
*/
|
||||
if ( !entry
|
||||
&& (has_ifindex_synced || ifindex_to_flush == route->ifindex)) {
|
||||
vtable->platform_route_delete_default (route->ifindex, route->metric);
|
||||
vtable->vt->route_delete_default (route->ifindex, route->metric);
|
||||
changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -411,7 +406,7 @@ _get_assumed_interface_metrics (const VTableIP *vtable, NMDefaultRouteManager *s
|
|||
}
|
||||
|
||||
if (!ifindex_has_synced_entry)
|
||||
g_hash_table_add (result, GUINT_TO_POINTER (vtable->route_metric_normalize (route->metric)));
|
||||
g_hash_table_add (result, GUINT_TO_POINTER (vtable->vt->metric_normalize (route->metric)));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -447,7 +442,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
|
|||
priv->resync.guard++;
|
||||
|
||||
if (!external_change) {
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
priv->resync.has_v4_changes = FALSE;
|
||||
else
|
||||
priv->resync.has_v6_changes = FALSE;
|
||||
|
|
@ -457,7 +452,7 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
|
|||
|
||||
entries = vtable->get_entries (priv);
|
||||
|
||||
routes = vtable->platform_route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
|
||||
routes = vtable->vt->route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_ONLY_DEFAULT);
|
||||
|
||||
assumed_metrics = _get_assumed_interface_metrics (vtable, self, routes);
|
||||
|
||||
|
|
@ -527,24 +522,24 @@ _resync_all (const VTableIP *vtable, NMDefaultRouteManager *self, const Entry *c
|
|||
* or none. Hence, we only have to remember what is going to change. */
|
||||
g_array_append_val (changed_metrics, expected_metric);
|
||||
if (old_entry) {
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": update %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) old_entry->effective_metric,
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": update %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->vt->route_to_string (&entry->route), (guint) old_entry->effective_metric,
|
||||
(guint) expected_metric);
|
||||
} else {
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": add %s (%u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) expected_metric);
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": add %s (%u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->vt->route_to_string (&entry->route), (guint) expected_metric);
|
||||
}
|
||||
} else if (entry->effective_metric != expected_metric) {
|
||||
g_array_append_val (changed_metrics, entry->effective_metric);
|
||||
g_array_append_val (changed_metrics, expected_metric);
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": resync metric %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) entry->effective_metric,
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": resync metric %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
|
||||
(guint) expected_metric);
|
||||
} else {
|
||||
if (!_vt_routes_has_entry (vtable, routes, entry)) {
|
||||
g_array_append_val (changed_metrics, entry->effective_metric);
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": readd route %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) entry->effective_metric,
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": readd route %s (%u -> %u)", LOG_ENTRY_ARGS (i, entry),
|
||||
vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric,
|
||||
(guint) entry->effective_metric);
|
||||
}
|
||||
}
|
||||
|
|
@ -608,10 +603,10 @@ _entry_at_idx_update (const VTableIP *vtable, NMDefaultRouteManager *self, guint
|
|||
if (!entry->synced && !entry->never_default)
|
||||
entry->effective_metric = entry->route.rx.metric;
|
||||
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": %s %s",
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": %s %s",
|
||||
LOG_ENTRY_ARGS (entry_idx, entry),
|
||||
old_entry ? "update" : "add",
|
||||
vtable->platform_route_to_string (&entry->route.rx));
|
||||
vtable->vt->route_to_string (&entry->route));
|
||||
|
||||
g_ptr_array_sort_with_data (entries, _sort_entries_cmp, NULL);
|
||||
|
||||
|
|
@ -631,8 +626,8 @@ _entry_at_idx_remove (const VTableIP *vtable, NMDefaultRouteManager *self, guint
|
|||
|
||||
entry = g_ptr_array_index (entries, entry_idx);
|
||||
|
||||
_LOGD (vtable->addr_family, LOG_ENTRY_FMT": remove %s (%u)", LOG_ENTRY_ARGS (entry_idx, entry),
|
||||
vtable->platform_route_to_string (&entry->route.rx), (guint) entry->effective_metric);
|
||||
_LOGD (vtable->vt->addr_family, LOG_ENTRY_FMT": remove %s (%u)", LOG_ENTRY_ARGS (entry_idx, entry),
|
||||
vtable->vt->route_to_string (&entry->route), (guint) entry->effective_metric);
|
||||
|
||||
/* Remove the entry from the list (but don't free it yet) */
|
||||
g_ptr_array_index (entries, entry_idx) = NULL;
|
||||
|
|
@ -692,7 +687,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
if ( entry
|
||||
&& entry->route.rx.ifindex != ip_ifindex) {
|
||||
/* Strange... the ifindex changed... Remove the device and start again. */
|
||||
_LOGD (vtable->addr_family, "ifindex of "LOG_ENTRY_FMT" changed: %d -> %d",
|
||||
_LOGD (vtable->vt->addr_family, "ifindex of "LOG_ENTRY_FMT" changed: %d -> %d",
|
||||
LOG_ENTRY_ARGS (entry_idx, entry),
|
||||
entry->route.rx.ifindex, ip_ifindex);
|
||||
|
||||
|
|
@ -709,7 +704,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
if (device) {
|
||||
gboolean is_assumed;
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
default_route = (const NMPlatformIPRoute *) nm_device_get_ip4_default_route (device, &is_assumed);
|
||||
else
|
||||
default_route = (const NMPlatformIPRoute *) nm_device_get_ip6_default_route (device, &is_assumed);
|
||||
|
|
@ -737,7 +732,7 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
&& nm_vpn_connection_get_vpn_state (vpn) == NM_VPN_CONNECTION_STATE_ACTIVATED) {
|
||||
|
||||
memset (&rt, 0, sizeof (rt));
|
||||
if (VTABLE_IS_IP4) {
|
||||
if (vtable->vt->is_ip4) {
|
||||
NMIP4Config *vpn_config;
|
||||
|
||||
vpn_config = nm_vpn_connection_get_ip4_config (vpn);
|
||||
|
|
@ -779,13 +774,13 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
entry = g_slice_new0 (Entry);
|
||||
entry->source.object = g_object_ref (source);
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
entry->route.r4 = *((const NMPlatformIP4Route *) default_route);
|
||||
else
|
||||
entry->route.r6 = *((const NMPlatformIP6Route *) default_route);
|
||||
|
||||
/* only use normalized metrics */
|
||||
entry->route.rx.metric = vtable->route_metric_normalize (entry->route.rx.metric);
|
||||
entry->route.rx.metric = vtable->vt->metric_normalize (entry->route.rx.metric);
|
||||
entry->route.rx.ifindex = ip_ifindex;
|
||||
entry->never_default = never_default;
|
||||
entry->effective_metric = entry->route.rx.metric;
|
||||
|
|
@ -798,12 +793,12 @@ _ipx_update_default_route (const VTableIP *vtable, NMDefaultRouteManager *self,
|
|||
Entry old_entry, new_entry;
|
||||
|
||||
new_entry = *entry;
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
new_entry.route.r4 = *((const NMPlatformIP4Route *) default_route);
|
||||
else
|
||||
new_entry.route.r6 = *((const NMPlatformIP6Route *) default_route);
|
||||
/* only use normalized metrics */
|
||||
new_entry.route.rx.metric = vtable->route_metric_normalize (new_entry.route.rx.metric);
|
||||
new_entry.route.rx.metric = vtable->vt->metric_normalize (new_entry.route.rx.metric);
|
||||
new_entry.route.rx.ifindex = ip_ifindex;
|
||||
new_entry.never_default = never_default;
|
||||
new_entry.synced = synced;
|
||||
|
|
@ -843,14 +838,14 @@ _ipx_connection_has_default_route (const VTableIP *vtable, NMDefaultRouteManager
|
|||
g_return_val_if_fail (NM_IS_DEFAULT_ROUTE_MANAGER (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
s_ip = nm_connection_get_setting_ip4_config (connection);
|
||||
else
|
||||
s_ip = nm_connection_get_setting_ip6_config (connection);
|
||||
if (!s_ip || nm_setting_ip_config_get_never_default (s_ip))
|
||||
return FALSE;
|
||||
|
||||
if (VTABLE_IS_IP4) {
|
||||
if (vtable->vt->is_ip4) {
|
||||
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
if ( !method
|
||||
|| !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)
|
||||
|
|
@ -980,7 +975,7 @@ _ipx_get_best_activating_device (const VTableIP *vtable, NMDefaultRouteManager *
|
|||
|
||||
prio = nm_device_get_ip4_route_metric (device);
|
||||
}
|
||||
prio = vtable->route_metric_normalize (prio);
|
||||
prio = vtable->vt->metric_normalize (prio);
|
||||
|
||||
if ( !best_device
|
||||
|| prio < best_prio
|
||||
|
|
@ -1062,7 +1057,7 @@ _ipx_get_best_config (const VTableIP *vtable,
|
|||
if (entry->never_default && !ignore_never_default)
|
||||
continue;
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
config_result = nm_vpn_connection_get_ip4_config (vpn);
|
||||
else
|
||||
config_result = nm_vpn_connection_get_ip6_config (vpn);
|
||||
|
|
@ -1095,7 +1090,7 @@ _ipx_get_best_config (const VTableIP *vtable,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
config_result = nm_device_get_ip4_config (device);
|
||||
else
|
||||
config_result = nm_device_get_ip6_config (device);
|
||||
|
|
@ -1164,40 +1159,14 @@ _v6_get_entries (NMDefaultRouteManagerPrivate *priv)
|
|||
return priv->entries_ip6;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_v4_platform_route_delete_default (int ifindex, guint32 metric)
|
||||
{
|
||||
return nm_platform_ip4_route_delete (ifindex, 0, 0, metric);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_v6_platform_route_delete_default (int ifindex, guint32 metric)
|
||||
{
|
||||
return nm_platform_ip6_route_delete (ifindex, in6addr_any, 0, metric);
|
||||
}
|
||||
|
||||
static guint32
|
||||
_v4_route_metric_normalize (guint32 metric)
|
||||
{
|
||||
return metric;
|
||||
}
|
||||
|
||||
static const VTableIP vtable_ip4 = {
|
||||
.addr_family = AF_INET,
|
||||
.vt = &nm_platform_vtable_route_v4,
|
||||
.get_entries = _v4_get_entries,
|
||||
.platform_route_to_string = (const char *(*)(const NMPlatformIPRoute *)) nm_platform_ip4_route_to_string,
|
||||
.platform_route_get_all = nm_platform_ip4_route_get_all,
|
||||
.platform_route_delete_default = _v4_platform_route_delete_default,
|
||||
.route_metric_normalize = _v4_route_metric_normalize,
|
||||
};
|
||||
|
||||
static const VTableIP vtable_ip6 = {
|
||||
.addr_family = AF_INET6,
|
||||
.vt = &nm_platform_vtable_route_v6,
|
||||
.get_entries = _v6_get_entries,
|
||||
.platform_route_to_string = (const char *(*)(const NMPlatformIPRoute *)) nm_platform_ip6_route_to_string,
|
||||
.platform_route_get_all = nm_platform_ip6_route_get_all,
|
||||
.platform_route_delete_default = _v6_platform_route_delete_default,
|
||||
.route_metric_normalize = nm_utils_ip6_route_metric_normalize,
|
||||
};
|
||||
|
||||
/***********************************************************************************/
|
||||
|
|
@ -1296,7 +1265,7 @@ _platform_ipx_route_changed_cb (const VTableIP *vtable,
|
|||
return;
|
||||
}
|
||||
|
||||
if (VTABLE_IS_IP4)
|
||||
if (vtable->vt->is_ip4)
|
||||
priv->resync.has_v4_changes = TRUE;
|
||||
else
|
||||
priv->resync.has_v6_changes = TRUE;
|
||||
|
|
|
|||
|
|
@ -25,72 +25,562 @@
|
|||
#include "nm-route-manager.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
#include "gsystem-local-alloc.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
//#define DEBUG_ROUTE_MANAGER
|
||||
|
||||
typedef struct {
|
||||
GArray *ip4_routes;
|
||||
GArray *ip6_routes;
|
||||
guint len;
|
||||
NMPlatformIPXRoute *entries[1];
|
||||
} RouteIndex;
|
||||
|
||||
typedef struct {
|
||||
GArray *entries;
|
||||
RouteIndex *index;
|
||||
} RouteEntries;
|
||||
|
||||
typedef struct {
|
||||
RouteEntries ip4_routes;
|
||||
RouteEntries ip6_routes;
|
||||
} NMRouteManagerPrivate;
|
||||
|
||||
#define NM_ROUTE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ROUTE_MANAGER, NMRouteManagerPrivate))
|
||||
|
||||
G_DEFINE_TYPE (NMRouteManager, nm_route_manager, G_TYPE_OBJECT)
|
||||
G_DEFINE_TYPE (NMRouteManager, nm_route_manager, G_TYPE_OBJECT);
|
||||
|
||||
static const NMPlatformIP4Route *
|
||||
array_get_ip4_route (const GArray *routes, int ifindex, const NMPlatformIP4Route *route)
|
||||
NM_DEFINE_SINGLETON_GETTER (NMRouteManager, nm_route_manager_get, NM_TYPE_ROUTE_MANAGER);
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const NMPlatformVTableRoute *vt;
|
||||
|
||||
/* a compare function for two routes that considers only the fields network/plen,metric. */
|
||||
int (*route_id_cmp) (const NMPlatformIPXRoute *r1, const NMPlatformIPXRoute *r2);
|
||||
} VTableIP;
|
||||
|
||||
static const VTableIP vtable_v4, vtable_v6;
|
||||
|
||||
#define VTABLE_ROUTE_INDEX(vtable, garray, idx) ((NMPlatformIPXRoute *) &((garray)->data[(idx) * (vtable)->vt->sizeof_route]))
|
||||
|
||||
#define VTABLE_IS_DEVICE_ROUTE(vtable, route) ((vtable)->vt->is_ip4 \
|
||||
? ((route)->r4.gateway == 0) \
|
||||
: IN6_IS_ADDR_UNSPECIFIED (&(route)->r6.gateway) )
|
||||
|
||||
#define CMP_AND_RETURN_INT(a, b) \
|
||||
G_STMT_START { \
|
||||
typeof(a) _a = (a), _b = (b); \
|
||||
\
|
||||
if (_a < _b) \
|
||||
return -1; \
|
||||
if (_a > _b) \
|
||||
return 1; \
|
||||
} G_STMT_END
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
#define _LOG_PREFIX_NAME "route-mgr"
|
||||
|
||||
#define _LOG(level, addr_family, ...) \
|
||||
G_STMT_START { \
|
||||
const int __addr_family = (addr_family); \
|
||||
const NMLogLevel __level = (level); \
|
||||
const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \
|
||||
\
|
||||
if (nm_logging_enabled (__level, __domain)) { \
|
||||
char __ch = __addr_family == AF_INET ? '4' : (__addr_family == AF_INET6 ? '6' : '-'); \
|
||||
char __prefix[30] = _LOG_PREFIX_NAME; \
|
||||
\
|
||||
if ((self) != singleton_instance) \
|
||||
g_snprintf (__prefix, sizeof (__prefix), "%s%c[%p]", _LOG_PREFIX_NAME, __ch, (self)); \
|
||||
else \
|
||||
__prefix[STRLEN (_LOG_PREFIX_NAME)] = __ch; \
|
||||
nm_log ((level), (__domain), \
|
||||
"%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
||||
__prefix _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
#define _LOG_LEVEL_ENABLED(level, addr_family) \
|
||||
({ \
|
||||
const int __addr_family = (addr_family); \
|
||||
const NMLogLevel __level = (level); \
|
||||
const NMLogDomain __domain = __addr_family == AF_INET ? LOGD_IP4 : (__addr_family == AF_INET6 ? LOGD_IP6 : LOGD_IP); \
|
||||
\
|
||||
nm_logging_enabled (__level, __domain); \
|
||||
})
|
||||
|
||||
#ifdef DEBUG_ROUTE_MANAGER
|
||||
#define _LOGT_ENABLED(addr_family) _LOG_LEVEL_ENABLED (LOGL_TRACE, addr_family)
|
||||
#define _LOGT(addr_family, ...) _LOG (LOGL_TRACE, addr_family, __VA_ARGS__)
|
||||
#else
|
||||
#define _LOGT_ENABLED(addr_family) FALSE
|
||||
#define _LOGT(addr_family, ...) G_STMT_START { (void) 0; } G_STMT_END
|
||||
#endif
|
||||
|
||||
#define _LOGD(addr_family, ...) _LOG (LOGL_DEBUG, addr_family, __VA_ARGS__)
|
||||
#define _LOGI(addr_family, ...) _LOG (LOGL_INFO , addr_family, __VA_ARGS__)
|
||||
#define _LOGW(addr_family, ...) _LOG (LOGL_WARN , addr_family, __VA_ARGS__)
|
||||
#define _LOGE(addr_family, ...) _LOG (LOGL_ERR , addr_family, __VA_ARGS__)
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
#if defined (DEBUG_ROUTE_MANAGER) && !defined (G_DISABLE_ASSERT)
|
||||
inline static void
|
||||
ASSERT_route_index_valid (const VTableIP *vtable, const GArray *entries, const RouteIndex *index, gboolean unique_ifindexes)
|
||||
{
|
||||
guint i, j;
|
||||
int c;
|
||||
const NMPlatformIPXRoute *r1, *r2;
|
||||
gs_unref_hashtable GHashTable *ptrs = g_hash_table_new (NULL, NULL);
|
||||
const NMPlatformIPXRoute *r_first = NULL, *r_last = NULL;
|
||||
|
||||
g_assert (index);
|
||||
|
||||
if (entries)
|
||||
g_assert_cmpint (entries->len, ==, index->len);
|
||||
else
|
||||
g_assert (index->len == 0);
|
||||
|
||||
if (index->len > 0) {
|
||||
r_first = VTABLE_ROUTE_INDEX (vtable, entries, 0);
|
||||
r_last = VTABLE_ROUTE_INDEX (vtable, entries, index->len - 1);
|
||||
}
|
||||
|
||||
/* assert that the @index is valid for the @entries. */
|
||||
|
||||
g_assert (!index->entries[index->len]);
|
||||
for (i = 0; i < index->len; i++) {
|
||||
r1 = index->entries[i];
|
||||
|
||||
g_assert (r1);
|
||||
g_assert (r1 >= r_first);
|
||||
g_assert (r1 <= r_last);
|
||||
g_assert_cmpint ((((char *) r1) - ((char *) entries->data)) % vtable->vt->sizeof_route, ==, 0);
|
||||
|
||||
g_assert (!g_hash_table_contains (ptrs, (gpointer) r1));
|
||||
g_hash_table_add (ptrs, (gpointer) r1);
|
||||
|
||||
for (j = i; j > 0; ) {
|
||||
r2 = index->entries[--j];
|
||||
|
||||
c = vtable->route_id_cmp (r1, r2);
|
||||
g_assert (c >= 0);
|
||||
if (c != 0)
|
||||
break;
|
||||
if (unique_ifindexes)
|
||||
g_assert_cmpint (r1->rx.ifindex, !=, r2->rx.ifindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define ASSERT_route_index_valid(vtable, entries, index, unique_ifindexes) G_STMT_START { (void) 0; } G_STMT_END
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
static int
|
||||
_v4_route_id_cmp (const NMPlatformIP4Route *r1, const NMPlatformIP4Route *r2)
|
||||
{
|
||||
CMP_AND_RETURN_INT (r1->plen, r2->plen);
|
||||
CMP_AND_RETURN_INT (r1->metric, r2->metric);
|
||||
CMP_AND_RETURN_INT (nm_utils_ip4_address_clear_host_address (r1->network, r1->plen),
|
||||
nm_utils_ip4_address_clear_host_address (r2->network, r2->plen));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_v6_route_id_cmp (const NMPlatformIP6Route *r1, const NMPlatformIP6Route *r2)
|
||||
{
|
||||
struct in6_addr n1, n2;
|
||||
|
||||
CMP_AND_RETURN_INT (r1->plen, r2->plen);
|
||||
CMP_AND_RETURN_INT (nm_utils_ip6_route_metric_normalize (r1->metric),
|
||||
nm_utils_ip6_route_metric_normalize (r2->metric));
|
||||
|
||||
nm_utils_ip6_address_clear_host_address (&n1, &r1->network, r1->plen);
|
||||
nm_utils_ip6_address_clear_host_address (&n2, &r2->network, r2->plen);
|
||||
return memcmp (&n1, &n2, sizeof (n1));
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
static int
|
||||
_route_index_create_sort (const NMPlatformIPXRoute **p1, const NMPlatformIPXRoute ** p2, const VTableIP *vtable)
|
||||
{
|
||||
return vtable->route_id_cmp (*p1, *p2);
|
||||
}
|
||||
|
||||
static RouteIndex *
|
||||
_route_index_create (const VTableIP *vtable, const GArray *routes)
|
||||
{
|
||||
RouteIndex *index;
|
||||
guint i;
|
||||
guint len = routes ? routes->len : 0;
|
||||
|
||||
index = g_malloc (sizeof (RouteIndex) + len * sizeof (NMPlatformIPXRoute *));
|
||||
|
||||
index->len = len;
|
||||
for (i = 0; i < len; i++)
|
||||
index->entries[i] = VTABLE_ROUTE_INDEX (vtable, routes, i);
|
||||
index->entries[i] = NULL;
|
||||
|
||||
/* this is a stable sort, which is very important at this point. */
|
||||
g_qsort_with_data (index->entries,
|
||||
len,
|
||||
sizeof (NMPlatformIPXRoute *),
|
||||
(GCompareDataFunc) _route_index_create_sort,
|
||||
(gpointer) vtable);
|
||||
return index;
|
||||
}
|
||||
|
||||
static guint
|
||||
_route_index_reverse_idx (const VTableIP *vtable, const RouteIndex *index, guint idx_idx, const GArray *routes)
|
||||
{
|
||||
const NMPlatformIPXRoute *r, *r0;
|
||||
gssize offset;
|
||||
|
||||
/* reverse the @idx_idx that points into @index, to the corresponding index into the unsorted @routes array. */
|
||||
|
||||
r = index->entries[idx_idx];
|
||||
r0 = VTABLE_ROUTE_INDEX (vtable, routes, 0);
|
||||
|
||||
if (vtable->vt->is_ip4)
|
||||
offset = &r->r4 - &r0->r4;
|
||||
else
|
||||
offset = &r->r6 - &r0->r6;
|
||||
g_assert (offset >= 0 && offset < index->len);
|
||||
g_assert (VTABLE_ROUTE_INDEX (vtable, routes, offset) == r);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_route_equals_ignoring_ifindex (const VTableIP *vtable, const NMPlatformIPXRoute *r1, const NMPlatformIPXRoute *r2)
|
||||
{
|
||||
NMPlatformIPXRoute r2_backup;
|
||||
|
||||
if (r1->rx.ifindex != r2->rx.ifindex) {
|
||||
memcpy (&r2_backup, r2, vtable->vt->sizeof_route);
|
||||
r2_backup.rx.ifindex = r1->rx.ifindex;
|
||||
r2 = &r2_backup;
|
||||
}
|
||||
return vtable->vt->route_cmp (r1, r2) == 0;
|
||||
}
|
||||
|
||||
static NMPlatformIPXRoute *
|
||||
_get_next_ipx_route (const RouteIndex *index, gboolean start_at_zero, guint *cur_idx, int ifindex)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
NMPlatformIP4Route *c = &g_array_index (routes, NMPlatformIP4Route, i);
|
||||
if (start_at_zero)
|
||||
i = 0;
|
||||
else
|
||||
i = *cur_idx + 1;
|
||||
/* Find the next route with matching @ifindex. */
|
||||
for (; i < index->len; i++) {
|
||||
if (index->entries[i]->rx.ifindex == ifindex) {
|
||||
*cur_idx = i;
|
||||
return index->entries[i];
|
||||
}
|
||||
}
|
||||
*cur_idx = index->len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ifindex) {
|
||||
/* Looking for a specific route. */
|
||||
if ( c->ifindex != ifindex
|
||||
|| route->mss != c->mss
|
||||
|| route->gateway != c->gateway)
|
||||
static const NMPlatformIPXRoute *
|
||||
_get_next_known_route (const VTableIP *vtable, const RouteIndex *index, gboolean start_at_zero, guint *cur_idx)
|
||||
{
|
||||
guint i = 0;
|
||||
const NMPlatformIPXRoute *cur = NULL;
|
||||
|
||||
if (!start_at_zero) {
|
||||
i = *cur_idx;
|
||||
cur = index->entries[i];
|
||||
i++;
|
||||
}
|
||||
/* For @known_routes we expect that all routes have the same @ifindex. This is not enforced however,
|
||||
* the ifindex value of these routes is ignored. */
|
||||
for (; i < index->len; i++) {
|
||||
const NMPlatformIPXRoute *r = index->entries[i];
|
||||
|
||||
/* skip over default routes. */
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (route->network == c->network &&
|
||||
route->plen == c->plen &&
|
||||
route->metric == c->metric)
|
||||
return c;
|
||||
/* @known_routes should not, but could contain duplicate routes. Skip over them. */
|
||||
if (cur && vtable->route_id_cmp (cur, r) == 0)
|
||||
continue;
|
||||
|
||||
*cur_idx = i;
|
||||
return r;
|
||||
}
|
||||
|
||||
*cur_idx = index->len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const NMPlatformIP6Route *
|
||||
array_get_ip6_route (const GArray *routes, int ifindex, const NMPlatformIP6Route *route)
|
||||
static const NMPlatformIPXRoute *
|
||||
_get_next_plat_route (const RouteIndex *index, gboolean start_at_zero, guint *cur_idx)
|
||||
{
|
||||
guint len = routes ? routes->len : 0;
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
NMPlatformIP6Route *c = &g_array_index (routes, NMPlatformIP6Route, i);
|
||||
int route_metric = nm_utils_ip6_route_metric_normalize (route->metric);
|
||||
int c_metric = nm_utils_ip6_route_metric_normalize (c->metric);
|
||||
|
||||
if (ifindex) {
|
||||
/* Looking for a specific route. */
|
||||
if ( c->ifindex != ifindex
|
||||
|| route->mss != c->mss
|
||||
|| !IN6_ARE_ADDR_EQUAL (&route->gateway, &c->gateway))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL (&route->network, &c->network) &&
|
||||
route->plen == c->plen &&
|
||||
route_metric == c_metric)
|
||||
return c;
|
||||
}
|
||||
if (start_at_zero)
|
||||
*cur_idx = 0;
|
||||
else
|
||||
++*cur_idx;
|
||||
|
||||
/* get next route from the platform index. */
|
||||
if (*cur_idx < index->len)
|
||||
return index->entries[*cur_idx];
|
||||
*cur_idx = index->len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
_sort_indexes_cmp (guint *a, guint *b)
|
||||
{
|
||||
CMP_AND_RETURN_INT (*a, *b);
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
static gboolean
|
||||
_vx_route_sync (const VTableIP *vtable, NMRouteManager *self, int ifindex, const GArray *known_routes)
|
||||
{
|
||||
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
|
||||
GArray *plat_routes;
|
||||
RouteEntries *ipx_routes;
|
||||
RouteIndex *plat_routes_idx, *known_routes_idx;
|
||||
gboolean success = TRUE;
|
||||
guint i, i_type;
|
||||
GArray *to_delete_indexes = NULL, *to_restore_routes = NULL;
|
||||
GPtrArray *to_add_routes = NULL;
|
||||
guint i_known_routes, i_plat_routes, i_ipx_routes;
|
||||
const NMPlatformIPXRoute *cur_known_route, *cur_plat_route;
|
||||
NMPlatformIPXRoute *cur_ipx_route;
|
||||
|
||||
ipx_routes = vtable->vt->is_ip4 ? &priv->ip4_routes : &priv->ip6_routes;
|
||||
plat_routes = vtable->vt->route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
|
||||
plat_routes_idx = _route_index_create (vtable, plat_routes);
|
||||
known_routes_idx = _route_index_create (vtable, known_routes);
|
||||
|
||||
ASSERT_route_index_valid (vtable, plat_routes, plat_routes_idx, TRUE);
|
||||
ASSERT_route_index_valid (vtable, known_routes, known_routes_idx, FALSE);
|
||||
|
||||
_LOGD (vtable->vt->addr_family, "%3d: sync %u IPv%c routes", ifindex, known_routes_idx->len, vtable->vt->is_ip4 ? '4' : '6');
|
||||
if (_LOGT_ENABLED (vtable->vt->addr_family)) {
|
||||
for (i = 0; i < known_routes_idx->len; i++) {
|
||||
_LOGT (vtable->vt->addr_family, "%3d: sync new addr #%u: %s",
|
||||
ifindex, i, vtable->vt->route_to_string (VTABLE_ROUTE_INDEX (vtable, known_routes, i)));
|
||||
}
|
||||
for (i = 0; i < ipx_routes->index->len; i++)
|
||||
_LOGT (vtable->vt->addr_family, "%3d: STATE: has #%u - %s", ifindex, i, vtable->vt->route_to_string (ipx_routes->index->entries[i]));
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Check which routes are in @known_routes, and update @ipx_routes.
|
||||
*
|
||||
* This first part only updates @ipx_routes to find out what routes must
|
||||
* be added/deleted.
|
||||
**************************************************************************/
|
||||
|
||||
/* iterate over @ipx_routes and @known_routes */
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex);
|
||||
cur_known_route = _get_next_known_route (vtable, known_routes_idx, TRUE, &i_known_routes);
|
||||
while (cur_ipx_route || cur_known_route) {
|
||||
int route_id_cmp_result = -1;
|
||||
|
||||
while ( cur_ipx_route
|
||||
&& ( !cur_known_route
|
||||
|| ((route_id_cmp_result = vtable->route_id_cmp (cur_ipx_route, cur_known_route)) < 0))) {
|
||||
/* we have @cur_ipx_route, which is less then @cur_known_route. Hence,
|
||||
* the route does no longer exist in @known_routes */
|
||||
if (!to_delete_indexes)
|
||||
to_delete_indexes = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
g_array_append_val (to_delete_indexes, i_ipx_routes);
|
||||
|
||||
/* later we will delete @cur_ipx_route. See if @cur_ipx_route was shadowing another route, that
|
||||
* we must restore. */
|
||||
if (i_ipx_routes + 1 < ipx_routes->index->len) {
|
||||
const NMPlatformIPXRoute *next_route = ipx_routes->index->entries[i_ipx_routes + 1];
|
||||
|
||||
if (vtable->route_id_cmp (cur_ipx_route, next_route) == 0) {
|
||||
if (!to_restore_routes)
|
||||
to_restore_routes = g_array_new (FALSE, FALSE, vtable->vt->sizeof_route);
|
||||
g_array_append_vals (to_restore_routes, next_route, 1);
|
||||
g_assert (next_route->rx.ifindex != ifindex);
|
||||
}
|
||||
}
|
||||
|
||||
/* find the next @cur_ipx_route with matching ifindex. */
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex);
|
||||
}
|
||||
if ( cur_ipx_route
|
||||
&& cur_known_route
|
||||
&& route_id_cmp_result == 0) {
|
||||
if (!_route_equals_ignoring_ifindex (vtable, cur_ipx_route, cur_known_route)) {
|
||||
/* The routes match. Update the entry in place. As this is an exact match of primary
|
||||
* fields, this only updates possibly modified fields such as @gateway or @mss.
|
||||
* Modifiying @cur_ipx_route this way does not invalidate @ipx_routes->index. */
|
||||
memcpy (cur_ipx_route, cur_known_route, vtable->vt->sizeof_route);
|
||||
cur_ipx_route->rx.ifindex = ifindex;
|
||||
cur_ipx_route->rx.metric = vtable->vt->metric_normalize (cur_ipx_route->rx.metric);
|
||||
_LOGT (vtable->vt->addr_family, "%3d: STATE: update #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_ipx_route));
|
||||
}
|
||||
} else if (cur_known_route) {
|
||||
g_assert (!cur_ipx_route || route_id_cmp_result > 0);
|
||||
/* @cur_known_route is new. We cannot immediately add @cur_known_route to @ipx_routes, because
|
||||
* it would invalidate @ipx_routes->index. Instead remember to add it later. */
|
||||
if (!to_add_routes)
|
||||
to_add_routes = g_ptr_array_new ();
|
||||
g_ptr_array_add (to_add_routes, (gpointer) cur_known_route);
|
||||
}
|
||||
|
||||
if (cur_ipx_route && (!cur_known_route || route_id_cmp_result == 0))
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex);
|
||||
if (cur_known_route)
|
||||
cur_known_route = _get_next_known_route (vtable, known_routes_idx, FALSE, &i_known_routes);
|
||||
}
|
||||
|
||||
/* Update @ipx_routes with the just learned changes. */
|
||||
if (to_delete_indexes || to_add_routes) {
|
||||
if (to_delete_indexes) {
|
||||
for (i = 0; i < to_delete_indexes->len; i++) {
|
||||
guint idx = g_array_index (to_delete_indexes, guint, i);
|
||||
|
||||
_LOGT (vtable->vt->addr_family, "%3d: STATE: delete #%u - %s", ifindex, idx, vtable->vt->route_to_string (ipx_routes->index->entries[idx]));
|
||||
g_array_index (to_delete_indexes, guint, i) = _route_index_reverse_idx (vtable, ipx_routes->index, idx, ipx_routes->entries);
|
||||
}
|
||||
g_array_sort (to_delete_indexes, (GCompareFunc) _sort_indexes_cmp);
|
||||
nm_utils_array_remove_at_indexes (ipx_routes->entries, &g_array_index (to_delete_indexes, guint, 0), to_delete_indexes->len);
|
||||
g_array_unref (to_delete_indexes);
|
||||
}
|
||||
if (to_add_routes) {
|
||||
for (i = 0; i < to_add_routes->len; i++) {
|
||||
NMPlatformIPXRoute *ipx_route;
|
||||
|
||||
g_array_append_vals (ipx_routes->entries, g_ptr_array_index (to_add_routes, i), 1);
|
||||
|
||||
ipx_route = VTABLE_ROUTE_INDEX (vtable, ipx_routes->entries, ipx_routes->entries->len - 1);
|
||||
ipx_route->rx.ifindex = ifindex;
|
||||
ipx_route->rx.metric = vtable->vt->metric_normalize (ipx_route->rx.metric);
|
||||
|
||||
_LOGT (vtable->vt->addr_family, "%3d: STATE: added #%u - %s", ifindex, ipx_routes->entries->len - 1, vtable->vt->route_to_string (ipx_route));
|
||||
}
|
||||
g_ptr_array_unref (to_add_routes);
|
||||
}
|
||||
g_free (ipx_routes->index);
|
||||
ipx_routes->index = _route_index_create (vtable, ipx_routes->entries);
|
||||
ASSERT_route_index_valid (vtable, ipx_routes->entries, ipx_routes->index, TRUE);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Delete routes in platform, that no longer exist in @ipx_routes
|
||||
***************************************************************************/
|
||||
|
||||
/* iterate over @plat_routes and @ipx_routes */
|
||||
cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes);
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex);
|
||||
while (cur_plat_route) {
|
||||
int route_id_cmp_result = 0;
|
||||
|
||||
g_assert (cur_plat_route->rx.ifindex == ifindex);
|
||||
|
||||
_LOGT (vtable->vt->addr_family, "%3d: platform rt #%u - %s", ifindex, i_ipx_routes, vtable->vt->route_to_string (cur_plat_route));
|
||||
|
||||
/* skip over @cur_ipx_route that are ordered before @cur_plat_route */
|
||||
while ( cur_ipx_route
|
||||
&& ((route_id_cmp_result = vtable->route_id_cmp (cur_ipx_route, cur_plat_route)) < 0)) {
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex);
|
||||
}
|
||||
|
||||
/* if @cur_ipx_route is not equal to @plat_route, the route must be deleted. */
|
||||
if (!(cur_ipx_route && route_id_cmp_result == 0))
|
||||
vtable->vt->route_delete (ifindex, cur_plat_route);
|
||||
|
||||
cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Restore shadowed routes. These routes are on an other @ifindex, but were
|
||||
* shadowed before. Unshadow them now.
|
||||
**************************************************************************/
|
||||
|
||||
if (to_restore_routes) {
|
||||
for (i_type = 0; i_type < 2; i_type++) {
|
||||
for (i = 0; i < to_restore_routes->len; i++) {
|
||||
const NMPlatformIPXRoute *rest_route = VTABLE_ROUTE_INDEX (vtable, to_restore_routes, i);
|
||||
|
||||
if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vtable, rest_route))
|
||||
|| (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vtable, rest_route))) {
|
||||
/* Make two runs over the list of @to_restore_routes. On the first, only add
|
||||
* device routes, on the second the others (gateway routes). */
|
||||
continue;
|
||||
}
|
||||
vtable->vt->route_add (0, rest_route, 0);
|
||||
}
|
||||
}
|
||||
g_array_unref (to_restore_routes);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Sync @ipx_routes for @ifindex to platform
|
||||
**************************************************************************/
|
||||
|
||||
for (i_type = 0; i_type < 2; i_type++) {
|
||||
/* iterate (twice) over @ipx_routes and @plat_routes */
|
||||
cur_plat_route = _get_next_plat_route (plat_routes_idx, TRUE, &i_plat_routes);
|
||||
cur_ipx_route = _get_next_ipx_route (ipx_routes->index, TRUE, &i_ipx_routes, ifindex);
|
||||
/* Iterate here over @ipx_routes instead of @known_routes. That is done because
|
||||
* we need to know whether a route is shadowed by another route, and that
|
||||
* requires to look at @ipx_routes. */
|
||||
for (; cur_ipx_route; cur_ipx_route = _get_next_ipx_route (ipx_routes->index, FALSE, &i_ipx_routes, ifindex)) {
|
||||
int route_id_cmp_result = -1;
|
||||
|
||||
if ( (i_type == 0 && !VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route))
|
||||
|| (i_type == 1 && VTABLE_IS_DEVICE_ROUTE (vtable, cur_ipx_route))) {
|
||||
/* Make two runs over the list of @ipx_routes. On the first, only add
|
||||
* device routes, on the second the others (gateway routes). */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( i_ipx_routes > 0
|
||||
&& vtable->route_id_cmp (cur_ipx_route, ipx_routes->index->entries[i_ipx_routes - 1]) == 0) {
|
||||
/* @cur_ipx_route is shadewed by another route. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* skip over @plat_routes that are ordered before our @cur_ipx_route. */
|
||||
while ( cur_plat_route
|
||||
&& (route_id_cmp_result = vtable->route_id_cmp (cur_plat_route, cur_ipx_route)) < 0)
|
||||
cur_plat_route = _get_next_plat_route (plat_routes_idx, FALSE, &i_plat_routes);
|
||||
|
||||
/* only add the route if we don't have an identical route in @plat_routes,
|
||||
* i.e. if @cur_plat_route is different from @cur_ipx_route. */
|
||||
if ( !cur_plat_route
|
||||
|| route_id_cmp_result != 0
|
||||
|| !_route_equals_ignoring_ifindex (vtable, cur_plat_route, cur_ipx_route)) {
|
||||
gboolean s;
|
||||
|
||||
s = vtable->vt->route_add (ifindex, cur_ipx_route, 0);
|
||||
if (!s && cur_ipx_route->rx.source < NM_IP_CONFIG_SOURCE_USER) {
|
||||
_LOGD (vtable->vt->addr_family, "ignore error adding IPv%c route to kernel: %s",
|
||||
vtable->vt->is_ip4 ? '4' : '6',
|
||||
vtable->vt->route_to_string (cur_ipx_route));
|
||||
/* Remember that there was a failure, but for now continue trying to sync the
|
||||
* remaining routes. */
|
||||
success = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_free (known_routes_idx);
|
||||
g_free (plat_routes_idx);
|
||||
g_array_unref (plat_routes);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_route_manager_ip4_route_sync:
|
||||
|
|
@ -108,111 +598,7 @@ array_get_ip6_route (const GArray *routes, int ifindex, const NMPlatformIP6Route
|
|||
gboolean
|
||||
nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes)
|
||||
{
|
||||
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
|
||||
GArray *plat_routes, *routes = priv->ip4_routes;
|
||||
NMPlatformIP4Route route;
|
||||
const NMPlatformIP4Route *known_route;
|
||||
const NMPlatformIP4Route *existing;
|
||||
gboolean success;
|
||||
int i, i_type;
|
||||
|
||||
/* Learn about routes that platform knows but we don't. */
|
||||
plat_routes = nm_platform_ip4_route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
|
||||
for (i = 0; i < plat_routes->len; i++) {
|
||||
existing = &g_array_index (plat_routes, NMPlatformIP4Route, i);
|
||||
if (!array_get_ip4_route (routes, existing->ifindex, existing))
|
||||
g_array_append_val (routes, *existing);
|
||||
}
|
||||
|
||||
/* Delete unknown routes */
|
||||
for (i = 0; i < routes->len;) {
|
||||
route = g_array_index (routes, NMPlatformIP4Route, i);
|
||||
|
||||
if (route.ifindex == ifindex) {
|
||||
/* Our route. Keep it? */
|
||||
if (array_get_ip4_route (known_routes, route.ifindex, &route)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_array_remove_index (routes, i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
existing = array_get_ip4_route (routes, 0, &route);
|
||||
if ( existing
|
||||
&& !array_get_ip4_route (plat_routes, existing->ifindex, existing)) {
|
||||
/* The route that should already exist is not there.
|
||||
* Try to add it. */
|
||||
nm_platform_ip4_route_add (existing->ifindex,
|
||||
existing->source,
|
||||
existing->network,
|
||||
existing->plen,
|
||||
existing->gateway,
|
||||
0,
|
||||
existing->metric,
|
||||
existing->mss);
|
||||
|
||||
/* It's now hopefully in platform. Take a note so that we
|
||||
* don't attempt to add it again. */
|
||||
g_array_append_val (plat_routes, *existing);
|
||||
}
|
||||
|
||||
if (route.ifindex == ifindex) {
|
||||
/* Clean up. */
|
||||
nm_platform_ip4_route_delete (route.ifindex,
|
||||
route.network,
|
||||
route.plen,
|
||||
route.metric);
|
||||
}
|
||||
}
|
||||
|
||||
g_array_unref (plat_routes);
|
||||
|
||||
if (!known_routes)
|
||||
return TRUE;
|
||||
|
||||
/* Add missing routes */
|
||||
for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
|
||||
for (i = 0; i < known_routes->len && success; i++) {
|
||||
known_route = &g_array_index (known_routes, NMPlatformIP4Route, i);
|
||||
|
||||
g_assert (known_route->ifindex);
|
||||
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
|
||||
continue;
|
||||
|
||||
if ( (i_type == 0 && known_route->gateway != 0)
|
||||
|| (i_type == 1 && known_route->gateway == 0)) {
|
||||
/* Make two runs over the list of routes. On the first, only add
|
||||
* device routes, on the second the others (gateway routes). */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore routes that already exist */
|
||||
if (!array_get_ip4_route (routes, 0, known_route)) {
|
||||
success = nm_platform_ip4_route_add (known_route->ifindex,
|
||||
known_route->source,
|
||||
known_route->network,
|
||||
known_route->plen,
|
||||
known_route->gateway,
|
||||
0,
|
||||
known_route->metric,
|
||||
known_route->mss);
|
||||
if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
|
||||
nm_log_dbg (LOGD_CORE, "ignore error adding IPv4 route to kernel: %s",
|
||||
nm_platform_ip4_route_to_string (known_route));
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!array_get_ip4_route (routes, known_route->ifindex, known_route))
|
||||
g_array_append_val (routes, *known_route);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
return _vx_route_sync (&vtable_v4, self, ifindex, known_routes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -231,108 +617,7 @@ nm_route_manager_ip4_route_sync (NMRouteManager *self, int ifindex, const GArray
|
|||
gboolean
|
||||
nm_route_manager_ip6_route_sync (NMRouteManager *self, int ifindex, const GArray *known_routes)
|
||||
{
|
||||
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
|
||||
GArray *plat_routes, *routes = priv->ip6_routes;
|
||||
NMPlatformIP6Route route;
|
||||
const NMPlatformIP6Route *known_route;
|
||||
const NMPlatformIP6Route *existing;
|
||||
gboolean success;
|
||||
int i, i_type;
|
||||
|
||||
/* Learn about routes that platform knows but we don't. */
|
||||
plat_routes = nm_platform_ip6_route_get_all (0, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
|
||||
for (i = 0; i < plat_routes->len; i++) {
|
||||
existing = &g_array_index (plat_routes, NMPlatformIP6Route, i);
|
||||
if (!array_get_ip6_route (routes, existing->ifindex, existing))
|
||||
g_array_append_val (routes, *existing);
|
||||
}
|
||||
|
||||
for (i = 0; i < routes->len;) {
|
||||
route = g_array_index (routes, NMPlatformIP6Route, i);
|
||||
|
||||
if (route.ifindex == ifindex) {
|
||||
/* Our route. Keep it? */
|
||||
if (array_get_ip6_route (known_routes, route.ifindex, &route)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_array_remove_index (routes, i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
||||
existing = array_get_ip6_route (routes, 0, &route);
|
||||
if ( existing
|
||||
&& !array_get_ip6_route (plat_routes, existing->ifindex, existing)) {
|
||||
/* The route that should already exist is not there.
|
||||
* Try to add it. */
|
||||
nm_platform_ip6_route_add (existing->ifindex,
|
||||
existing->source,
|
||||
existing->network,
|
||||
existing->plen,
|
||||
existing->gateway,
|
||||
existing->metric,
|
||||
existing->mss);
|
||||
|
||||
/* It's now hopefully in platform. Take a note so that we
|
||||
* don't attempt to add it again. */
|
||||
g_array_append_val (plat_routes, *existing);
|
||||
}
|
||||
|
||||
if (route.ifindex == ifindex) {
|
||||
/* Clean up. */
|
||||
nm_platform_ip6_route_delete (route.ifindex,
|
||||
route.network,
|
||||
route.plen,
|
||||
route.metric);
|
||||
}
|
||||
}
|
||||
|
||||
g_array_unref (plat_routes);
|
||||
|
||||
if (!known_routes)
|
||||
return TRUE;
|
||||
|
||||
/* Add missing routes */
|
||||
for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
|
||||
for (i = 0; i < known_routes->len && success; i++) {
|
||||
known_route = &g_array_index (known_routes, NMPlatformIP6Route, i);
|
||||
|
||||
g_assert (known_route->ifindex);
|
||||
|
||||
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
|
||||
continue;
|
||||
|
||||
if ( (i_type == 0 && !IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway))
|
||||
|| (i_type == 1 && IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway))) {
|
||||
/* Make two runs over the list of routes. On the first, only add
|
||||
* device routes, on the second the others (gateway routes). */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore routes that already exist */
|
||||
if (!array_get_ip6_route (routes, 0, known_route)) {
|
||||
success = nm_platform_ip6_route_add (known_route->ifindex,
|
||||
known_route->source,
|
||||
known_route->network,
|
||||
known_route->plen,
|
||||
known_route->gateway,
|
||||
known_route->metric,
|
||||
known_route->mss);
|
||||
if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
|
||||
nm_log_dbg (LOGD_CORE, "ignore error adding IPv6 route to kernel: %s",
|
||||
nm_platform_ip6_route_to_string (known_route));
|
||||
success = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!array_get_ip6_route (routes, known_route->ifindex, known_route))
|
||||
g_array_append_val (routes, *known_route);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
return _vx_route_sync (&vtable_v6, self, ifindex, known_routes);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -342,15 +627,29 @@ nm_route_manager_route_flush (NMRouteManager *self, int ifindex)
|
|||
&& nm_route_manager_ip6_route_sync (self, ifindex, NULL);
|
||||
}
|
||||
|
||||
NM_DEFINE_SINGLETON_GETTER (NMRouteManager, nm_route_manager_get, NM_TYPE_ROUTE_MANAGER);
|
||||
/*********************************************************************************************/
|
||||
|
||||
static const VTableIP vtable_v4 = {
|
||||
.vt = &nm_platform_vtable_route_v4,
|
||||
.route_id_cmp = (int (*) (const NMPlatformIPXRoute *, const NMPlatformIPXRoute *)) _v4_route_id_cmp,
|
||||
};
|
||||
|
||||
static const VTableIP vtable_v6 = {
|
||||
.vt = &nm_platform_vtable_route_v6,
|
||||
.route_id_cmp = (int (*) (const NMPlatformIPXRoute *, const NMPlatformIPXRoute *)) _v6_route_id_cmp,
|
||||
};
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
static void
|
||||
nm_route_manager_init (NMRouteManager *self)
|
||||
{
|
||||
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
priv->ip4_routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
||||
priv->ip6_routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
|
||||
priv->ip4_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
||||
priv->ip6_routes.entries = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP6Route));
|
||||
priv->ip4_routes.index = _route_index_create (&vtable_v4, priv->ip4_routes.entries);
|
||||
priv->ip6_routes.index = _route_index_create (&vtable_v6, priv->ip6_routes.entries);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -358,8 +657,10 @@ finalize (GObject *object)
|
|||
{
|
||||
NMRouteManagerPrivate *priv = NM_ROUTE_MANAGER_GET_PRIVATE (object);
|
||||
|
||||
g_array_free (priv->ip4_routes, TRUE);
|
||||
g_array_free (priv->ip6_routes, TRUE);
|
||||
g_array_free (priv->ip4_routes.entries, TRUE);
|
||||
g_array_free (priv->ip6_routes.entries, TRUE);
|
||||
g_free (priv->ip4_routes.index);
|
||||
g_free (priv->ip6_routes.index);
|
||||
|
||||
G_OBJECT_CLASS (nm_route_manager_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1152,7 +1152,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
route.source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
route.ifindex = ifindex;
|
||||
route.source = source;
|
||||
route.network = network;
|
||||
route.network = nm_utils_ip4_address_clear_host_address (network, plen);
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
|
|
@ -1169,8 +1169,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
break;
|
||||
}
|
||||
if (i == priv->ip4_routes->len) {
|
||||
g_warning ("Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip4_route_to_string (&route));
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip4_route_to_string (&route));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1217,7 +1217,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
route.source = NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
route.ifindex = ifindex;
|
||||
route.source = source;
|
||||
route.network = network;
|
||||
nm_utils_ip6_address_clear_host_address (&route.network, &network, plen);
|
||||
route.plen = plen;
|
||||
route.gateway = gateway;
|
||||
route.metric = metric;
|
||||
|
|
@ -1236,8 +1236,8 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
|
|||
break;
|
||||
}
|
||||
if (i == priv->ip6_routes->len) {
|
||||
g_warning ("Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip6_route_to_string (&route));
|
||||
nm_log_warn (LOGD_PLATFORM, "Fake platform: error adding %s: Network Unreachable",
|
||||
nm_platform_ip6_route_to_string (&route));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1737,10 +1737,6 @@ add_object (NMPlatform *platform, struct nl_object *obj)
|
|||
auto_nl_object struct nl_object *object = obj;
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
int nle;
|
||||
struct nl_dump_params dp = {
|
||||
.dp_type = NL_DUMP_DETAILS,
|
||||
.dp_fd = stderr,
|
||||
};
|
||||
|
||||
g_return_val_if_fail (object, FALSE);
|
||||
|
||||
|
|
@ -1756,7 +1752,18 @@ add_object (NMPlatform *platform, struct nl_object *obj)
|
|||
break;
|
||||
default:
|
||||
error ("Netlink error adding %s: %s", to_string_object (platform, object), nl_geterror (nle));
|
||||
nl_object_dump (object, &dp);
|
||||
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
||||
char buf[256];
|
||||
struct nl_dump_params dp = {
|
||||
.dp_type = NL_DUMP_DETAILS,
|
||||
.dp_buf = buf,
|
||||
.dp_buflen = sizeof (buf),
|
||||
};
|
||||
|
||||
nl_object_dump (object, &dp);
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
debug ("netlink object:\n%s", buf);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2637,6 +2637,97 @@ log_ip6_route (NMPlatform *p, int ifindex, NMPlatformIP6Route *route, NMPlatform
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static gboolean
|
||||
_vtr_v4_route_add (int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src)
|
||||
{
|
||||
return nm_platform_ip4_route_add (ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->rx.source,
|
||||
route->r4.network,
|
||||
route->rx.plen,
|
||||
route->r4.gateway,
|
||||
v4_pref_src,
|
||||
route->rx.metric,
|
||||
route->rx.mss);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v6_route_add (int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src)
|
||||
{
|
||||
return nm_platform_ip6_route_add (ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->rx.source,
|
||||
route->r6.network,
|
||||
route->rx.plen,
|
||||
route->r6.gateway,
|
||||
route->rx.metric,
|
||||
route->rx.mss);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v4_route_delete (int ifindex, const NMPlatformIPXRoute *route)
|
||||
{
|
||||
return nm_platform_ip4_route_delete (ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->r4.network,
|
||||
route->rx.plen,
|
||||
route->rx.metric);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v6_route_delete (int ifindex, const NMPlatformIPXRoute *route)
|
||||
{
|
||||
return nm_platform_ip6_route_delete (ifindex > 0 ? ifindex : route->rx.ifindex,
|
||||
route->r6.network,
|
||||
route->rx.plen,
|
||||
route->rx.metric);
|
||||
}
|
||||
|
||||
static guint32
|
||||
_vtr_v4_metric_normalize (guint32 metric)
|
||||
{
|
||||
return metric;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v4_route_delete_default (int ifindex, guint32 metric)
|
||||
{
|
||||
return nm_platform_ip4_route_delete (ifindex, 0, 0, metric);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_vtr_v6_route_delete_default (int ifindex, guint32 metric)
|
||||
{
|
||||
return nm_platform_ip6_route_delete (ifindex, in6addr_any, 0, metric);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
|
||||
.is_ip4 = TRUE,
|
||||
.addr_family = AF_INET,
|
||||
.sizeof_route = sizeof (NMPlatformIP4Route),
|
||||
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b)) nm_platform_ip4_route_cmp,
|
||||
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route)) nm_platform_ip4_route_to_string,
|
||||
.route_get_all = nm_platform_ip4_route_get_all,
|
||||
.route_add = _vtr_v4_route_add,
|
||||
.route_delete = _vtr_v4_route_delete,
|
||||
.route_delete_default = _vtr_v4_route_delete_default,
|
||||
.metric_normalize = _vtr_v4_metric_normalize,
|
||||
};
|
||||
|
||||
const NMPlatformVTableRoute nm_platform_vtable_route_v6 = {
|
||||
.is_ip4 = FALSE,
|
||||
.addr_family = AF_INET6,
|
||||
.sizeof_route = sizeof (NMPlatformIP6Route),
|
||||
.route_cmp = (int (*) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b)) nm_platform_ip6_route_cmp,
|
||||
.route_to_string = (const char *(*) (const NMPlatformIPXRoute *route)) nm_platform_ip6_route_to_string,
|
||||
.route_get_all = nm_platform_ip6_route_get_all,
|
||||
.route_add = _vtr_v6_route_add,
|
||||
.route_delete = _vtr_v6_route_delete,
|
||||
.route_delete_default = _vtr_v6_route_delete_default,
|
||||
.metric_normalize = nm_utils_ip6_route_metric_normalize,
|
||||
};
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
nm_platform_init (NMPlatform *object)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -246,6 +246,23 @@ typedef union {
|
|||
#undef __NMPlatformObject_COMMON
|
||||
|
||||
|
||||
typedef struct {
|
||||
gboolean is_ip4;
|
||||
int addr_family;
|
||||
gsize sizeof_route;
|
||||
int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b);
|
||||
const char *(*route_to_string) (const NMPlatformIPXRoute *route);
|
||||
GArray *(*route_get_all) (int ifindex, NMPlatformGetRouteMode mode);
|
||||
gboolean (*route_add) (int ifindex, const NMPlatformIPXRoute *route, guint32 v4_pref_src);
|
||||
gboolean (*route_delete) (int ifindex, const NMPlatformIPXRoute *route);
|
||||
gboolean (*route_delete_default) (int ifindex, guint32 metric);
|
||||
guint32 (*metric_normalize) (guint32 metric);
|
||||
} NMPlatformVTableRoute;
|
||||
|
||||
extern const NMPlatformVTableRoute nm_platform_vtable_route_v4;
|
||||
extern const NMPlatformVTableRoute nm_platform_vtable_route_v6;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int peer;
|
||||
} NMPlatformVethProperties;
|
||||
|
|
|
|||
|
|
@ -246,6 +246,12 @@ test_ip6_address_external (void)
|
|||
free_signal (address_removed);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_with_logging (argc, argv, NULL, "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -86,6 +86,12 @@ test_cleanup_internal (void)
|
|||
g_array_unref (routes6);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_with_logging (argc, argv, NULL, "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ main (int argc, char **argv)
|
|||
int result;
|
||||
const char *program = *argv;
|
||||
|
||||
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
|
||||
init_tests (&argc, &argv);
|
||||
|
||||
NM_PRAGMA_WARNING_DISABLE("-Wtautological-compare")
|
||||
if (SETUP == nm_linux_platform_setup && getuid() != 0) {
|
||||
|
|
@ -263,10 +263,10 @@ main (int argc, char **argv)
|
|||
nmtst_reexec_sudo ();
|
||||
|
||||
#ifdef REQUIRE_ROOT_TESTS
|
||||
g_message ("Fail test: requires root privileges (%s)", program);
|
||||
g_print ("Fail test: requires root privileges (%s)\n", program);
|
||||
return EXIT_FAILURE;
|
||||
#else
|
||||
g_message ("Skipping test: requires root privileges (%s)", program);
|
||||
g_print ("Skipping test: requires root privileges (%s)\n", program);
|
||||
return 77;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include "nm-fake-platform.h"
|
||||
#include "nm-linux-platform.h"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
#define DEVICE_NAME "nm-test-device"
|
||||
|
||||
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
||||
|
|
@ -43,5 +45,6 @@ void link_callback (NMPlatform *platform, int ifindex, NMPlatformLink *received,
|
|||
|
||||
void run_command (const char *format, ...);
|
||||
|
||||
void init_tests (int *argc, char ***argv);
|
||||
void setup_tests (void);
|
||||
|
||||
|
|
|
|||
|
|
@ -539,6 +539,12 @@ test_external (void)
|
|||
free_signal (link_removed);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_with_logging (argc, argv, NULL, "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ test_ip4_route (void)
|
|||
rts[2].mss = mss;
|
||||
g_assert_cmpint (routes->len, ==, 3);
|
||||
g_assert (!memcmp (routes->data, rts, sizeof (rts)));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len);
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE);
|
||||
g_array_unref (routes);
|
||||
|
||||
/* Remove route */
|
||||
|
|
@ -293,7 +293,7 @@ test_ip6_route (void)
|
|||
rts[2].mss = mss;
|
||||
g_assert_cmpint (routes->len, ==, 3);
|
||||
g_assert (!memcmp (routes->data, rts, sizeof (rts)));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE);
|
||||
g_array_unref (routes);
|
||||
|
||||
/* Remove route */
|
||||
|
|
@ -311,6 +311,12 @@ test_ip6_route (void)
|
|||
free_signal (route_removed);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_with_logging (argc, argv, NULL, "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ NMTST_DEFINE ();
|
|||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
g_test_add_func (TPATH "ibft/dhcp", test_read_ibft_dhcp);
|
||||
g_test_add_func (TPATH "ibft/static", test_read_ibft_static);
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ int main (int argc, char **argv)
|
|||
{
|
||||
char *base;
|
||||
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
/* The tests */
|
||||
test_get_ifcfg_name ("get-ifcfg-name-bad", "/foo/bar/adfasdfadf", FALSE, NULL);
|
||||
|
|
|
|||
|
|
@ -12443,7 +12443,7 @@ NMTST_DEFINE ();
|
|||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
g_test_add_func (TPATH "svUnescape", test_svUnescape);
|
||||
g_test_add_func (TPATH "vlan-trailing-spaces", test_read_vlan_trailing_spaces);
|
||||
|
|
|
|||
|
|
@ -448,8 +448,7 @@ main (int argc, char **argv)
|
|||
|
||||
nm_linux_platform_setup ();
|
||||
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nm_logging_setup ("WARN", "DEFAULT", NULL, NULL);
|
||||
nmtst_init_assert_logging (&argc, &argv, "WARN", "DEFAULT");
|
||||
|
||||
f = g_build_filename (argv[1], "net", NULL);
|
||||
ifnet_init (f);
|
||||
|
|
|
|||
|
|
@ -3632,7 +3632,7 @@ NMTST_DEFINE ();
|
|||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
/* The tests */
|
||||
g_test_add_func ("/keyfile/test_read_valid_wired_connection ", test_read_valid_wired_connection);
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ NMTST_DEFINE ();
|
|||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT");
|
||||
|
||||
/* Initialize the DBus manager singleton explicitly, because it is accessed by
|
||||
* the class initializer of NMDevice (used by the NMTestDevice stub).
|
||||
|
|
|
|||
|
|
@ -330,6 +330,104 @@ test_nm_utils_kill_child (void)
|
|||
g_test_assert_expected_messages ();
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
static void
|
||||
_remove_at_indexes_init_random_idx (GArray *idx, guint array_len, guint idx_len)
|
||||
{
|
||||
GRand *rand = nmtst_get_rand ();
|
||||
gs_free char *mask = NULL;
|
||||
guint i, max_test_idx;
|
||||
|
||||
g_assert (idx);
|
||||
g_assert (array_len > 0);
|
||||
g_assert (idx_len >= 1 && idx_len <= array_len);
|
||||
|
||||
mask = g_new0 (char, array_len);
|
||||
|
||||
max_test_idx = array_len - 1;
|
||||
for (i = 0; i < idx_len; i++) {
|
||||
guint itest;
|
||||
|
||||
/* find a index itest that is not yet taken */
|
||||
if (max_test_idx == 0)
|
||||
itest = 0;
|
||||
else
|
||||
itest = g_rand_int_range (rand, 0, max_test_idx);
|
||||
while (itest < array_len && mask[itest])
|
||||
itest++;
|
||||
g_assert (itest <= max_test_idx);
|
||||
g_assert (!mask[itest]);
|
||||
|
||||
mask[itest] = TRUE;
|
||||
if (itest == max_test_idx) {
|
||||
g_assert (max_test_idx > 0 || i == idx_len - 1);
|
||||
|
||||
if (max_test_idx == 0)
|
||||
g_assert_cmpint (i, ==, idx_len - 1);
|
||||
else {
|
||||
max_test_idx--;
|
||||
while (max_test_idx > 0 && mask[max_test_idx])
|
||||
max_test_idx--;
|
||||
if (mask[max_test_idx])
|
||||
g_assert_cmpint (i, ==, idx_len - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_array_set_size (idx, 0);
|
||||
for (i = 0; i < array_len; i++) {
|
||||
if (mask[i])
|
||||
g_array_append_val (idx, i);
|
||||
}
|
||||
g_assert_cmpint (idx->len, ==, idx_len);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_utils_array_remove_at_indexes ()
|
||||
{
|
||||
gs_unref_array GArray *idx = NULL, *array = NULL;
|
||||
gs_unref_hashtable GHashTable *unique = NULL;
|
||||
guint i_len, i_idx_len, i_rnd, i;
|
||||
|
||||
idx = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||
array = g_array_new (FALSE, FALSE, sizeof (gssize));
|
||||
unique = g_hash_table_new (NULL, NULL);
|
||||
for (i_len = 1; i_len < 20; i_len++) {
|
||||
for (i_idx_len = 1; i_idx_len <= i_len; i_idx_len++) {
|
||||
for (i_rnd = 0; i_rnd < 20; i_rnd++) {
|
||||
|
||||
_remove_at_indexes_init_random_idx (idx, i_len, i_idx_len);
|
||||
g_array_set_size (array, i_len);
|
||||
for (i = 0; i < i_len; i++)
|
||||
g_array_index (array, gssize, i) = i;
|
||||
|
||||
nm_utils_array_remove_at_indexes (array, &g_array_index (idx, guint, 0), i_idx_len);
|
||||
|
||||
g_hash_table_remove_all (unique);
|
||||
/* ensure that all the indexes are still unique */
|
||||
for (i = 0; i < array->len; i++)
|
||||
g_hash_table_add (unique, GUINT_TO_POINTER (g_array_index (array, gssize, i)));
|
||||
g_assert_cmpint (g_hash_table_size (unique), ==, array->len);
|
||||
|
||||
for (i = 0; i < idx->len; i++)
|
||||
g_hash_table_add (unique, GUINT_TO_POINTER (g_array_index (idx, guint, i)));
|
||||
g_assert_cmpint (g_hash_table_size (unique), ==, i_len);
|
||||
|
||||
/* ensure proper sort order in array */
|
||||
for (i = 0; i < array->len; i++) {
|
||||
gssize i1 = g_array_index (array, gssize, i);
|
||||
|
||||
g_assert (i1 >= 0 && i1 < i_len);
|
||||
if (i > 0) {
|
||||
gsize i0 = g_array_index (array, gssize, i - 1);
|
||||
g_assert_cmpint (i0, <, i1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
|
|
@ -338,11 +436,10 @@ NMTST_DEFINE ();
|
|||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_assert_logging (&argc, &argv);
|
||||
|
||||
nm_logging_setup ("DEBUG", "DEFAULT", NULL, NULL);
|
||||
nmtst_init_assert_logging (&argc, &argv, "DEBUG", "DEFAULT");
|
||||
|
||||
g_test_add_func ("/general/nm_utils_kill_child", test_nm_utils_kill_child);
|
||||
g_test_add_func ("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ typedef struct {
|
|||
} test_fixture;
|
||||
|
||||
static void
|
||||
setup_dev0_ip4 (int ifindex)
|
||||
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;
|
||||
|
|
@ -49,13 +49,15 @@ setup_dev0_ip4 (int ifindex)
|
|||
route.plen = 24;
|
||||
route.gateway = INADDR_ANY;
|
||||
route.metric = 20;
|
||||
route.mss = mss_of_first_route;
|
||||
g_array_append_val (routes, route);
|
||||
|
||||
route.source = 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 = 21;
|
||||
route.metric = metric_of_second_route;
|
||||
route.mss = 0;
|
||||
g_array_append_val (routes, route);
|
||||
|
||||
nm_route_manager_ip4_route_sync (nm_route_manager_get (), ifindex, routes);
|
||||
|
|
@ -162,7 +164,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.ifindex = fixture->ifindex0,
|
||||
.gateway = INADDR_ANY,
|
||||
.metric = 20,
|
||||
.mss = 0,
|
||||
.mss = 1000,
|
||||
},
|
||||
{
|
||||
.source = NM_IP_CONFIG_SOURCE_USER,
|
||||
|
|
@ -170,7 +172,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.plen = 8,
|
||||
.ifindex = fixture->ifindex0,
|
||||
.gateway = nmtst_inet4_from_string ("6.6.6.1"),
|
||||
.metric = 21,
|
||||
.metric = 21021,
|
||||
.mss = 0,
|
||||
},
|
||||
{
|
||||
|
|
@ -233,19 +235,10 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
.metric = 20,
|
||||
.mss = 0,
|
||||
},
|
||||
{
|
||||
.source = 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,
|
||||
},
|
||||
};
|
||||
|
||||
setup_dev0_ip4 (fixture->ifindex0);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
setup_dev0_ip4 (fixture->ifindex0, 1000, 21021);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 8.0.0.0/8 via 6.6.6.2 dev nm-test-device1 *");
|
||||
setup_dev1_ip4 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
|
|
@ -254,28 +247,29 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
* 8.0.0.0/8 could not be added. */
|
||||
routes = ip4_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len);
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 8.0.0.0/8 via 6.6.6.2 dev nm-test-device1 *");
|
||||
setup_dev1_ip4 (fixture->ifindex1);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
setup_dev0_ip4 (fixture->ifindex0);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
setup_dev0_ip4 (fixture->ifindex0, 0, 21);
|
||||
|
||||
/* Ensure nothing changed. */
|
||||
routes = ip4_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state1, routes->len);
|
||||
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);
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
update_dev0_ip4 (fixture->ifindex0);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
/* 7.0.0.0/8 on dev0 was updated for gateway removal*/
|
||||
routes = ip4_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state2));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state2, routes->len);
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state2, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
nm_route_manager_route_flush (nm_route_manager_get (), fixture->ifindex0);
|
||||
|
|
@ -286,7 +280,7 @@ test_ip4 (test_fixture *fixture, gconstpointer user_data)
|
|||
* No dev0 routes left. */
|
||||
routes = ip4_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state3));
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state3, routes->len);
|
||||
nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, state3, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
nm_route_manager_route_flush (nm_route_manager_get (), fixture->ifindex1);
|
||||
|
|
@ -570,19 +564,10 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|||
.metric = 1024,
|
||||
.mss = 0,
|
||||
},
|
||||
{
|
||||
.source = 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);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 2001:db8:d34d::/64 via 2001:db8:8086::2 dev nm-test-device1 *");
|
||||
setup_dev1_ip6 (fixture->ifindex1);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
|
|
@ -592,28 +577,27 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|||
* 2001:db8:abad:c0de::/64 routes did not clash */
|
||||
routes = ip6_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding 2001:db8:d34d::/64 via 2001:db8:8086::2 dev nm-test-device1 *");
|
||||
setup_dev1_ip6 (fixture->ifindex1);
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
setup_dev0_ip6 (fixture->ifindex0);
|
||||
g_test_assert_expected_messages ();
|
||||
setup_dev0_ip6 (fixture->ifindex0);
|
||||
|
||||
/* Ensure nothing changed. */
|
||||
routes = ip6_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state1));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state1, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_WARNING, "*error adding*");
|
||||
update_dev0_ip6 (fixture->ifindex0);
|
||||
g_test_assert_expected_messages ();
|
||||
|
||||
/* 2001:db8:abad:c0de::/64 on dev0 was updated for gateway removal*/
|
||||
routes = ip6_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state2));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state2, routes->len);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state2, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
nm_route_manager_route_flush (nm_route_manager_get (), fixture->ifindex0);
|
||||
|
|
@ -625,7 +609,7 @@ test_ip6 (test_fixture *fixture, gconstpointer user_data)
|
|||
* No dev0 routes left. */
|
||||
routes = ip6_routes (fixture);
|
||||
g_assert_cmpint (routes->len, ==, G_N_ELEMENTS (state3));
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state3, routes->len);
|
||||
nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, state3, routes->len, TRUE);
|
||||
g_array_free (routes, TRUE);
|
||||
|
||||
nm_route_manager_route_flush (nm_route_manager_get (), fixture->ifindex1);
|
||||
|
|
@ -673,6 +657,12 @@ fixture_teardown (test_fixture *fixture, gconstpointer user_data)
|
|||
nm_platform_link_delete (fixture->ifindex1);
|
||||
}
|
||||
|
||||
void
|
||||
init_tests (int *argc, char ***argv)
|
||||
{
|
||||
nmtst_init_assert_logging (argc, argv, "WARN", "ALL");
|
||||
}
|
||||
|
||||
void
|
||||
setup_tests (void)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue