diff options
-rw-r--r-- | src/dns/nm-dns-dnsmasq.c | 12 | ||||
-rw-r--r-- | src/nm-dispatcher.c | 4 | ||||
-rw-r--r-- | src/nm-ip4-config.c | 257 | ||||
-rw-r--r-- | src/nm-ip4-config.h | 27 | ||||
-rw-r--r-- | src/nm-ip6-config.c | 196 | ||||
-rw-r--r-- | src/nm-ip6-config.h | 8 | ||||
-rw-r--r-- | src/nm-pacrunner-manager.c | 4 |
7 files changed, 439 insertions, 69 deletions
diff --git a/src/dns/nm-dns-dnsmasq.c b/src/dns/nm-dns-dnsmasq.c index cb311dffd..3ec1fd2de 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/dns/nm-dns-dnsmasq.c @@ -91,8 +91,10 @@ get_ip4_rdns_domains (NMIP4Config *ip4) nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address) nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains); - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) - nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains); + nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + nm_utils_get_reverse_dns_domains_ip4 (route->network, route->plen, domains); + } /* Terminating NULL so we can use g_strfreev() to free it */ g_ptr_array_add (domains, NULL); @@ -119,8 +121,10 @@ get_ip6_rdns_domains (NMIP6Config *ip6) nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address) nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) - nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); + nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); + } /* Terminating NULL so we can use g_strfreev() to free it */ g_ptr_array_add (domains, NULL); diff --git a/src/nm-dispatcher.c b/src/nm-dispatcher.c index cb7bb3c5a..b5b11812e 100644 --- a/src/nm-dispatcher.c +++ b/src/nm-dispatcher.c @@ -166,6 +166,8 @@ dump_ip4_to_props (NMIP4Config *ip4, GVariantBuilder *builder) /* Static routes */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("aau")); nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + continue; array[0] = route->network; array[1] = route->plen; array[2] = route->gateway; @@ -235,6 +237,8 @@ dump_ip6_to_props (NMIP6Config *ip6, GVariantBuilder *builder) /* Static routes */ g_variant_builder_init (&int_builder, G_VARIANT_TYPE ("a(ayuayu)")); nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) + continue; ip = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &route->network, sizeof (struct in6_addr), 1); diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 9037c2d6f..cf8435414 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -377,6 +377,7 @@ typedef struct { GVariant *route_data_variant; GVariant *routes_variant; NMDedupMultiIndex *multi_idx; + const NMPObject *best_default_route; union { NMIPConfigDedupMultiIdxType idx_ip4_addresses_; NMDedupMultiIdxType idx_ip4_addresses; @@ -471,6 +472,95 @@ nm_ip_config_iter_ip4_route_init (NMDedupMultiIter *ipconf_iter, const NMIP4Conf /*****************************************************************************/ +const NMPObject * +_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp) +{ + int addr_family; + int c; + guint metric_cur, metric_cmp; + + nm_assert ( !obj_cur + || NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cur), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); + nm_assert ( !obj_cmp + || ( !obj_cur + && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_cmp), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) + || NMP_OBJECT_GET_TYPE (obj_cur) == NMP_OBJECT_GET_TYPE (obj_cmp)); + nm_assert ( !obj_cur + || nm_ip_config_best_default_route_is (obj_cur)); + + /* assumes that @obj_cur is already the best default route (or NULL). It checks whether + * @obj_cmp is also a default route and returns the best of both. */ + if ( obj_cmp + && nm_ip_config_best_default_route_is (obj_cmp)) { + if (!obj_cur) + return obj_cmp; + + addr_family = NMP_OBJECT_GET_CLASS (obj_cmp)->addr_family; + metric_cur = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cur)->metric); + metric_cmp = nm_utils_ip_route_metric_normalize (addr_family, NMP_OBJECT_CAST_IP_ROUTE (obj_cmp)->metric); + + if (metric_cmp < metric_cur) + return obj_cmp; + + if (metric_cmp == metric_cur) { + /* Routes have the same metric. We still want to deterministically + * prefer one or the other. It's important to consistently choose one + * or the other, so that the order doesn't matter how routes are added + * (and merged). */ + c = nmp_object_cmp (obj_cur, obj_cmp); + if (c != 0) + return c < 0 ? obj_cur : obj_cmp; + + /* as last resort, compare pointers. */ + if (obj_cmp < obj_cur) + return obj_cmp; + } + } + return obj_cur; +} + +gboolean +_nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate) +{ + if (new_candidate == *best_default_route) + return FALSE; + nmp_object_ref (new_candidate); + nm_clear_nmp_object (best_default_route); + *best_default_route = new_candidate; + return TRUE; +} + +gboolean +_nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate) +{ + new_candidate = _nm_ip_config_best_default_route_find_better (*best_default_route, + new_candidate); + return _nm_ip_config_best_default_route_set (best_default_route, new_candidate); +} + +const NMPObject * +nm_ip4_config_best_default_route_get (const NMIP4Config *self) +{ + g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL); + + return NM_IP4_CONFIG_GET_PRIVATE (self)->best_default_route; +} + +const NMPObject * +_nm_ip4_config_best_default_route_find (const NMIP4Config *self) +{ + NMDedupMultiIter ipconf_iter; + const NMPObject *new_best_default_route = NULL; + + nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) { + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, + ipconf_iter.current->obj); + } + return new_best_default_route; +} + +/*****************************************************************************/ + static void _notify_addresses (NMIP4Config *self) { @@ -487,6 +577,7 @@ _notify_routes (NMIP4Config *self) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + nm_assert (priv->best_default_route == _nm_ip4_config_best_default_route_find (self)); nm_clear_g_variant (&priv->route_data_variant); nm_clear_g_variant (&priv->routes_variant); _notify (self, PROP_ROUTE_DATA); @@ -1056,8 +1147,7 @@ nm_ip4_config_create_setting (const NMIP4Config *self) nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) { NMIPRoute *s_route; - /* Ignore default route. */ - if (!route->plen) + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) continue; /* Ignore routes provided by external sources */ @@ -1133,10 +1223,8 @@ nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src, NMIPConfigMergeFl /* routes */ if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) { - const NMPlatformIP4Route *route; - - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &route) - _add_route (dst, NMP_OBJECT_UP_CAST (route), NULL, NULL); + nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, NULL) + _add_route (dst, ipconf_iter.current->obj, NULL, NULL); } if (dst_priv->route_metric == -1) @@ -1310,6 +1398,7 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) const NMPlatformIP4Route *r; NMDedupMultiIter ipconf_iter; gboolean changed; + gboolean changed_default_route; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); @@ -1349,12 +1438,24 @@ nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src) /* routes */ changed = FALSE; + changed_default_route = FALSE; nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) { + nm_auto_nmpobj const NMPObject *obj_old = NULL; + if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx, &dst_priv->idx_ip4_routes, NMP_OBJECT_UP_CAST (r), - NULL)) + (gconstpointer *) &obj_old)) { + if (dst_priv->best_default_route == obj_old) { + nm_clear_nmp_object (&dst_priv->best_default_route); + changed_default_route = TRUE; + } changed = TRUE; + } + } + if (changed_default_route) { + _nm_ip_config_best_default_route_set (&dst_priv->best_default_route, + _nm_ip4_config_best_default_route_find (dst)); } if (changed) _notify_routes (dst); @@ -1421,16 +1522,17 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) NMDedupMultiIter ipconf_iter; const NMPlatformIP4Address *a; const NMPlatformIP4Route *r; + const NMPObject *new_best_default_route; gboolean changed; g_return_if_fail (src); g_return_if_fail (dst); - g_object_freeze_notify (G_OBJECT (dst)); - dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst); src_priv = NM_IP4_CONFIG_GET_PRIVATE (src); + g_object_freeze_notify (G_OBJECT (dst)); + /* addresses */ changed = FALSE; nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) { @@ -1459,17 +1561,24 @@ nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src) /* routes */ changed = FALSE; + new_best_default_route = NULL; nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) { + const NMPObject *o = NMP_OBJECT_UP_CAST (r); + if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, &src_priv->idx_ip4_routes, - NMP_OBJECT_UP_CAST (r))) + o)) { + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o); continue; + } if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); changed = TRUE; } + if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) + nm_assert (changed); if (changed) _notify_routes (dst); @@ -1509,6 +1618,7 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev const NMIP4ConfigPrivate *src_priv; NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst; const NMDedupMultiHeadEntry *head_entry_src; + const NMPObject *new_best_default_route; g_return_val_if_fail (src != NULL, FALSE); g_return_val_if_fail (dst != NULL, FALSE); @@ -1627,19 +1737,25 @@ nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relev } if (!are_equal) { has_minor_changes = TRUE; + new_best_default_route = NULL; nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes); nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) { + const NMPObject *o = ipconf_iter_src.current->obj; + const NMPObject *obj_new; + _nm_ip_config_add_obj (dst_priv->multi_idx, &dst_priv->idx_ip4_routes_, dst_priv->ifindex, - ipconf_iter_src.current->obj, + o, NULL, FALSE, TRUE, NULL, - NULL); + &obj_new); + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new); } nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip4_routes, FALSE); + _nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route); _notify_routes (dst); } @@ -2028,18 +2144,12 @@ nm_ip4_config_add_address (NMIP4Config *self, const NMPlatformIP4Address *new) void _nmtst_ip4_config_del_address (NMIP4Config *self, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); const NMPlatformIP4Address *a; a = _nmtst_ip4_config_get_address (self, i); - g_return_if_fail (a); - - if (nm_dedup_multi_index_remove_obj (priv->multi_idx, - &priv->idx_ip4_addresses, - NMP_OBJECT_UP_CAST (a), - NULL) != 1) - g_return_if_reached (); - _notify_addresses (self); + if (!nm_ip4_config_nmpobj_remove (self, + NMP_OBJECT_UP_CAST (a))) + g_assert_not_reached (); } guint @@ -2121,8 +2231,10 @@ nm_ip4_config_reset_routes (NMIP4Config *self) NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); if (nm_dedup_multi_index_remove_idx (priv->multi_idx, - &priv->idx_ip4_routes) > 0) + &priv->idx_ip4_routes) > 0) { + nm_clear_nmp_object (&priv->best_default_route); _notify_routes (self); + } } static void @@ -2132,6 +2244,7 @@ _add_route (NMIP4Config *self, const NMPObject **out_obj_new) { NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + nm_auto_nmpobj const NMPObject *obj_old = NULL; const NMPObject *obj_new_2; nm_assert ((!new) != (!obj_new)); @@ -2145,8 +2258,12 @@ _add_route (NMIP4Config *self, (const NMPlatformObject *) new, TRUE, FALSE, - NULL, + &obj_old, &obj_new_2)) { + if ( priv->best_default_route == obj_old + && obj_old != obj_new_2) + nm_clear_nmp_object (&priv->best_default_route); + _nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2); NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2)); _notify_routes (self); } else @@ -2172,7 +2289,7 @@ nm_ip4_config_add_route (NMIP4Config *self, { g_return_if_fail (self); g_return_if_fail (new); - g_return_if_fail (new->plen > 0 && new->plen <= 32); + g_return_if_fail (new->plen <= 32); g_return_if_fail (NM_IP4_CONFIG_GET_PRIVATE (self)->ifindex > 0); _add_route (self, NULL, new, out_obj_new); @@ -2181,18 +2298,12 @@ nm_ip4_config_add_route (NMIP4Config *self, void _nmtst_ip4_config_del_route (NMIP4Config *self, guint i) { - NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); const NMPlatformIP4Route *r; r = _nmtst_ip4_config_get_route (self, i); - g_return_if_fail (r); - - if (nm_dedup_multi_index_remove_obj (priv->multi_idx, - &priv->idx_ip4_routes, - NMP_OBJECT_UP_CAST (r), - NULL) != 1) - g_return_if_reached (); - _notify_routes (self); + if (!nm_ip4_config_nmpobj_remove (self, + NMP_OBJECT_UP_CAST (r))) + g_assert_not_reached (); } guint @@ -2701,6 +2812,84 @@ nm_ip4_config_get_metered (const NMIP4Config *self) /*****************************************************************************/ +const NMPObject * +nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, const NMPObject *needle) +{ + const NMIP4ConfigPrivate *priv; + const NMDedupMultiIdxType *idx_type; + + g_return_val_if_fail (NM_IS_IP4_CONFIG (self), NULL); + + priv = NM_IP4_CONFIG_GET_PRIVATE (self); + switch (NMP_OBJECT_GET_TYPE (needle)) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + idx_type = &priv->idx_ip4_addresses; + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + idx_type = &priv->idx_ip4_routes; + break; + default: + g_return_val_if_reached (NULL); + } + + return nm_dedup_multi_entry_get_obj (nm_dedup_multi_index_lookup_obj (priv->multi_idx, + idx_type, + needle)); +} + +gboolean +nm_ip4_config_nmpobj_remove (NMIP4Config *self, + const NMPObject *needle) +{ + NMIP4ConfigPrivate *priv; + NMDedupMultiIdxType *idx_type; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + guint n; + + g_return_val_if_fail (NM_IS_IP4_CONFIG (self), FALSE); + + priv = NM_IP4_CONFIG_GET_PRIVATE (self); + switch (NMP_OBJECT_GET_TYPE (needle)) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + idx_type = &priv->idx_ip4_addresses; + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + idx_type = &priv->idx_ip4_routes; + break; + default: + g_return_val_if_reached (FALSE); + } + + n = nm_dedup_multi_index_remove_obj (priv->multi_idx, + idx_type, + needle, + (gconstpointer *) &obj_old); + if (n != 1) { + nm_assert (n == 0); + return FALSE; + } + + nm_assert (NMP_OBJECT_GET_TYPE (obj_old) == NMP_OBJECT_GET_TYPE (needle)); + + switch (NMP_OBJECT_GET_TYPE (obj_old)) { + case NMP_OBJECT_TYPE_IP4_ADDRESS: + _notify_addresses (self); + break; + case NMP_OBJECT_TYPE_IP4_ROUTE: + if (priv->best_default_route == obj_old) { + _nm_ip_config_best_default_route_set (&priv->best_default_route, + _nm_ip4_config_best_default_route_find (self)); + } + _notify_routes (self); + break; + default: + nm_assert_not_reached (); + } + return TRUE; +} + +/*****************************************************************************/ + static inline void hash_u32 (GChecksum *sum, guint32 n) { @@ -3056,6 +3245,8 @@ finalize (GObject *object) NMIP4Config *self = NM_IP4_CONFIG (object); NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (self); + nm_clear_nmp_object (&priv->best_default_route); + nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_addresses); nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip4_routes); diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 1113c9928..7db858b7b 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -75,6 +75,25 @@ nm_ip_config_iter_ip4_route_next (NMDedupMultiIter *ipconf_iter, const NMPlatfor /*****************************************************************************/ +static inline gboolean +nm_ip_config_best_default_route_is (const NMPObject *obj) +{ + const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE (obj); + + /* return whether @obj is considered a default-route, that is, a route + * as added by NetworkManager. E.g. if the route is not in the main-table, + * it's considered just like a regular route. */ + return r + && !r->table_coerced + && NM_PLATFORM_IP_ROUTE_IS_DEFAULT (r); +} + +const NMPObject *_nm_ip_config_best_default_route_find_better (const NMPObject *obj_cur, const NMPObject *obj_cmp); +gboolean _nm_ip_config_best_default_route_set (const NMPObject **best_default_route, const NMPObject *new_candidate); +gboolean _nm_ip_config_best_default_route_merge (const NMPObject **best_default_route, const NMPObject *new_candidate); + +/*****************************************************************************/ + gboolean nm_ip_config_obj_id_equal_ip4_address (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b); gboolean nm_ip_config_obj_id_equal_ip6_address (const NMPlatformIP6Address *a, @@ -163,6 +182,9 @@ gboolean nm_ip4_config_has_gateway (const NMIP4Config *self); guint32 nm_ip4_config_get_gateway (const NMIP4Config *self); gint64 nm_ip4_config_get_route_metric (const NMIP4Config *self); +const NMPObject *nm_ip4_config_best_default_route_get (const NMIP4Config *self); +const NMPObject *_nm_ip4_config_best_default_route_find (const NMIP4Config *self); + const NMDedupMultiHeadEntry *nm_ip4_config_lookup_addresses (const NMIP4Config *self); void nm_ip4_config_reset_addresses (NMIP4Config *self); void nm_ip4_config_add_address (NMIP4Config *self, const NMPlatformIP4Address *address); @@ -234,6 +256,11 @@ NMIPConfigSource nm_ip4_config_get_mtu_source (const NMIP4Config *self); void nm_ip4_config_set_metered (NMIP4Config *self, gboolean metered); gboolean nm_ip4_config_get_metered (const NMIP4Config *self); +const NMPObject *nm_ip4_config_nmpobj_lookup (const NMIP4Config *self, + const NMPObject *needle); +gboolean nm_ip4_config_nmpobj_remove (NMIP4Config *self, + const NMPObject *needle); + void nm_ip4_config_hash (const NMIP4Config *self, GChecksum *sum, gboolean dns_only); gboolean nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b); diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index 641e73434..0aad49d54 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -72,6 +72,7 @@ typedef struct { GVariant *route_data_variant; GVariant *routes_variant; NMDedupMultiIndex *multi_idx; + const NMPObject *best_default_route; union { NMIPConfigDedupMultiIdxType idx_ip6_addresses_; NMDedupMultiIdxType idx_ip6_addresses; @@ -177,6 +178,29 @@ nm_ip_config_iter_ip6_route_init (NMDedupMultiIter *ipconf_iter, const NMIP6Conf /*****************************************************************************/ +const NMPObject * +nm_ip6_config_best_default_route_get (const NMIP6Config *self) +{ + g_return_val_if_fail (NM_IS_IP6_CONFIG (self), NULL); + + return NM_IP6_CONFIG_GET_PRIVATE (self)->best_default_route; +} + +const NMPObject * +_nm_ip6_config_best_default_route_find (const NMIP6Config *self) +{ + NMDedupMultiIter ipconf_iter; + const NMPObject *new_best_default_route = NULL; + + nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, NULL) { + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, + ipconf_iter.current->obj); + } + return new_best_default_route; +} + +/*****************************************************************************/ + static void _notify_addresses (NMIP6Config *self) { @@ -193,6 +217,7 @@ _notify_routes (NMIP6Config *self) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + nm_assert (priv->best_default_route == _nm_ip6_config_best_default_route_find (self)); nm_clear_g_variant (&priv->route_data_variant); nm_clear_g_variant (&priv->routes_variant); _notify (self, PROP_ROUTE_DATA); @@ -781,8 +806,7 @@ nm_ip6_config_create_setting (const NMIP6Config *self) if (IN6_IS_ADDR_LINKLOCAL (&route->network)) continue; - /* Ignore default route. */ - if (!route->plen) + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (route)) continue; /* Ignore routes provided by external sources */ @@ -857,10 +881,8 @@ nm_ip6_config_merge (NMIP6Config *dst, const NMIP6Config *src, NMIPConfigMergeFl /* routes */ if (!NM_FLAGS_HAS (merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) { - const NMPlatformIP6Route *route; - - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &route) - _add_route (dst, NMP_OBJECT_UP_CAST (route), NULL, NULL); + nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, NULL) + _add_route (dst, ipconf_iter.current->obj, NULL, NULL); } if (dst_priv->route_metric == -1) @@ -997,6 +1019,7 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) NMDedupMultiIter ipconf_iter; const struct in6_addr *dst_tmp, *src_tmp; gboolean changed; + gboolean changed_default_route; g_return_if_fail (src != NULL); g_return_if_fail (dst != NULL); @@ -1037,12 +1060,24 @@ nm_ip6_config_subtract (NMIP6Config *dst, const NMIP6Config *src) /* routes */ changed = FALSE; + changed_default_route = FALSE; nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) { + nm_auto_nmpobj const NMPObject *obj_old = NULL; + if (nm_dedup_multi_index_remove_obj (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, NMP_OBJECT_UP_CAST (r), - NULL)) + (gconstpointer *) &obj_old)) { + if (dst_priv->best_default_route == obj_old) { + nm_clear_nmp_object (&dst_priv->best_default_route); + changed_default_route = TRUE; + } changed = TRUE; + } + } + if (changed_default_route) { + _nm_ip_config_best_default_route_set (&dst_priv->best_default_route, + _nm_ip6_config_best_default_route_find (dst)); } if (changed) _notify_routes (dst); @@ -1088,6 +1123,7 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) const NMPlatformIP6Address *a; const NMPlatformIP6Route *r; gboolean changed; + const NMPObject *new_best_default_route; g_return_if_fail (src); g_return_if_fail (dst); @@ -1128,17 +1164,24 @@ nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src) /* routes */ changed = FALSE; + new_best_default_route = NULL; nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, dst, &r) { + const NMPObject *o = NMP_OBJECT_UP_CAST (r); + if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, &src_priv->idx_ip6_routes, - NMP_OBJECT_UP_CAST (r))) + o)) { + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, o); continue; + } if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, ipconf_iter.current) != 1) nm_assert_not_reached (); changed = TRUE; } + if (_nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route)) + nm_assert (changed); if (changed) _notify_routes (dst); @@ -1175,6 +1218,7 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev const NMIP6ConfigPrivate *src_priv; NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst; const NMDedupMultiHeadEntry *head_entry_src; + const NMPObject *new_best_default_route; g_return_val_if_fail (NM_IS_IP6_CONFIG (src), FALSE); g_return_val_if_fail (NM_IS_IP6_CONFIG (dst), FALSE); @@ -1293,19 +1337,25 @@ nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relev } if (!are_equal) { has_minor_changes = TRUE; + new_best_default_route = NULL; nm_dedup_multi_index_dirty_set_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes); nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) { + const NMPObject *o = ipconf_iter_src.current->obj; + const NMPObject *obj_new; + _nm_ip_config_add_obj (dst_priv->multi_idx, &dst_priv->idx_ip6_routes_, dst_priv->ifindex, - ipconf_iter_src.current->obj, + o, NULL, FALSE, TRUE, NULL, - NULL); + &obj_new); + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new); } nm_dedup_multi_index_dirty_remove_idx (dst_priv->multi_idx, &dst_priv->idx_ip6_routes, FALSE); + _nm_ip_config_best_default_route_set (&dst_priv->best_default_route, new_best_default_route); _notify_routes (dst); } @@ -1631,18 +1681,12 @@ nm_ip6_config_add_address (NMIP6Config *self, const NMPlatformIP6Address *new) void _nmtst_ip6_config_del_address (NMIP6Config *self, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); const NMPlatformIP6Address *a; a = _nmtst_ip6_config_get_address (self, i); - g_return_if_fail (a); - - if (nm_dedup_multi_index_remove_obj (priv->multi_idx, - &priv->idx_ip6_addresses, - NMP_OBJECT_UP_CAST (a), - NULL) != 1) - g_return_if_reached (); - _notify_addresses (self); + if (!nm_ip6_config_nmpobj_remove (self, + NMP_OBJECT_UP_CAST (a))) + g_assert_not_reached (); } guint @@ -1767,6 +1811,7 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, NMIP6ConfigPrivate *priv; guint i; gboolean changed = FALSE; + const NMPObject *new_best_default_route; g_return_if_fail (NM_IS_IP6_CONFIG (self)); @@ -1776,9 +1821,11 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, nm_dedup_multi_index_dirty_set_idx (priv->multi_idx, &priv->idx_ip6_routes); + new_best_default_route = NULL; for (i = 0; i < routes_n; i++) { const NMNDiscRoute *ndisc_route = &routes[i]; NMPObject obj; + const NMPObject *obj_new; NMPlatformIP6Route *r; nmp_object_stackinit (&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL); @@ -1798,10 +1845,14 @@ nm_ip6_config_reset_routes_ndisc (NMIP6Config *self, FALSE, TRUE, NULL, - NULL)) + &obj_new)) changed = TRUE; + new_best_default_route = _nm_ip_config_best_default_route_find_better (new_best_default_route, obj_new); } + if (_nm_ip_config_best_default_route_set (&priv->best_default_route, new_best_default_route)) + changed = TRUE; + if (nm_dedup_multi_index_dirty_remove_idx (priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0) changed = TRUE; @@ -1815,8 +1866,10 @@ nm_ip6_config_reset_routes (NMIP6Config *self) NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); if (nm_dedup_multi_index_remove_idx (priv->multi_idx, - &priv->idx_ip6_routes) > 0) + &priv->idx_ip6_routes) > 0) { + nm_clear_nmp_object (&priv->best_default_route); _notify_routes (self); + } } static void @@ -1826,6 +1879,7 @@ _add_route (NMIP6Config *self, const NMPObject **out_obj_new) { NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + nm_auto_nmpobj const NMPObject *obj_old = NULL; const NMPObject *obj_new_2; nm_assert ((!new) != (!obj_new)); @@ -1839,8 +1893,12 @@ _add_route (NMIP6Config *self, (const NMPlatformObject *) new, TRUE, FALSE, - NULL, + &obj_old, &obj_new_2)) { + if ( priv->best_default_route == obj_old + && obj_old != obj_new_2) + nm_clear_nmp_object (&priv->best_default_route); + _nm_ip_config_best_default_route_merge (&priv->best_default_route, obj_new_2); NM_SET_OUT (out_obj_new, nmp_object_ref (obj_new_2)); _notify_routes (self); } else @@ -1866,7 +1924,7 @@ nm_ip6_config_add_route (NMIP6Config *self, { g_return_if_fail (self); g_return_if_fail (new); - g_return_if_fail (new->plen > 0 && new->plen <= 128); + g_return_if_fail (new->plen <= 128); g_return_if_fail (NM_IP6_CONFIG_GET_PRIVATE (self)->ifindex > 0); _add_route (self, NULL, new, out_obj_new); @@ -1875,18 +1933,12 @@ nm_ip6_config_add_route (NMIP6Config *self, void _nmtst_ip6_config_del_route (NMIP6Config *self, guint i) { - NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); const NMPlatformIP6Route *r; r = _nmtst_ip6_config_get_route (self, i); - g_return_if_fail (r); - - if (nm_dedup_multi_index_remove_obj (priv->multi_idx, - &priv->idx_ip6_routes, - NMP_OBJECT_UP_CAST (r), - NULL) != 1) - g_return_if_reached (); - _notify_routes (self); + if (!nm_ip6_config_nmpobj_remove (self, + NMP_OBJECT_UP_CAST (r))) + g_assert_not_reached (); } guint @@ -2251,6 +2303,84 @@ nm_ip6_config_get_mss (const NMIP6Config *self) /*****************************************************************************/ +const NMPObject * +nm_ip6_config_nmpobj_lookup (const NMIP6Config *self, const NMPObject *needle) +{ + const NMIP6ConfigPrivate *priv; + const NMDedupMultiIdxType *idx_type; + + g_return_val_if_fail (NM_IS_IP6_CONFIG (self), NULL); + + priv = NM_IP6_CONFIG_GET_PRIVATE (self); + switch (NMP_OBJECT_GET_TYPE (needle)) { + case NMP_OBJECT_TYPE_IP6_ADDRESS: + idx_type = &priv->idx_ip6_addresses; + break; + case NMP_OBJECT_TYPE_IP6_ROUTE: + idx_type = &priv->idx_ip6_routes; + break; + default: + g_return_val_if_reached (NULL); + } + + return nm_dedup_multi_entry_get_obj (nm_dedup_multi_index_lookup_obj (priv->multi_idx, + idx_type, + needle)); +} + +gboolean +nm_ip6_config_nmpobj_remove (NMIP6Config *self, + const NMPObject *needle) +{ + NMIP6ConfigPrivate *priv; + NMDedupMultiIdxType *idx_type; + nm_auto_nmpobj const NMPObject *obj_old = NULL; + guint n; + + g_return_val_if_fail (NM_IS_IP6_CONFIG (self), FALSE); + + priv = NM_IP6_CONFIG_GET_PRIVATE (self); + switch (NMP_OBJECT_GET_TYPE (needle)) { + case NMP_OBJECT_TYPE_IP6_ADDRESS: + idx_type = &priv->idx_ip6_addresses; + break; + case NMP_OBJECT_TYPE_IP6_ROUTE: + idx_type = &priv->idx_ip6_routes; + break; + default: + g_return_val_if_reached (FALSE); + } + + n = nm_dedup_multi_index_remove_obj (priv->multi_idx, + idx_type, + needle, + (gconstpointer *) &obj_old); + if (n != 1) { + nm_assert (n == 0); + return FALSE; + } + + nm_assert (NMP_OBJECT_GET_TYPE (obj_old) == NMP_OBJECT_GET_TYPE (needle)); + + switch (NMP_OBJECT_GET_TYPE (obj_old)) { + case NMP_OBJECT_TYPE_IP6_ADDRESS: + _notify_addresses (self); + break; + case NMP_OBJECT_TYPE_IP6_ROUTE: + if (priv->best_default_route == obj_old) { + _nm_ip_config_best_default_route_set (&priv->best_default_route, + _nm_ip6_config_best_default_route_find (self)); + } + _notify_routes (self); + break; + default: + nm_assert_not_reached (); + } + return TRUE; +} + +/*****************************************************************************/ + static inline void hash_u32 (GChecksum *sum, guint32 n) { @@ -2611,6 +2741,8 @@ finalize (GObject *object) NMIP6Config *self = NM_IP6_CONFIG (object); NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE (self); + nm_clear_nmp_object (&priv->best_default_route); + nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip6_addresses); nm_dedup_multi_index_remove_idx (priv->multi_idx, &priv->idx_ip6_routes); diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 0a7fe1749..ec8bee881 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -127,6 +127,9 @@ void nm_ip6_config_set_gateway (NMIP6Config *self, const struct in6_addr *); const struct in6_addr *nm_ip6_config_get_gateway (const NMIP6Config *self); gint64 nm_ip6_config_get_route_metric (const NMIP6Config *self); +const NMPObject *nm_ip6_config_best_default_route_get (const NMIP6Config *self); +const NMPObject *_nm_ip6_config_best_default_route_find (const NMIP6Config *self); + const NMDedupMultiHeadEntry *nm_ip6_config_lookup_addresses (const NMIP6Config *self); void nm_ip6_config_reset_addresses (NMIP6Config *self); void nm_ip6_config_add_address (NMIP6Config *self, const NMPlatformIP6Address *address); @@ -184,6 +187,11 @@ gint nm_ip6_config_get_dns_priority (const NMIP6Config *self); void nm_ip6_config_set_mss (NMIP6Config *self, guint32 mss); guint32 nm_ip6_config_get_mss (const NMIP6Config *self); +const NMPObject *nm_ip6_config_nmpobj_lookup (const NMIP6Config *self, + const NMPObject *needle); +gboolean nm_ip6_config_nmpobj_remove (NMIP6Config *self, + const NMPObject *needle); + void nm_ip6_config_hash (const NMIP6Config *self, GChecksum *sum, gboolean dns_only); gboolean nm_ip6_config_equal (const NMIP6Config *a, const NMIP6Config *b); diff --git a/src/nm-pacrunner-manager.c b/src/nm-pacrunner-manager.c index 2558ca0f3..08e10e40d 100644 --- a/src/nm-pacrunner-manager.c +++ b/src/nm-pacrunner-manager.c @@ -192,6 +192,8 @@ get_ip4_domains (GPtrArray *domains, NMIP4Config *ip4) } nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &routes) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes)) + continue; cidr = g_strdup_printf ("%s/%u", nm_utils_inet4_ntop (routes->network, NULL), routes->plen); @@ -225,6 +227,8 @@ get_ip6_domains (GPtrArray *domains, NMIP6Config *ip6) } nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &routes) { + if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (routes)) + continue; cidr = g_strdup_printf ("%s/%u", nm_utils_inet6_ntop (&routes->network, NULL), routes->plen); |