diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 918481128b..7514fa784b 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -3884,6 +3884,8 @@ device_link_changed (NMDevice *self) if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); } + + priv->linklocal6_dad_counter = 0; if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) { if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); @@ -12667,6 +12669,7 @@ nm_device_get_firmware_missing (NMDevice *self) static void intersect_ext_config (NMDevice *self, AppliedConfig *config, + gboolean intersect_addresses, gboolean intersect_routes) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -12683,11 +12686,16 @@ intersect_ext_config (NMDevice *self, ? (NMIPConfig *) priv->ext_ip_config_4 : (NMIPConfig *) priv->ext_ip_config_6; - if (config->current) - nm_ip_config_intersect (config->current, ext, intersect_routes, penalty); - else { + if (config->current) { + nm_ip_config_intersect (config->current, + ext, + intersect_addresses, + intersect_routes, + penalty); + } else { config->current = nm_ip_config_intersect_alloc (config->orig, ext, + intersect_addresses, intersect_routes, penalty); } @@ -12723,15 +12731,16 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config * by the user. */ if (priv->con_ip_config_4) { nm_ip4_config_intersect (priv->con_ip_config_4, priv->ext_ip_config_4, + TRUE, is_up, default_route_metric_penalty_get (self, AF_INET)); } - intersect_ext_config (self, &priv->dev_ip_config_4, is_up); - intersect_ext_config (self, &priv->dev2_ip_config_4, is_up); + intersect_ext_config (self, &priv->dev_ip_config_4, TRUE, is_up); + intersect_ext_config (self, &priv->dev2_ip_config_4, TRUE, is_up); for (iter = priv->vpn_configs_4; iter; iter = iter->next) - nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, is_up, 0); + nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, TRUE, is_up, 0); } /* Remove parts from ext_ip_config_4 to only contain the information that @@ -12775,16 +12784,17 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_config * by the user. */ if (priv->con_ip_config_6) { nm_ip6_config_intersect (priv->con_ip_config_6, priv->ext_ip_config_6, + is_up, is_up, default_route_metric_penalty_get (self, AF_INET6)); } - intersect_ext_config (self, &priv->ac_ip6_config, is_up); - intersect_ext_config (self, &priv->dhcp6.ip6_config, is_up); - intersect_ext_config (self, &priv->dev2_ip_config_6, is_up); + intersect_ext_config (self, &priv->ac_ip6_config, is_up, is_up); + intersect_ext_config (self, &priv->dhcp6.ip6_config, is_up, is_up); + intersect_ext_config (self, &priv->dev2_ip_config_6, is_up, is_up); for (iter = priv->vpn_configs_6; iter; iter = iter->next) - nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, is_up, 0); + nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, is_up, is_up, 0); if ( priv->ipv6ll_has && !nm_ip6_config_lookup_address (priv->ext_ip_config_6, &priv->ipv6ll_addr)) @@ -12892,6 +12902,7 @@ queued_ip_config_change (NMDevice *self, int addr_family) if (!IS_IPv4) { NMPlatform *platform; GSList *dad6_failed_addrs, *iter; + const NMPlatformLink *pllink; dad6_failed_addrs = g_steal_pointer (&priv->dad6_failed_addrs); @@ -12900,7 +12911,8 @@ queued_ip_config_change (NMDevice *self, int addr_family) && priv->ifindex > 0 && !nm_device_sys_iface_state_is_external (self) && (platform = nm_device_get_platform (self)) - && nm_platform_link_get (platform, priv->ifindex)) { + && (pllink = nm_platform_link_get (platform, priv->ifindex)) + && (pllink->n_ifi_flags & IFF_UP)) { gboolean need_ipv6ll = FALSE; NMNDiscConfigMap ndisc_config_changed = NM_NDISC_CONFIG_NONE; diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index 5286a0e65a..1c06a42ce9 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -1511,6 +1511,7 @@ nm_ip4_config_subtract (NMIP4Config *dst, static gboolean _nm_ip4_config_intersect_helper (NMIP4Config *dst, const NMIP4Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty, gboolean update_dst) @@ -1533,24 +1534,26 @@ _nm_ip4_config_intersect_helper (NMIP4Config *dst, g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ - changed = FALSE; - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) { - if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, - &src_priv->idx_ip4_addresses, - NMP_OBJECT_UP_CAST (a))) - continue; + if (intersect_addresses) { + changed = FALSE; + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) { + if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, + &src_priv->idx_ip4_addresses, + NMP_OBJECT_UP_CAST (a))) + continue; - if (!update_dst) - return TRUE; + if (!update_dst) + return TRUE; - if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, - ipconf_iter.current) != 1) - nm_assert_not_reached (); - changed = TRUE; - } - if (changed) { - _notify_addresses (dst); - result = TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, + ipconf_iter.current) != 1) + nm_assert_not_reached (); + changed = TRUE; + } + if (changed) { + _notify_addresses (dst); + result = TRUE; + } } /* ignore nameservers */ @@ -1599,12 +1602,12 @@ _nm_ip4_config_intersect_helper (NMIP4Config *dst, _notify (dst, PROP_GATEWAY); } -skip_routes: if (changed) { _notify_routes (dst); result = TRUE; } +skip_routes: /* ignore domains */ /* ignore dns searches */ /* ignore dns options */ @@ -1622,6 +1625,8 @@ skip_routes: * nm_ip4_config_intersect: * @dst: a configuration to be updated * @src: another configuration + * @intersect_addresses: whether addresses should be intersected + * @intersect_routes: whether routes should be intersected * @default_route_metric_penalty: the default route metric penalty * * Computes the intersection between @src and @dst and updates @dst in place @@ -1630,16 +1635,24 @@ skip_routes: void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { - _nm_ip4_config_intersect_helper (dst, src, intersect_routes, default_route_metric_penalty, TRUE); + _nm_ip4_config_intersect_helper (dst, + src, + intersect_addresses, + intersect_routes, + default_route_metric_penalty, + TRUE); } /** * nm_ip4_config_intersect_alloc: * @a: a configuration * @b: another configuration + * @intersect_addresses: whether addresses should be intersected + * @intersect_routes: whether routes should be intersected * @default_route_metric_penalty: the default route metric penalty * * Computes the intersection between @a and @b and returns the result in a newly @@ -1654,17 +1667,24 @@ nm_ip4_config_intersect (NMIP4Config *dst, NMIP4Config * nm_ip4_config_intersect_alloc (const NMIP4Config *a, const NMIP4Config *b, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { NMIP4Config *a_copy; if (_nm_ip4_config_intersect_helper ((NMIP4Config *) a, b, + intersect_addresses, intersect_routes, - default_route_metric_penalty, FALSE)) { + default_route_metric_penalty, + FALSE)) { a_copy = nm_ip4_config_clone (a); - _nm_ip4_config_intersect_helper (a_copy, b, intersect_routes, - default_route_metric_penalty, TRUE); + _nm_ip4_config_intersect_helper (a_copy, + b, + intersect_addresses, + intersect_routes, + default_route_metric_penalty, + TRUE); return a_copy; } else return NULL; diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 07fb7f12a2..6b4bfd64e6 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -189,10 +189,12 @@ void nm_ip4_config_subtract (NMIP4Config *dst, guint32 default_route_metric_penalty); void nm_ip4_config_intersect (NMIP4Config *dst, const NMIP4Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty); NMIP4Config *nm_ip4_config_intersect_alloc (const NMIP4Config *a, const NMIP4Config *b, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty); gboolean nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes); @@ -543,12 +545,14 @@ nm_ip_config_best_default_route_get (const NMIPConfig *self) static inline void nm_ip_config_intersect (NMIPConfig *dst, const NMIPConfig *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { _NM_IP_CONFIG_DISPATCH_SET_OP (, dst, src, nm_ip4_config_intersect, nm_ip6_config_intersect, + intersect_addresses, intersect_routes, default_route_metric_penalty); } @@ -591,6 +595,7 @@ nm_ip_config_replace (NMIPConfig *dst, static inline NMIPConfig * nm_ip_config_intersect_alloc (const NMIPConfig *a, const NMIPConfig *b, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { @@ -598,6 +603,7 @@ nm_ip_config_intersect_alloc (const NMIPConfig *a, nm_assert (NM_IS_IP4_CONFIG (b)); return (NMIPConfig *) nm_ip4_config_intersect_alloc ((const NMIP4Config *) a, (const NMIP4Config *) b, + intersect_addresses, intersect_routes, default_route_metric_penalty); } else { @@ -605,6 +611,7 @@ nm_ip_config_intersect_alloc (const NMIPConfig *a, nm_assert (NM_IS_IP6_CONFIG (b)); return (NMIPConfig *) nm_ip6_config_intersect_alloc ((const NMIP6Config *) a, (const NMIP6Config *) b, + intersect_addresses, intersect_routes, default_route_metric_penalty); } diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index d63968cf0d..99a9ff8886 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -1086,6 +1086,7 @@ nm_ip6_config_subtract (NMIP6Config *dst, static gboolean _nm_ip6_config_intersect_helper (NMIP6Config *dst, const NMIP6Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty, gboolean update_dst) @@ -1108,24 +1109,26 @@ _nm_ip6_config_intersect_helper (NMIP6Config *dst, g_object_freeze_notify (G_OBJECT (dst)); /* addresses */ - changed = FALSE; - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, dst, &a) { - if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, - &src_priv->idx_ip6_addresses, - NMP_OBJECT_UP_CAST (a))) - continue; + if (intersect_addresses) { + changed = FALSE; + nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, dst, &a) { + if (nm_dedup_multi_index_lookup_obj (src_priv->multi_idx, + &src_priv->idx_ip6_addresses, + NMP_OBJECT_UP_CAST (a))) + continue; - if (!update_dst) - return TRUE; + if (!update_dst) + return TRUE; - if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, - ipconf_iter.current) != 1) - nm_assert_not_reached (); - changed = TRUE; - } - if (changed) { - _notify_addresses (dst); - result = TRUE; + if (nm_dedup_multi_index_remove_entry (dst_priv->multi_idx, + ipconf_iter.current) != 1) + nm_assert_not_reached (); + changed = TRUE; + } + if (changed) { + _notify_addresses (dst); + result = TRUE; + } } /* ignore nameservers */ @@ -1193,6 +1196,8 @@ skip_routes: * nm_ip6_config_intersect: * @dst: a configuration to be updated * @src: another configuration + * @intersect_addresses: whether addresses should be intersected + * @intersect_routes: whether routes should be intersected * @default_route_metric_penalty: the default route metric penalty * * Computes the intersection between @src and @dst and updates @dst in place @@ -1201,16 +1206,24 @@ skip_routes: void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { - _nm_ip6_config_intersect_helper (dst, src, intersect_routes, default_route_metric_penalty, TRUE); + _nm_ip6_config_intersect_helper (dst, + src, + intersect_addresses, + intersect_routes, + default_route_metric_penalty, + TRUE); } /** * nm_ip6_config_intersect_alloc: * @a: a configuration * @b: another configuration + * @intersect_addresses: whether addresses should be intersected + * @intersect_routes: whether routes should be intersected * @default_route_metric_penalty: the default route metric penalty * * Computes the intersection between @a and @b and returns the result in a newly @@ -1225,17 +1238,25 @@ nm_ip6_config_intersect (NMIP6Config *dst, NMIP6Config * nm_ip6_config_intersect_alloc (const NMIP6Config *a, const NMIP6Config *b, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty) { NMIP6Config *a_copy; - if (_nm_ip6_config_intersect_helper ((NMIP6Config *) a, b, + if (_nm_ip6_config_intersect_helper ((NMIP6Config *) a, + b, + intersect_addresses, intersect_routes, - default_route_metric_penalty, FALSE)) { + default_route_metric_penalty, + FALSE)) { a_copy = nm_ip6_config_clone (a); - _nm_ip6_config_intersect_helper (a_copy, b, intersect_routes, - default_route_metric_penalty, TRUE); + _nm_ip6_config_intersect_helper (a_copy, + b, + intersect_addresses, + intersect_routes, + default_route_metric_penalty, + TRUE); return a_copy; } else return NULL; diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 862f237de0..557e379604 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -130,10 +130,12 @@ void nm_ip6_config_subtract (NMIP6Config *dst, guint32 default_route_metric_penalty); void nm_ip6_config_intersect (NMIP6Config *dst, const NMIP6Config *src, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty); NMIP6Config *nm_ip6_config_intersect_alloc (const NMIP6Config *a, const NMIP6Config *b, + gboolean intersect_addresses, gboolean intersect_routes, guint32 default_route_metric_penalty); gboolean nm_ip6_config_replace (NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);