core: refactor NMIP6Config to use dedup-index for IPv6 routes

This commit is contained in:
Thomas Haller
2017-07-03 17:03:54 +02:00
parent 28340588d9
commit cfd1851c00
9 changed files with 363 additions and 201 deletions

View File

@@ -111,7 +111,9 @@ get_ip6_rdns_domains (NMIP6Config *ip6)
{ {
char **strv; char **strv;
GPtrArray *domains = NULL; GPtrArray *domains = NULL;
int i; guint i;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *route;
g_return_val_if_fail (ip6 != NULL, NULL); g_return_val_if_fail (ip6 != NULL, NULL);
@@ -123,11 +125,8 @@ get_ip6_rdns_domains (NMIP6Config *ip6)
nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains);
} }
for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route)
const NMPlatformIP6Route *route = nm_ip6_config_get_route (ip6, i);
nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains);
}
/* Terminating NULL so we can use g_strfreev() to free it */ /* Terminating NULL so we can use g_strfreev() to free it */
g_ptr_array_add (domains, NULL); g_ptr_array_add (domains, NULL);

View File

@@ -182,6 +182,7 @@ static void
dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder) dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
{ {
GVariantBuilder int_builder; GVariantBuilder int_builder;
NMDedupMultiIter ipconf_iter;
guint n, i; guint n, i;
const NMPlatformIP6Address *addr; const NMPlatformIP6Address *addr;
const struct in6_addr *gw_bytes; const struct in6_addr *gw_bytes;
@@ -230,9 +231,7 @@ dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder)
/* Static routes */ /* Static routes */
g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)")); g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)"));
n = nm_ip6_config_get_num_routes (ip6); nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) {
for (i = 0; i < n; i++) {
route = nm_ip6_config_get_route (ip6, i);
ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
&route->network, &route->network,
sizeof (struct in6_addr), 1); sizeof (struct in6_addr), 1);

View File

@@ -46,14 +46,22 @@ G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
/*****************************************************************************/ /*****************************************************************************/
static gboolean gboolean
_idx_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a, nm_ip_config_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a,
const NMPlatformIP4Route *r_b) const NMPlatformIP4Route *r_b)
{ {
return r_a->network == r_b->network return r_a->network == r_b->network
&& r_a->plen == r_b->plen; && r_a->plen == r_b->plen;
} }
gboolean
nm_ip_config_obj_id_equal_ip6_route (const NMPlatformIP6Route *r_a,
const NMPlatformIP6Route *r_b)
{
return r_a->plen == r_b->plen
&& IN6_ARE_ADDR_EQUAL (&r_a->network, &r_b->network);
}
static guint static guint
_idx_obj_id_hash (const NMDedupMultiIdxType *idx_type, _idx_obj_id_hash (const NMDedupMultiIdxType *idx_type,
const NMDedupMultiObj *obj) const NMDedupMultiObj *obj)
@@ -68,10 +76,13 @@ _idx_obj_id_hash (const NMDedupMultiIdxType *idx_type,
case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP4_ROUTE:
h = 40303327; h = 40303327;
h = NM_HASH_COMBINE (h, o->ip4_route.network); h = NM_HASH_COMBINE (h, o->ip4_route.network);
h = NM_HASH_COMBINE (h, o->ip4_route.plen); h = NM_HASH_COMBINE (h, o->ip_route.plen);
break; break;
case NMP_OBJECT_TYPE_IP6_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE:
g_return_val_if_reached (0); h = 577629323;
h = NM_HASH_COMBINE_IN6_ADDR (h, &o->ip6_route.network);
h = NM_HASH_COMBINE (h, o->ip_route.plen);
break;
default: default:
g_return_val_if_reached (0); g_return_val_if_reached (0);
}; };
@@ -94,9 +105,9 @@ _idx_obj_id_equal (const NMDedupMultiIdxType *idx_type,
case NMP_OBJECT_TYPE_IP6_ADDRESS: case NMP_OBJECT_TYPE_IP6_ADDRESS:
g_return_val_if_reached (FALSE); g_return_val_if_reached (FALSE);
case NMP_OBJECT_TYPE_IP4_ROUTE: case NMP_OBJECT_TYPE_IP4_ROUTE:
return _idx_obj_id_equal_ip4_route (&o_a->ip4_route, &o_b->ip4_route); return nm_ip_config_obj_id_equal_ip4_route (&o_a->ip4_route, &o_b->ip4_route);
case NMP_OBJECT_TYPE_IP6_ROUTE: case NMP_OBJECT_TYPE_IP6_ROUTE:
g_return_val_if_reached (FALSE); return nm_ip_config_obj_id_equal_ip6_route (&o_a->ip6_route, &o_b->ip6_route);
default: default:
g_return_val_if_reached (FALSE); g_return_val_if_reached (FALSE);
}; };
@@ -1300,7 +1311,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev
if (nm_platform_ip4_route_cmp (r_src, r_dst) != 0) { if (nm_platform_ip4_route_cmp (r_src, r_dst) != 0) {
are_equal = FALSE; are_equal = FALSE;
if (!_idx_obj_id_equal_ip4_route (r_src, r_dst)) { if (!nm_ip_config_obj_id_equal_ip4_route (r_src, r_dst)) {
has_relevant_changes = TRUE; has_relevant_changes = TRUE;
break; break;
} }

View File

@@ -43,6 +43,11 @@ gboolean nm_ip4_config_iter_ip4_route_next (NMDedupMultiIter *iter, const NMPlat
nm_ip4_config_iter_ip4_route_next ((iter), (route)); \ nm_ip4_config_iter_ip4_route_next ((iter), (route)); \
) )
gboolean nm_ip_config_obj_id_equal_ip4_route (const NMPlatformIP4Route *r_a,
const NMPlatformIP4Route *r_b);
gboolean nm_ip_config_obj_id_equal_ip6_route (const NMPlatformIP6Route *r_a,
const NMPlatformIP6Route *r_b);
/*****************************************************************************/ /*****************************************************************************/
#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ()) #define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type ())

View File

@@ -29,11 +29,13 @@
#include "nm-utils/nm-dedup-multi.h" #include "nm-utils/nm-dedup-multi.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "platform/nmp-object.h"
#include "platform/nm-platform.h" #include "platform/nm-platform.h"
#include "platform/nm-platform-utils.h" #include "platform/nm-platform-utils.h"
#include "nm-route-manager.h" #include "nm-route-manager.h"
#include "nm-core-internal.h" #include "nm-core-internal.h"
#include "NetworkManagerUtils.h" #include "NetworkManagerUtils.h"
#include "nm-ip4-config.h"
#include "introspection/org.freedesktop.NetworkManager.IP6Config.h" #include "introspection/org.freedesktop.NetworkManager.IP6Config.h"
@@ -48,7 +50,6 @@ typedef struct {
gint64 route_metric; gint64 route_metric;
struct in6_addr gateway; struct in6_addr gateway;
GArray *addresses; GArray *addresses;
GArray *routes;
GArray *nameservers; GArray *nameservers;
GPtrArray *domains; GPtrArray *domains;
GPtrArray *searches; GPtrArray *searches;
@@ -56,6 +57,7 @@ typedef struct {
GVariant *address_data_variant; GVariant *address_data_variant;
GVariant *addresses_variant; GVariant *addresses_variant;
NMDedupMultiIndex *multi_idx; NMDedupMultiIndex *multi_idx;
NMDedupMultiIdxType idx_ip6_routes;
} NMIP6ConfigPrivate; } NMIP6ConfigPrivate;
struct _NMIP6Config { struct _NMIP6Config {
@@ -88,6 +90,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config,
/*****************************************************************************/ /*****************************************************************************/
static void _add_route (NMIP6Config *config, const NMPObject *o_new, const NMPlatformIP6Route *new);
/*****************************************************************************/
int int
nm_ip6_config_get_ifindex (const NMIP6Config *config) nm_ip6_config_get_ifindex (const NMIP6Config *config)
{ {
@@ -110,6 +116,49 @@ nm_ip6_config_set_privacy (NMIP6Config *config, NMSettingIP6ConfigPrivacy privac
/*****************************************************************************/ /*****************************************************************************/
static const NMDedupMultiHeadEntry *
_idx_ip6_routes (const NMIP6Config *self)
{
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
return nm_dedup_multi_index_lookup_head (priv->multi_idx,
&priv->idx_ip6_routes,
NULL);
}
static const NMPlatformIP6Route *
_entry_iter_get_ip6_route (const CList *iter)
{
const NMDedupMultiEntry *e = c_list_entry (iter, NMDedupMultiEntry, lst_entries);
const NMPObject *o = e->obj;
nm_assert (o);
nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_TYPE_IP6_ROUTE);
return &o->ip6_route;
}
void
nm_ip6_config_iter_ip6_route_init (NMDedupMultiIter *ipconf_iter, const NMIP6Config *self)
{
g_return_if_fail (NM_IS_IP6_CONFIG (self));
nm_dedup_multi_iter_init (ipconf_iter, _idx_ip6_routes (self));
}
gboolean
nm_ip6_config_iter_ip6_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatformIP6Route **out_route)
{
gboolean has_next;
has_next = nm_dedup_multi_iter_next (ipconf_iter);
if (has_next) {
nm_assert (NMP_OBJECT_GET_TYPE (ipconf_iter->current->obj) == NMP_OBJECT_TYPE_IP6_ROUTE);
NM_SET_OUT (out_route, &(((const NMPObject *) ipconf_iter->current->obj)->ip6_route));
}
return has_next;
}
/*****************************************************************************/
static void static void
notify_addresses (NMIP6Config *self) notify_addresses (NMIP6Config *self)
{ {
@@ -193,15 +242,6 @@ addresses_are_duplicate (const NMPlatformIP6Address *a, const NMPlatformIP6Addre
return IN6_ARE_ADDR_EQUAL (&a->address, &b->address); return IN6_ARE_ADDR_EQUAL (&a->address, &b->address);
} }
static gboolean
routes_are_duplicate (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gboolean consider_gateway_and_metric)
{
return IN6_ARE_ADDR_EQUAL (&a->network, &b->network) && a->plen == b->plen &&
( !consider_gateway_and_metric
|| ( IN6_ARE_ADDR_EQUAL (&a->gateway, &b->gateway)
&& nm_utils_ip6_route_metric_normalize (a->metric) == nm_utils_ip6_route_metric_normalize (b->metric)));
}
static gint static gint
_addresses_sort_cmp_get_prio (const struct in6_addr *addr) _addresses_sort_cmp_get_prio (const struct in6_addr *addr)
{ {
@@ -315,10 +355,12 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
{ {
NMIP6Config *config; NMIP6Config *config;
NMIP6ConfigPrivate *priv; NMIP6ConfigPrivate *priv;
guint i;
guint32 lowest_metric = G_MAXUINT32; guint32 lowest_metric = G_MAXUINT32;
struct in6_addr old_gateway = IN6ADDR_ANY_INIT; struct in6_addr old_gateway = IN6ADDR_ANY_INIT;
gboolean has_gateway = FALSE; gboolean has_gateway;
const NMDedupMultiHeadEntry *pl_head_entry;
NMDedupMultiIter iter;
const NMPObject *plobj = NULL;
gboolean notify_nameservers = FALSE; gboolean notify_nameservers = FALSE;
/* Slaves have no IP configuration */ /* Slaves have no IP configuration */
@@ -329,47 +371,56 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
priv = NM_IP6_CONFIG_GET_PRIVATE (config); priv = NM_IP6_CONFIG_GET_PRIVATE (config);
g_array_unref (priv->addresses); g_array_unref (priv->addresses);
g_array_unref (priv->routes);
priv->addresses = nm_platform_ip6_address_get_all (platform, ifindex); priv->addresses = nm_platform_ip6_address_get_all (platform, ifindex);
priv->routes = nm_platform_ip6_route_get_all (platform, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
pl_head_entry = nm_platform_lookup_route_visible (platform,
NMP_OBJECT_TYPE_IP6_ROUTE,
ifindex,
TRUE,
TRUE);
/* Extract gateway from default route */ /* Extract gateway from default route */
old_gateway = priv->gateway; old_gateway = priv->gateway;
for (i = 0; i < priv->routes->len; ) {
const NMPlatformIP6Route *route = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) { lowest_metric = G_MAXUINT32;
has_gateway = FALSE;
nmp_cache_iter_for_each (&iter, pl_head_entry, &plobj) {
const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (plobj);
if ( NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)
&& route->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL) {
if (route->metric < lowest_metric) { if (route->metric < lowest_metric) {
priv->gateway = route->gateway; priv->gateway = route->gateway;
lowest_metric = route->metric; lowest_metric = route->metric;
} }
has_gateway = TRUE; has_gateway = TRUE;
/* Remove the default route from the list */
g_array_remove_index_fast (priv->routes, i);
continue;
} }
i++;
} }
/* we detect the route metric based on the default route. All non-default /* we detect the route metric based on the default route. All non-default
* routes have their route metrics explicitly set. */ * routes have their route metrics explicitly set. */
priv->route_metric = has_gateway ? (gint64) lowest_metric : (gint64) -1; priv->route_metric = has_gateway ? (gint64) lowest_metric : (gint64) -1;
nm_dedup_multi_iter_rewind (&iter);
nmp_cache_iter_for_each (&iter, pl_head_entry, &plobj) {
const NMPlatformIP6Route *route = NMP_OBJECT_CAST_IP6_ROUTE (plobj);
if (route->rt_source == NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
continue;
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 /* If there is a host route to the gateway, ignore that route. It is
* automatically added by NetworkManager when needed. * automatically added by NetworkManager when needed.
*/ */
if (has_gateway) { continue;
for (i = 0; i < priv->routes->len; i++) {
const NMPlatformIP6Route *route = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if ( route->plen == 128
&& IN6_ARE_ADDR_EQUAL (&route->network, &priv->gateway)
&& IN6_IS_ADDR_UNSPECIFIED (&route->gateway)) {
g_array_remove_index (priv->routes, i);
i--;
}
} }
_add_route (config, plobj, NULL);
} }
/* If the interface has the default route, and has IPv6 addresses, capture /* If the interface has the default route, and has IPv6 addresses, capture
@@ -403,7 +454,6 @@ nm_ip6_config_commit (const NMIP6Config *config,
gboolean routes_full_sync) gboolean routes_full_sync)
{ {
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
gboolean success;
g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (config != NULL, FALSE); g_return_val_if_fail (config != NULL, FALSE);
@@ -413,21 +463,24 @@ nm_ip6_config_commit (const NMIP6Config *config,
/* Routes */ /* Routes */
{ {
guint i; const NMDedupMultiHeadEntry *head_entry;
guint count = nm_ip6_config_get_num_routes (config); gs_unref_array GArray *routes = NULL;
GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP6Route), count); const CList *iter;
const NMPlatformIP6Route *route;
for (i = 0; i < count; i++) { head_entry = _idx_ip6_routes (config);
route = nm_ip6_config_get_route (config, i);
g_array_append_vals (routes, route, 1); 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, _entry_iter_get_ip6_route (iter), 1);
} }
success = nm_route_manager_ip6_route_sync (route_manager, ifindex, routes, TRUE, routes_full_sync); if (!nm_route_manager_ip6_route_sync (route_manager, ifindex, routes, TRUE, routes_full_sync))
g_array_unref (routes); return FALSE;
} }
return success; return TRUE;
} }
static void static void
@@ -558,7 +611,7 @@ nm_ip6_config_merge_setting (NMIP6Config *config, NMSettingIPConfig *setting, gu
route.rt_source = NM_IP_CONFIG_SOURCE_USER; route.rt_source = NM_IP_CONFIG_SOURCE_USER;
merge_route_attributes (s_route, &route); merge_route_attributes (s_route, &route);
nm_ip6_config_add_route (config, &route); _add_route (config, NULL, &route);
} }
/* DNS */ /* DNS */
@@ -594,10 +647,12 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
{ {
NMSettingIPConfig *s_ip6; NMSettingIPConfig *s_ip6;
const struct in6_addr *gateway; const struct in6_addr *gateway;
guint naddresses, nroutes, nnameservers, nsearches, noptions; guint naddresses, nnameservers, nsearches, noptions;
const char *method = NULL; const char *method = NULL;
int i; int i;
gint64 route_metric; gint64 route_metric;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *route;
s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ()); s_ip6 = NM_SETTING_IP_CONFIG (nm_setting_ip6_config_new ());
@@ -610,7 +665,6 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
gateway = nm_ip6_config_get_gateway (config); gateway = nm_ip6_config_get_gateway (config);
naddresses = nm_ip6_config_get_num_addresses (config); naddresses = nm_ip6_config_get_num_addresses (config);
nroutes = nm_ip6_config_get_num_routes (config);
nnameservers = nm_ip6_config_get_num_nameservers (config); nnameservers = nm_ip6_config_get_num_nameservers (config);
nsearches = nm_ip6_config_get_num_searches (config); nsearches = nm_ip6_config_get_num_searches (config);
noptions = nm_ip6_config_get_num_dns_options (config); noptions = nm_ip6_config_get_num_dns_options (config);
@@ -661,8 +715,7 @@ nm_ip6_config_create_setting (const NMIP6Config *config)
NULL); NULL);
/* Routes */ /* Routes */
for (i = 0; i < nroutes; i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, config, &route) {
const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i);
NMIPRoute *s_route; NMIPRoute *s_route;
/* Ignore link-local route. */ /* Ignore link-local route. */
@@ -718,6 +771,7 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
NMIP6ConfigPrivate *dst_priv; NMIP6ConfigPrivate *dst_priv;
const NMIP6ConfigPrivate *src_priv; const NMIP6ConfigPrivate *src_priv;
guint32 i; guint32 i;
NMDedupMultiIter ipconf_iter;
g_return_if_fail (src != NULL); g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL); g_return_if_fail (dst != NULL);
@@ -743,8 +797,10 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl
/* routes */ /* routes */
if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) { if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) const NMPlatformIP6Route *route;
nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, src, &route)
_add_route (dst, NMP_OBJECT_UP_CAST (route), NULL);
} }
if (dst_priv->route_metric == -1) if (dst_priv->route_metric == -1)
@@ -833,21 +889,6 @@ _nameservers_get_index (const NMIP6Config *self, const struct in6_addr *ns)
return -1; return -1;
} }
static int
_routes_get_index (const NMIP6Config *self, const NMPlatformIP6Route *route)
{
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
guint i;
for (i = 0; i < priv->routes->len; i++) {
const NMPlatformIP6Route *r = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (routes_are_duplicate (route, r, FALSE))
return (int) i;
}
return -1;
}
static int static int
_domains_get_index (const NMIP6Config *self, const char *domain) _domains_get_index (const NMIP6Config *self, const char *domain)
{ {
@@ -905,13 +946,18 @@ _dns_options_get_index (const NMIP6Config *self, const char *option)
void void
nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
{ {
NMIP6ConfigPrivate *priv_dst;
guint i; guint i;
gint idx; gint idx;
const NMPlatformIP6Route *r;
NMDedupMultiIter ipconf_iter;
const struct in6_addr *dst_tmp, *src_tmp; const struct in6_addr *dst_tmp, *src_tmp;
g_return_if_fail (src != NULL); g_return_if_fail (src != NULL);
g_return_if_fail (dst != NULL); g_return_if_fail (dst != NULL);
priv_dst = NM_IP6_CONFIG_GET_PRIVATE (dst);
g_object_freeze_notify (G_OBJECT (dst)); g_object_freeze_notify (G_OBJECT (dst));
/* addresses */ /* addresses */
@@ -940,10 +986,10 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
/* ignore route_metric */ /* ignore route_metric */
/* routes */ /* routes */
for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
idx = _routes_get_index (dst, nm_ip6_config_get_route (src, i)); nm_dedup_multi_index_remove_obj (priv_dst->multi_idx,
if (idx >= 0) &priv_dst->idx_ip6_routes,
nm_ip6_config_del_route (dst, idx); NMP_OBJECT_UP_CAST (r));
} }
/* domains */ /* domains */
@@ -980,12 +1026,19 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src)
void void
nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
{ {
NMIP6ConfigPrivate *priv_dst;
const NMIP6ConfigPrivate *priv_src;
guint i; guint i;
gint idx; gint idx;
const struct in6_addr *dst_tmp, *src_tmp; const struct in6_addr *dst_tmp, *src_tmp;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *r;
g_return_if_fail (src != NULL); g_return_if_fail (src);
g_return_if_fail (dst != NULL); g_return_if_fail (dst);
priv_dst = NM_IP6_CONFIG_GET_PRIVATE (dst);
priv_src = NM_IP6_CONFIG_GET_PRIVATE (src);
g_object_freeze_notify (G_OBJECT (dst)); g_object_freeze_notify (G_OBJECT (dst));
@@ -1012,12 +1065,15 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src)
} }
/* routes */ /* routes */
for (i = 0; i < nm_ip6_config_get_num_routes (dst); ) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, dst, &r) {
idx = _routes_get_index (src, nm_ip6_config_get_route (dst, i)); if (nm_dedup_multi_index_lookup_obj (priv_src->multi_idx,
if (idx < 0) &priv_src->idx_ip6_routes,
nm_ip6_config_del_route (dst, i); NMP_OBJECT_UP_CAST (r)))
else continue;
i++;
if (nm_dedup_multi_index_remove_entry (priv_dst->multi_idx,
ipconf_iter.current) != 1)
nm_assert_not_reached ();
} }
/* ignore domains */ /* ignore domains */
@@ -1052,7 +1108,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
NMIP6ConfigPrivate *dst_priv; NMIP6ConfigPrivate *dst_priv;
const NMIP6ConfigPrivate *src_priv; const NMIP6ConfigPrivate *src_priv;
const NMPlatformIP6Address *dst_addr, *src_addr; const NMPlatformIP6Address *dst_addr, *src_addr;
const NMPlatformIP6Route *dst_route, *src_route; NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
g_return_val_if_fail (NM_IS_IP6_CONFIG (src), FALSE); g_return_val_if_fail (NM_IS_IP6_CONFIG (src), FALSE);
g_return_val_if_fail (NM_IS_IP6_CONFIG (dst), FALSE); g_return_val_if_fail (NM_IS_IP6_CONFIG (dst), FALSE);
@@ -1117,26 +1173,45 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev
} }
/* routes */ /* routes */
num = nm_ip6_config_get_num_routes (src); nm_ip6_config_iter_ip6_route_init (&ipconf_iter_src, src);
are_equal = num == nm_ip6_config_get_num_routes (dst); nm_ip6_config_iter_ip6_route_init (&ipconf_iter_dst, dst);
if (are_equal) { are_equal = TRUE;
for (i = 0; i < num; i++ ) { while (TRUE) {
if (nm_platform_ip6_route_cmp (src_route = nm_ip6_config_get_route (src, i), gboolean has;
dst_route = nm_ip6_config_get_route (dst, i))) { const NMPlatformIP6Route *r_src, *r_dst;
has = nm_ip6_config_iter_ip6_route_next (&ipconf_iter_src, &r_src);
if (has != nm_ip6_config_iter_ip6_route_next (&ipconf_iter_dst, &r_dst)) {
are_equal = FALSE; are_equal = FALSE;
if (!routes_are_duplicate (src_route, dst_route, TRUE)) { has_relevant_changes = TRUE;
break;
}
if (!has)
break;
if (nm_platform_ip6_route_cmp (r_src, r_dst) != 0) {
are_equal = FALSE;
if (!nm_ip_config_obj_id_equal_ip6_route (r_src, r_dst)) {
has_relevant_changes = TRUE; has_relevant_changes = TRUE;
break; break;
} }
} }
} }
} else
has_relevant_changes = TRUE;
if (!are_equal) { if (!are_equal) {
nm_ip6_config_reset_routes (dst); const NMPlatformIP6Route *r_src;
for (i = 0; i < num; i++)
nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
has_minor_changes = TRUE; has_minor_changes = TRUE;
nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes);
nm_dedup_multi_iter_rewind (&ipconf_iter_src);
while (nm_ip6_config_iter_ip6_route_next (&ipconf_iter_src, &r_src)) {
nm_dedup_multi_index_add (dst_priv->multi_idx,
&dst_priv->idx_ip6_routes,
NMP_OBJECT_UP_CAST (r_src),
NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
NULL,
NULL);
}
nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, FALSE);
} }
/* nameservers */ /* nameservers */
@@ -1252,6 +1327,8 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail)
const struct in6_addr *tmp; const struct in6_addr *tmp;
guint32 i; guint32 i;
const char *str; const char *str;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *route;
g_return_if_fail (config != NULL); g_return_if_fail (config != NULL);
@@ -1277,8 +1354,8 @@ nm_ip6_config_dump (const NMIP6Config *config, const char *detail)
} }
/* routes */ /* routes */
for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, config, &route)
g_message (" rt: %s", nm_platform_ip6_route_to_string (nm_ip6_config_get_route (config, i), NULL, 0)); g_message (" rt: %s", nm_platform_ip6_route_to_string (route, NULL, 0));
/* domains */ /* domains */
for (i = 0; i < nm_ip6_config_get_num_domains (config); i++) for (i = 0; i < nm_ip6_config_get_num_domains (config); i++)
@@ -1524,13 +1601,84 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
{ {
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
if (priv->routes->len != 0) { if (nm_dedup_multi_index_remove_idx (priv->multi_idx,
g_array_set_size (priv->routes, 0); &priv->idx_ip6_routes) > 0) {
_notify (config, PROP_ROUTE_DATA); _notify (config, PROP_ROUTE_DATA);
_notify (config, PROP_ROUTES); _notify (config, PROP_ROUTES);
} }
} }
static void
_add_route (NMIP6Config *config, const NMPObject *o_new, const NMPlatformIP6Route *new)
{
NMIP6ConfigPrivate *priv;
NMPObject o_new_storage;
nm_auto_nmpobj const NMPObject *obj_old = NULL;
nm_assert (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
nm_assert (priv->ifindex > 0);
/* we go through extra lengths to accept a full o_new object. That one,
* can be reused by increasing the ref-count. */
if (!o_new) {
nm_assert (new);
nm_assert (new->plen > 0 && new->plen <= 128);
nmp_object_stackinit (&o_new_storage, NMP_OBJECT_TYPE_IP6_ROUTE,
(const NMPlatformObject *) new);
o_new_storage.ip6_route.ifindex = priv->ifindex;
o_new = &o_new_storage;
} else {
nm_assert (!new);
nm_assert (NMP_OBJECT_GET_TYPE (o_new) == NMP_OBJECT_TYPE_IP6_ROUTE);
nm_assert (o_new->ip6_route.plen > 0 && o_new->ip6_route.plen <= 128);
if (o_new->ip6_route.ifindex != priv->ifindex) {
nmp_object_stackinit (&o_new_storage, NMP_OBJECT_TYPE_IP6_ROUTE, &o_new->object);
o_new_storage.ip6_route.ifindex = priv->ifindex;
o_new = &o_new_storage;
}
}
if (!nm_dedup_multi_index_add (priv->multi_idx,
&priv->idx_ip6_routes,
o_new,
NM_DEDUP_MULTI_IDX_MODE_APPEND,
NULL,
&obj_old))
return;
if (obj_old) {
NMIPConfigSource old_source;
old_source = obj_old->ip_route.rt_source;
/* 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 (o_new->ip_route.rt_source < old_source) {
if (o_new != &o_new_storage) {
nmp_object_stackinit (&o_new_storage, NMP_OBJECT_TYPE_IP6_ROUTE,
&o_new->object);
o_new = &o_new_storage;
}
o_new_storage.ip_route.rt_source = old_source;
if (!nm_dedup_multi_index_add (priv->multi_idx,
&priv->idx_ip6_routes,
o_new,
NM_DEDUP_MULTI_IDX_MODE_APPEND,
NULL,
NULL))
nm_assert_not_reached ();
}
}
_notify (config, PROP_ROUTE_DATA);
_notify (config, PROP_ROUTES);
}
/** /**
* nm_ip6_config_add_route: * nm_ip6_config_add_route:
* @config: the #NMIP6Config * @config: the #NMIP6Config
@@ -1544,76 +1692,70 @@ nm_ip6_config_reset_routes (NMIP6Config *config)
void void
nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new) nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *new)
{ {
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); g_return_if_fail (config);
NMIPConfigSource old_source; g_return_if_fail (new);
int i;
g_return_if_fail (new != NULL);
g_return_if_fail (new->plen > 0 && new->plen <= 128); g_return_if_fail (new->plen > 0 && new->plen <= 128);
g_return_if_fail (priv->ifindex > 0); g_return_if_fail (NM_IP6_CONFIG_GET_PRIVATE (config)->ifindex > 0);
for (i = 0; i < priv->routes->len; i++ ) { _add_route (config, NULL, new);
NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (routes_are_duplicate (item, new, FALSE)) {
if (nm_platform_ip6_route_cmp (item, new) == 0)
return;
old_source = item->rt_source;
*item = *new;
/* Restore highest priority source */
item->rt_source = MAX (old_source, new->rt_source);
item->ifindex = priv->ifindex;
goto NOTIFY;
}
}
g_array_append_val (priv->routes, *new);
g_array_index (priv->routes, NMPlatformIP6Route, priv->routes->len - 1).ifindex = priv->ifindex;
NOTIFY:
_notify (config, PROP_ROUTE_DATA);
_notify (config, PROP_ROUTES);
} }
void void
nm_ip6_config_del_route (NMIP6Config *config, guint i) _nmtst_ip6_config_del_route (NMIP6Config *self, guint i)
{ {
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
const NMPlatformIP6Route *r;
g_return_if_fail (i < priv->routes->len); r = _nmtst_ip6_config_get_route (self, i);
g_return_if_fail (r);
g_array_remove_index (priv->routes, i); if (nm_dedup_multi_index_remove_obj (priv->multi_idx,
_notify (config, PROP_ROUTE_DATA); &priv->idx_ip6_routes,
_notify (config, PROP_ROUTES); NMP_OBJECT_UP_CAST (r)) != 1)
g_return_if_reached ();
_notify (self, PROP_ROUTE_DATA);
_notify (self, PROP_ROUTES);
} }
guint guint
nm_ip6_config_get_num_routes (const NMIP6Config *config) nm_ip6_config_get_num_routes (const NMIP6Config *self)
{ {
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); const NMDedupMultiHeadEntry *head_entry;
return priv->routes->len; head_entry = _idx_ip6_routes (self);
nm_assert ((head_entry ? head_entry->len : 0) == c_list_length (&head_entry->lst_entries_head));
return head_entry ? head_entry->len : 0;
} }
const NMPlatformIP6Route * const NMPlatformIP6Route *
nm_ip6_config_get_route (const NMIP6Config *config, guint i) _nmtst_ip6_config_get_route (const NMIP6Config *self, guint i)
{ {
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); const NMDedupMultiHeadEntry *head_entry;
CList *iter;
guint j;
return &g_array_index (priv->routes, NMPlatformIP6Route, i); head_entry = _idx_ip6_routes (self);
if (head_entry) {
j = 0;
c_list_for_each (iter, &head_entry->lst_entries_head) {
if (i == j)
return _entry_iter_get_ip6_route (iter);
j++;
}
}
g_return_val_if_reached (NULL);
} }
const NMPlatformIP6Route * const NMPlatformIP6Route *
nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host) nm_ip6_config_get_direct_route_for_host (const NMIP6Config *self, const struct in6_addr *host)
{ {
const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); const NMPlatformIP6Route *best_route = NULL;
guint i; const NMPlatformIP6Route *item;
NMPlatformIP6Route *best_route = NULL; NMDedupMultiIter ipconf_iter;
g_return_val_if_fail (host && !IN6_IS_ADDR_UNSPECIFIED (host), NULL); g_return_val_if_fail (host && !IN6_IS_ADDR_UNSPECIFIED (host), NULL);
for (i = 0; i < priv->routes->len; i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, self, &item) {
NMPlatformIP6Route *item = &g_array_index (priv->routes, NMPlatformIP6Route, i);
if (!IN6_IS_ADDR_UNSPECIFIED (&item->gateway)) if (!IN6_IS_ADDR_UNSPECIFIED (&item->gateway))
continue; continue;
@@ -1629,7 +1771,6 @@ nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct
best_route = item; best_route = item;
} }
return best_route; return best_route;
} }
@@ -1963,6 +2104,8 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only
{ {
guint32 i; guint32 i;
const char *s; const char *s;
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *route;
g_return_if_fail (config); g_return_if_fail (config);
g_return_if_fail (sum); g_return_if_fail (sum);
@@ -1977,9 +2120,7 @@ nm_ip6_config_hash (const NMIP6Config *config, GChecksum *sum, gboolean dns_only
hash_u32 (sum, address->plen); hash_u32 (sum, address->plen);
} }
for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, config, &route) {
const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i);
hash_in6addr (sum, &route->network); hash_in6addr (sum, &route->network);
hash_u32 (sum, route->plen); hash_u32 (sum, route->plen);
hash_in6addr (sum, &route->gateway); hash_in6addr (sum, &route->gateway);
@@ -2074,6 +2215,9 @@ get_property (GObject *object, guint prop_id,
{ {
NMIP6Config *config = NM_IP6_CONFIG (object); NMIP6Config *config = NM_IP6_CONFIG (object);
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
NMDedupMultiIter ipconf_iter;
const NMPlatformIP6Route *route;
GVariantBuilder array_builder, addr_builder, route_builder;
switch (prop_id) { switch (prop_id) {
case PROP_IFINDEX: case PROP_IFINDEX:
@@ -2082,7 +2226,6 @@ get_property (GObject *object, guint prop_id,
case PROP_ADDRESS_DATA: case PROP_ADDRESS_DATA:
case PROP_ADDRESSES: case PROP_ADDRESSES:
{ {
GVariantBuilder array_builder, addr_builder;
gs_unref_array GArray *new = NULL; gs_unref_array GArray *new = NULL;
const struct in6_addr *gateway; const struct in6_addr *gateway;
guint naddr, i; guint naddr, i;
@@ -2144,14 +2287,8 @@ return_cached:
break; break;
case PROP_ROUTE_DATA: case PROP_ROUTE_DATA:
{ {
GVariantBuilder array_builder, route_builder;
guint nroutes = nm_ip6_config_get_num_routes (config);
int i;
g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}"));
for (i = 0; i < nroutes; i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, config, &route) {
const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i);
g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&route_builder, "{sv}", g_variant_builder_add (&route_builder, "{sv}",
"dest", "dest",
@@ -2177,14 +2314,8 @@ return_cached:
break; break;
case PROP_ROUTES: case PROP_ROUTES:
{ {
GVariantBuilder array_builder;
int nroutes = nm_ip6_config_get_num_routes (config);
int i;
g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a(ayuayu)")); g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a(ayuayu)"));
for (i = 0; i < nroutes; i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, config, &route) {
const NMPlatformIP6Route *route = nm_ip6_config_get_route (config, i);
/* legacy versions of nm_ip6_route_set_prefix() in libnm-util assert that the /* legacy versions of nm_ip6_route_set_prefix() in libnm-util assert that the
* plen is positive. Skip the default routes not to break older clients. */ * plen is positive. Skip the default routes not to break older clients. */
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route))
@@ -2263,8 +2394,10 @@ nm_ip6_config_init (NMIP6Config *config)
{ {
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (config);
nm_ip_config_dedup_multi_idx_type_init ((NMIPConfigDedupMultiIdxType *) &priv->idx_ip6_routes,
NMP_OBJECT_TYPE_IP6_ROUTE);
priv->addresses = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Address)); priv->addresses = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Address));
priv->routes = g_array_new (FALSE, TRUE, sizeof (NMPlatformIP6Route));
priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr)); priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr));
priv->domains = g_ptr_array_new_with_free_func (g_free); priv->domains = g_ptr_array_new_with_free_func (g_free);
priv->searches = g_ptr_array_new_with_free_func (g_free); priv->searches = g_ptr_array_new_with_free_func (g_free);
@@ -2301,8 +2434,9 @@ finalize (GObject *object)
NMIP6Config *self = NM_IP6_CONFIG (object); NMIP6Config *self = NM_IP6_CONFIG (object);
NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self);
nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip6_routes);
g_array_unref (priv->addresses); g_array_unref (priv->addresses);
g_array_unref (priv->routes);
g_array_unref (priv->nameservers); g_array_unref (priv->nameservers);
g_ptr_array_unref (priv->domains); g_ptr_array_unref (priv->domains);
g_ptr_array_unref (priv->searches); g_ptr_array_unref (priv->searches);

View File

@@ -26,6 +26,20 @@
#include "nm-exported-object.h" #include "nm-exported-object.h"
#include "nm-setting-ip6-config.h" #include "nm-setting-ip6-config.h"
#include "nm-utils/nm-dedup-multi.h"
/*****************************************************************************/
void nm_ip6_config_iter_ip6_route_init (NMDedupMultiIter *iter, const NMIP6Config *self);
gboolean nm_ip6_config_iter_ip6_route_next (NMDedupMultiIter *iter, const NMPlatformIP6Route **out_route);
#define nm_ip6_config_iter_ip6_route_for_each(iter, self, route) \
for (nm_ip6_config_iter_ip6_route_init ((iter), (self)); \
nm_ip6_config_iter_ip6_route_next ((iter), (route)); \
)
/*****************************************************************************/
#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ()) #define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type ())
#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config)) #define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
#define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass)) #define NM_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
@@ -101,9 +115,9 @@ gboolean nm_ip6_config_has_any_dad_pending (const NMIP6Config *self,
void nm_ip6_config_reset_routes (NMIP6Config *config); void nm_ip6_config_reset_routes (NMIP6Config *config);
void nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *route); void nm_ip6_config_add_route (NMIP6Config *config, const NMPlatformIP6Route *route);
void nm_ip6_config_del_route (NMIP6Config *config, guint i); void _nmtst_ip6_config_del_route (NMIP6Config *config, guint i);
guint nm_ip6_config_get_num_routes (const NMIP6Config *config); guint nm_ip6_config_get_num_routes (const NMIP6Config *config);
const NMPlatformIP6Route *nm_ip6_config_get_route (const NMIP6Config *config, guint i); const NMPlatformIP6Route *_nmtst_ip6_config_get_route (const NMIP6Config *config, guint i);
const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host); const NMPlatformIP6Route *nm_ip6_config_get_direct_route_for_host (const NMIP6Config *config, const struct in6_addr *host);
const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host (const NMIP6Config *config, const struct in6_addr *host); const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host (const NMIP6Config *config, const struct in6_addr *host);

View File

@@ -202,8 +202,10 @@ get_ip4_domains (GPtrArray *domains, NMIP4Config *ip4)
static void static void
get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6) get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6)
{ {
NMDedupMultiIter ipconf_iter;
char *cidr; char *cidr;
int i; const NMPlatformIP6Route *routes;
guint i;
/* Extract searches */ /* Extract searches */
for (i = 0; i < nm_ip6_config_get_num_searches (ip6); i++) for (i = 0; i < nm_ip6_config_get_num_searches (ip6); i++)
@@ -223,9 +225,7 @@ get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6)
g_ptr_array_add (domains, cidr); g_ptr_array_add (domains, cidr);
} }
for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) { nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &routes) {
const NMPlatformIP6Route *routes = nm_ip6_config_get_route (ip6, i);
cidr = g_strdup_printf ("%s/%u", cidr = g_strdup_printf ("%s/%u",
nm_utils_inet6_ntop (&routes->network, NULL), nm_utils_inet6_ntop (&routes->network, NULL),
routes->plen); routes->plen);

View File

@@ -98,7 +98,7 @@ test_subtract (void)
g_assert (nm_ip6_config_get_gateway (dst) == NULL); g_assert (nm_ip6_config_get_gateway (dst) == NULL);
g_assert_cmpuint (nm_ip6_config_get_num_routes (dst), ==, 1); g_assert_cmpuint (nm_ip6_config_get_num_routes (dst), ==, 1);
test_route = nm_ip6_config_get_route (dst, 0); test_route = _nmtst_ip6_config_get_route (dst, 0);
g_assert (test_route != NULL); g_assert (test_route != NULL);
tmp = *nmtst_inet6_from_string (expected_route_dest); tmp = *nmtst_inet6_from_string (expected_route_dest);
@@ -207,27 +207,27 @@ test_add_route_with_source (void)
route.rt_source = NM_IP_CONFIG_SOURCE_USER; route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip6_config_add_route (a, &route); nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0); test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
route.rt_source = NM_IP_CONFIG_SOURCE_VPN; route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_ip6_config_add_route (a, &route); nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0); test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
/* Test that a lower priority address source is overwritten */ /* Test that a lower priority address source is overwritten */
nm_ip6_config_del_route (a, 0); _nmtst_ip6_config_del_route (a, 0);
route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL; route.rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
nm_ip6_config_add_route (a, &route); nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0); test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL); g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_KERNEL);
route.rt_source = NM_IP_CONFIG_SOURCE_USER; route.rt_source = NM_IP_CONFIG_SOURCE_USER;
nm_ip6_config_add_route (a, &route); nm_ip6_config_add_route (a, &route);
test_route = nm_ip6_config_get_route (a, 0); test_route = _nmtst_ip6_config_get_route (a, 0);
g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER); g_assert_cmpint (test_route->rt_source, ==, NM_IP_CONFIG_SOURCE_USER);
g_object_unref (a); g_object_unref (a);

View File

@@ -992,6 +992,8 @@ print_vpn_config (NMVpnConnection *self)
_LOGI ("Data: No IPv4 configuration"); _LOGI ("Data: No IPv4 configuration");
if (priv->ip6_config) { if (priv->ip6_config) {
const NMPlatformIP6Route *route;
_LOGI ("Data: IPv6 configuration:"); _LOGI ("Data: IPv6 configuration:");
address6 = nm_ip6_config_get_address (priv->ip6_config, 0); address6 = nm_ip6_config_get_address (priv->ip6_config, 0);
@@ -1003,10 +1005,7 @@ print_vpn_config (NMVpnConnection *self)
_LOGI ("Data: Internal Point-to-Point Address: %s", nm_utils_inet6_ntop (&address6->peer_address, NULL)); _LOGI ("Data: Internal Point-to-Point Address: %s", nm_utils_inet6_ntop (&address6->peer_address, NULL));
_LOGI ("Data: Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config)); _LOGI ("Data: Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config));
num = nm_ip6_config_get_num_routes (priv->ip6_config); nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route) {
for (i = 0; i < num; i++) {
const NMPlatformIP6Route *route = nm_ip6_config_get_route (priv->ip6_config, i);
_LOGI ("Data: Static Route: %s/%d Next Hop: %s", _LOGI ("Data: Static Route: %s/%d Next Hop: %s",
nm_utils_inet6_ntop (&route->network, NULL), nm_utils_inet6_ntop (&route->network, NULL),
route->plen, route->plen,
@@ -1578,7 +1577,6 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
const char *str; const char *str;
GVariant *v; GVariant *v;
gboolean b; gboolean b;
guint i, n;
int ip_ifindex; int ip_ifindex;
g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT)); g_return_if_fail (dict && g_variant_is_of_type (dict, G_VARIANT_TYPE_VARDICT));
@@ -1669,9 +1667,11 @@ nm_vpn_connection_ip6_config_get (NMVpnConnection *self, GVariant *dict)
if ( g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES, "b", &b) if ( g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES, "b", &b)
&& b) { && b) {
if (priv->ip6_config) { if (priv->ip6_config) {
n = nm_ip6_config_get_num_routes (priv->ip6_config); NMDedupMultiIter ipconf_iter;
for (i = 0; i < n; i++) const NMPlatformIP6Route *route;
nm_ip6_config_add_route (config, nm_ip6_config_get_route (priv->ip6_config, i));
nm_ip6_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route)
nm_ip6_config_add_route (config, route);
} }
} else if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayu)", &iter)) { } else if (g_variant_lookup (dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayu)", &iter)) {
GVariant *dest, *next_hop; GVariant *dest, *next_hop;