diff options
Diffstat (limited to 'src/devices/nm-device.c')
-rw-r--r-- | src/devices/nm-device.c | 1587 |
1 files changed, 682 insertions, 905 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 6c23a77286..fc7c76b94d 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -234,8 +234,14 @@ typedef struct _NMDevicePrivate { NMDeviceStateReason reason; } queued_state; - guint queued_ip4_config_id; - guint queued_ip6_config_id; + union { + struct { + guint queued_ip_config_id_6; + guint queued_ip_config_id_4; + }; + guint queued_ip_config_id_x[2]; + }; + GSList *pending_actions; GSList *dad6_failed_addrs; @@ -263,6 +269,9 @@ typedef struct _NMDevicePrivate { bool queued_ip4_config_pending:1; bool queued_ip6_config_pending:1; + bool update_ip_config_completed_v4:1; + bool update_ip_config_completed_v6:1; + char * ip_iface; int ip_ifindex; NMDeviceType type; @@ -360,6 +369,11 @@ typedef struct _NMDevicePrivate { NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:4; + bool is_enslaved:1; + bool master_ready_handled:1; + + bool ipv6ll_handle:1; /* TRUE if NM handles the device's IPv6LL address */ + /* Generic DHCP stuff */ char * dhcp_anycast_address; @@ -370,17 +384,56 @@ typedef struct _NMDevicePrivate { NMPacrunnerManager *pacrunner_manager; NMPacrunnerCallId *pacrunner_call_id; - /* IP4 configuration info */ - NMIP4Config * ip4_config; /* Combined config from VPN, settings, and device */ + /* IP configuration info. Combined config from VPN, settings, and device */ + union { + struct { + NMIP6Config *ip_config_6; + NMIP4Config *ip_config_4; + }; + NMIPConfig *ip_config_x[2]; + }; + union { const IpState ip4_state; IpState ip4_state_; }; - NMIP4Config * con_ip4_config; /* config from the setting */ AppliedConfig dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ - AppliedConfig wwan_ip4_config; /* WWAN configuration */ - NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ - GSList * vpn4_configs; /* VPNs which use this device */ + + /* config from the setting */ + union { + struct { + NMIP6Config *con_ip_config_6; + NMIP4Config *con_ip_config_4; + }; + NMIPConfig *con_ip_config_x[2]; + }; + + /* Stuff added outside NM */ + union { + struct { + NMIP6Config *ext_ip_config_6; + NMIP4Config *ext_ip_config_4; + }; + NMIPConfig *ext_ip_config_x[2]; + }; + + /* VPNs which use this device */ + union { + struct { + GSList *vpn_configs_6; + GSList *vpn_configs_4; + }; + GSList *vpn_configs_x[2]; + }; + + /* WWAN configuration */ + union { + struct { + AppliedConfig wwan_ip_config_6; + AppliedConfig wwan_ip_config_4; + }; + AppliedConfig wwan_ip_config_x[2]; + }; bool v4_has_shadowed_routes; const char *ip4_rp_filter; @@ -425,19 +478,12 @@ typedef struct _NMDevicePrivate { NMArpingManager * announcing; } arping; - /* IP6 configuration info */ - NMIP6Config * ip6_config; union { const IpState ip6_state; IpState ip6_state_; }; - NMIP6Config * con_ip6_config; /* config from the setting */ - AppliedConfig wwan_ip6_config; AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */ - NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */ - GSList * vpn6_configs; /* VPNs which use this device */ - bool nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ NMIP6Config * dad6_ip6_config; GHashTable * rt6_temporary_not_available; @@ -471,8 +517,6 @@ typedef struct _NMDevicePrivate { /* master interface for bridge/bond/team slave */ NMDevice * master; - bool is_enslaved; - bool master_ready_handled; gulong master_ready_id; /* slave management */ @@ -511,27 +555,24 @@ static const GDBusSignalInfo signal_info_state_changed; static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url); -static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs); +static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_configs); -static gboolean nm_device_set_ip4_config (NMDevice *self, - NMIP4Config *config, - gboolean commit, - GPtrArray *ip4_dev_route_blacklist); -static gboolean ip4_config_merge_and_apply (NMDevice *self, - gboolean commit); +static gboolean nm_device_set_ip_config (NMDevice *self, + int addr_family, + NMIPConfig *config, + gboolean commit, + GPtrArray *ip4_dev_route_blacklist); -static gboolean nm_device_set_ip6_config (NMDevice *self, - NMIP6Config *config, - gboolean commit); -static gboolean ip6_config_merge_and_apply (NMDevice *self, - gboolean commit); +static gboolean ip_config_merge_and_apply (NMDevice *self, + int addr_family, + gboolean commit); static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason); -static gboolean addrconf6_start_with_link_ready (NMDevice *self); -static NMActStageReturn linklocal6_start (NMDevice *self); +static void addrconf6_start_with_link_ready (NMDevice *self); +static gboolean linklocal6_start (NMDevice *self); static void _carrier_wait_check_queued_act_request (NMDevice *self); static gint64 _get_carrier_wait_ms (NMDevice *self); @@ -927,29 +968,18 @@ nm_device_assume_state_reset (NMDevice *self) /*****************************************************************************/ static void -init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config) -{ - gs_free char *value = NULL; - gint priority; - - value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "ipv4.dns-priority", - self); - priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); - nm_ip4_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); -} - -static void -init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config) +init_ip_config_dns_priority (NMDevice *self, NMIPConfig *config) { gs_free char *value = NULL; gint priority; value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, - "ipv6.dns-priority", + (nm_ip_config_get_addr_family (config) == AF_INET) + ? "ipv4.dns-priority" + : "ipv6.dns-priority", self); priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0); - nm_ip6_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); + nm_ip_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL); } /*****************************************************************************/ @@ -2010,12 +2040,12 @@ nm_device_get_best_default_route (NMDevice *self, switch (addr_family) { case AF_INET: - return priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL; + return priv->ip_config_4 ? nm_ip4_config_best_default_route_get (priv->ip_config_4) : NULL; case AF_INET6: - return priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL; + return priv->ip_config_6 ? nm_ip6_config_best_default_route_get (priv->ip_config_6) : NULL; case AF_UNSPEC: - return (priv->ip4_config ? nm_ip4_config_best_default_route_get (priv->ip4_config) : NULL) - ?: (priv->ip6_config ? nm_ip6_config_best_default_route_get (priv->ip6_config) : NULL); + return (priv->ip_config_4 ? nm_ip4_config_best_default_route_get (priv->ip_config_4) : NULL) + ?: (priv->ip_config_6 ? nm_ip6_config_best_default_route_get (priv->ip_config_6) : NULL); default: g_return_val_if_reached (NULL); } @@ -2161,10 +2191,10 @@ update_connectivity_state (NMDevice *self, NMConnectivityState state) if ( priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external (self)) { if ( nm_device_get_best_default_route (self, AF_INET) - && !ip4_config_merge_and_apply (self, TRUE)) + && !ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "Failed to update IPv4 route metric"); if ( nm_device_get_best_default_route (self, AF_INET6) - && !ip6_config_merge_and_apply (self, TRUE)) + && !ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "Failed to update IPv6 route metric"); } } @@ -2377,7 +2407,7 @@ nm_device_master_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *c /* Since slave devices don't have their own IP configuration, * set the MTU here. */ - _commit_mtu (slave, NM_DEVICE_GET_PRIVATE (slave)->ip4_config); + _commit_mtu (slave, NM_DEVICE_GET_PRIVATE (slave)->ip_config_4); return success; } @@ -2783,7 +2813,7 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) now = nm_utils_get_monotonic_timestamp_s (); - head_entry = nm_ip6_config_lookup_addresses (priv->ip6_config); + head_entry = nm_ip6_config_lookup_addresses (priv->ip_config_6); addresses = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscAddress), head_entry ? head_entry->len : 0); nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) { @@ -2826,11 +2856,11 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) ndisc_addr->preferred = preferred; } - len = nm_ip6_config_get_num_nameservers (priv->ip6_config); + len = nm_ip6_config_get_num_nameservers (priv->ip_config_6); dns_servers = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSServer), len); g_array_set_size (dns_servers, len); for (i = 0; i < len; i++) { - const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip6_config, i); + const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip_config_6, i); NMNDiscDNSServer *ndisc_nameserver; ndisc_nameserver = &g_array_index (dns_servers, NMNDiscDNSServer, i); @@ -2839,11 +2869,11 @@ ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self) ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME; } - len = nm_ip6_config_get_num_searches (priv->ip6_config); + len = nm_ip6_config_get_num_searches (priv->ip_config_6); dns_domains = g_array_sized_new (FALSE, TRUE, sizeof (NMNDiscDNSDomain), len); g_array_set_size (dns_domains, len); for (i = 0; i < len; i++) { - const char *search = nm_ip6_config_get_search (priv->ip6_config, i); + const char *search = nm_ip6_config_get_search (priv->ip_config_6, i); NMNDiscDNSDomain *ndisc_search; ndisc_search = &g_array_index (dns_domains, NMNDiscDNSDomain, i); @@ -2969,11 +2999,11 @@ device_link_changed (NMDevice *self) /* the link was down and just came up. That happens for example, while changing MTU. * We must restore IP configuration. */ if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after link comes up again"); } if (priv->ip6_state == IP_DONE) { - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after link comes up again"); } } @@ -3477,8 +3507,8 @@ realize_start_setup (NMDevice *self, g_return_if_fail (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)); g_return_if_fail (priv->ip_ifindex <= 0); g_return_if_fail (priv->ip_iface == NULL); - g_return_if_fail (!priv->queued_ip4_config_id); - g_return_if_fail (!priv->queued_ip6_config_id); + g_return_if_fail (!priv->queued_ip_config_id_4); + g_return_if_fail (!priv->queued_ip_config_id_6); _LOGD (LOGD_DEVICE, "start setup of %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), plink ? plink->ifindex : 0); @@ -3525,7 +3555,7 @@ realize_start_setup (NMDevice *self, if (nm_platform_check_kernel_support (nm_device_get_platform (self), NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) - priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex); + priv->ipv6ll_handle = nm_platform_link_get_user_ipv6ll_enabled (nm_device_get_platform (self), priv->ifindex); if (nm_platform_link_supports_sriov (nm_device_get_platform (self), priv->ifindex)) capabilities |= NM_DEVICE_CAP_SRIOV; @@ -3624,6 +3654,9 @@ nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink) if (plink) device_recheck_slave_status (self, plink); + priv->update_ip_config_completed_v4 = FALSE; + priv->update_ip_config_completed_v6 = FALSE; + priv->real = TRUE; _notify (self, PROP_REAL); @@ -4327,8 +4360,8 @@ nm_device_removed (NMDevice *self, gboolean unconfigure_ip_config) if (!unconfigure_ip_config) return; - nm_device_set_ip4_config (self, NULL, FALSE, NULL); - nm_device_set_ip6_config (self, NULL, FALSE); + nm_device_set_ip_config (self, AF_INET, NULL, FALSE, NULL); + nm_device_set_ip_config (self, AF_INET6, NULL, FALSE, NULL); } static gboolean @@ -4580,9 +4613,9 @@ device_has_config (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); /* Check for IP configuration. */ - if (priv->ip4_config && nm_ip4_config_get_num_addresses (priv->ip4_config)) + if (priv->ip_config_4 && nm_ip4_config_get_num_addresses (priv->ip_config_4)) return TRUE; - if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) + if (priv->ip_config_6 && nm_ip6_config_get_num_addresses (priv->ip_config_6)) return TRUE; /* The existence of a software device is good enough. */ @@ -4707,10 +4740,10 @@ nm_device_generate_connection (NMDevice *self, } } else { /* Only regular and master devices get IP configuration; slaves do not */ - s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); + s_ip4 = nm_ip4_config_create_setting (priv->ip_config_4); nm_connection_add_setting (connection, s_ip4); - s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); + s_ip6 = nm_ip6_config_create_setting (priv->ip_config_6); nm_connection_add_setting (connection, s_ip6); nm_connection_add_setting (connection, nm_setting_proxy_new ()); @@ -5900,7 +5933,7 @@ nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) nm_device_activate_schedule_ip4_config_result (self, config); } else if (priv->ip4_state == IP_DONE) { applied_config_init (&priv->dev_ip4_config, config); - if (!ip4_config_merge_and_apply (self, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); } @@ -5996,56 +6029,42 @@ ipv4ll_start (NMDevice *self) /*****************************************************************************/ static void -ensure_con_ip4_config (NMDevice *self) +ensure_con_ip_config (NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; + const gboolean IS_IPv4 = (addr_family == AF_INET); + NMIPConfig *con_ip_config; - if (priv->con_ip4_config) + if (priv->con_ip_config_x[IS_IPv4]) return; connection = nm_device_get_applied_connection (self); if (!connection) return; - priv->con_ip4_config = _ip4_config_new (self); - nm_ip4_config_merge_setting (priv->con_ip4_config, - nm_connection_get_setting_ip4_config (connection), - _get_mdns (self), - nm_device_get_route_table (self, AF_INET, TRUE), - nm_device_get_route_metric (self, AF_INET)); + con_ip_config = _ip_config_new (self, addr_family); - if (nm_device_sys_iface_state_is_external_or_assume (self)) { - /* For assumed connections ignore all addresses and routes. */ - nm_ip4_config_reset_addresses (priv->con_ip4_config); - nm_ip4_config_reset_routes (priv->con_ip4_config); + if (IS_IPv4) { + nm_ip4_config_merge_setting (NM_IP4_CONFIG (con_ip_config), + nm_connection_get_setting_ip4_config (connection), + _get_mdns (self), + nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_metric (self, addr_family)); + } else { + nm_ip6_config_merge_setting (NM_IP6_CONFIG (con_ip_config), + nm_connection_get_setting_ip6_config (connection), + nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_metric (self, addr_family)); } -} - -static void -ensure_con_ip6_config (NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - - if (priv->con_ip6_config) - return; - - connection = nm_device_get_applied_connection (self); - if (!connection) - return; - - priv->con_ip6_config = _ip6_config_new (self); - nm_ip6_config_merge_setting (priv->con_ip6_config, - nm_connection_get_setting_ip6_config (connection), - nm_device_get_route_table (self, AF_INET6, TRUE), - nm_device_get_route_metric (self, AF_INET6)); if (nm_device_sys_iface_state_is_external_or_assume (self)) { /* For assumed connections ignore all addresses and routes. */ - nm_ip6_config_reset_addresses (priv->con_ip6_config); - nm_ip6_config_reset_routes (priv->con_ip6_config); + nm_ip_config_reset_addresses (con_ip_config); + nm_ip_config_reset_routes (con_ip_config); } + + priv->con_ip_config_x[IS_IPv4] = con_ip_config; } /*****************************************************************************/ @@ -6079,101 +6098,194 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) } static gboolean -ip4_config_merge_and_apply (NMDevice *self, - gboolean commit) +ip_config_merge_and_apply (NMDevice *self, + int addr_family, + gboolean commit) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; gboolean success; - NMIP4Config *composite, *config; + gs_unref_object NMIPConfig *composite = NULL; + NMIPConfig *config; + gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; + NMConnection *connection; gboolean ignore_auto_routes = FALSE; gboolean ignore_auto_dns = FALSE; gboolean ignore_default_routes = FALSE; GSList *iter; - gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL; + const char *ip6_addr_gen_token = NULL; + const gboolean IS_IPv4 = (addr_family == AF_INET); if (nm_device_sys_iface_state_is_external (self)) - commit = 0; + commit = FALSE; - /* Apply ignore-auto-routes and ignore-auto-dns settings */ connection = nm_device_get_applied_connection (self); + + /* Apply ignore-auto-routes and ignore-auto-dns settings */ if (connection) { - NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection); + NMSettingIPConfig *s_ip = IS_IPv4 + ? nm_connection_get_setting_ip4_config (connection) + : nm_connection_get_setting_ip6_config (connection); - if (s_ip4) { - ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip4); - ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip4); + if (s_ip) { + ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip); + ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip); /* if the connection has an explicit gateway, we also ignore * the default routes from other sources. */ - ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip4) - || nm_setting_ip_config_get_gateway (s_ip4); + ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip) + || nm_setting_ip_config_get_gateway (s_ip); + + if (!IS_IPv4) { + NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (s_ip); + + if (nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) + ip6_addr_gen_token = nm_setting_ip6_config_get_token (s_ip6); + } } } - composite = _ip4_config_new (self); - init_ip4_config_dns_priority (self, composite); + composite = _ip_config_new (self, addr_family); + + if (!IS_IPv4) { + nm_ip6_config_set_privacy (NM_IP6_CONFIG (composite), + priv->ndisc + ? priv->ndisc_use_tempaddr + : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); + } + + init_ip_config_dns_priority (self, composite); if (commit) { - if (priv->queued_ip4_config_id) - update_ext_ip_config (self, AF_INET, FALSE, FALSE); - ensure_con_ip4_config (self); + if (priv->queued_ip_config_id_x[IS_IPv4]) + update_ext_ip_config (self, addr_family, FALSE); + ensure_con_ip_config (self, addr_family); } - if (commit) - priv->default_route_metric_penalty_ip4_has = default_route_metric_penalty_detect (self); + if (commit) { + gboolean v; - config = (NMIP4Config *) applied_config_get_current (&priv->dev_ip4_config); - if (config) { - nm_ip4_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get (self, AF_INET)); + v = default_route_metric_penalty_detect (self); + if (IS_IPv4) + priv->default_route_metric_penalty_ip4_has = v; + else + priv->default_route_metric_penalty_ip6_has = v; + } + + /* Merge all the IP configs into the composite config */ + + if (IS_IPv4) { + config = applied_config_get_current (&priv->dev_ip4_config); + if (config) { + nm_ip4_config_merge (NM_IP4_CONFIG (composite), NM_IP4_CONFIG (config), + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), + default_route_metric_penalty_get (self, addr_family)); + } + } + + if (!IS_IPv4) { + config = applied_config_get_current (&priv->ac_ip6_config); + if (config) { + nm_ip6_config_merge (NM_IP6_CONFIG (composite), NM_IP6_CONFIG (config), + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), + default_route_metric_penalty_get (self, addr_family)); + } } - for (iter = priv->vpn4_configs; iter; iter = iter->next) - nm_ip4_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); + if (!IS_IPv4) { + config = applied_config_get_current (&priv->dhcp6.ip6_config); + if (config) { + nm_ip6_config_merge (NM_IP6_CONFIG (composite), NM_IP6_CONFIG (config), + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), + default_route_metric_penalty_get (self, addr_family)); + } + } - if (priv->ext_ip4_config) - nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, 0); + for (iter = priv->vpn_configs_x[IS_IPv4]; iter; iter = iter->next) + nm_ip_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); + + if (priv->ext_ip_config_x[IS_IPv4]) + nm_ip_config_merge (composite, priv->ext_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_DEFAULT, 0); /* Merge WWAN config *last* to ensure modem-given settings overwrite * any external stuff set by pppd or other scripts. */ - config = (NMIP4Config *) applied_config_get_current (&priv->wwan_ip4_config); + config = applied_config_get_current (&priv->wwan_ip_config_x[IS_IPv4]); if (config) { - nm_ip4_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get (self, AF_INET)); + nm_ip_config_merge (composite, config, + (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) + | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) + | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), + default_route_metric_penalty_get (self, addr_family)); + } + + if (!IS_IPv4) { + if (priv->rt6_temporary_not_available) { + const NMPObject *o; + GHashTableIter hiter; + + g_hash_table_iter_init (&hiter, priv->rt6_temporary_not_available); + while (g_hash_table_iter_next (&hiter, (gpointer *) &o, NULL)) { + nm_ip6_config_add_route (NM_IP6_CONFIG (composite), + NMP_OBJECT_CAST_IP6_ROUTE (o), + NULL); + } + } } /* Merge user overrides into the composite config. For assumed connections, - * con_ip4_config is empty. */ - if (priv->con_ip4_config) { - nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT, - default_route_metric_penalty_get (self, AF_INET)); + * con_ip_config_x is empty. */ + if (priv->con_ip_config_x[IS_IPv4]) { + nm_ip_config_merge (composite, priv->con_ip_config_x[IS_IPv4], NM_IP_CONFIG_MERGE_DEFAULT, + default_route_metric_penalty_get (self, addr_family)); } if (commit) { - nm_ip4_config_add_dependent_routes (composite, - nm_device_get_route_table (self, AF_INET, TRUE), - nm_device_get_route_metric (self, AF_INET), - &ip4_dev_route_blacklist); + if (IS_IPv4) { + nm_ip4_config_add_dependent_routes (NM_IP4_CONFIG (composite), + nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_metric (self, addr_family), + &ip4_dev_route_blacklist); + } else { + nm_ip6_config_add_dependent_routes (NM_IP6_CONFIG (composite), + nm_device_get_route_table (self, addr_family, TRUE), + nm_device_get_route_metric (self, addr_family)); + } } - if (commit) { - if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) - NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, composite); + if (IS_IPv4) { + if (commit) { + if (NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit) + NM_DEVICE_GET_CLASS (self)->ip4_config_pre_commit (self, NM_IP4_CONFIG (composite)); + } + } + + if (!IS_IPv4) { + if (commit) { + NMUtilsIPv6IfaceId iid; + + if ( ip6_addr_gen_token + && nm_utils_ipv6_interface_identifier_get_from_token (&iid, ip6_addr_gen_token)) { + nm_platform_link_set_ipv6_token (nm_device_get_platform (self), + nm_device_get_ip_ifindex (self), + iid); + } + } } - success = nm_device_set_ip4_config (self, composite, commit, ip4_dev_route_blacklist); - g_object_unref (composite); + success = nm_device_set_ip_config (self, addr_family, composite, commit, ip4_dev_route_blacklist); + if (commit) { + if (IS_IPv4) + priv->v4_commit_first_time = FALSE; + else + priv->v6_commit_first_time = FALSE; + } - if (commit) - priv->v4_commit_first_time = FALSE; return success; } @@ -6186,7 +6298,7 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) applied_config_init (&priv->dev_ip4_config, config); - if (!ip4_config_merge_and_apply (self, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { _LOGW (LOGD_DHCP4, "failed to update IPv4 config for DHCP change."); return FALSE; } @@ -6226,8 +6338,8 @@ dhcp4_fail (NMDevice *self, gboolean timeout) * on the interface. */ if ( priv->ip4_state == IP_DONE - && priv->con_ip4_config - && nm_ip4_config_get_num_addresses (priv->con_ip4_config) > 0) + && priv->con_ip_config_4 + && nm_ip4_config_get_num_addresses (priv->con_ip_config_4) > 0) goto clear_config; /* Fail the method in case of timeout or failure during initial @@ -6844,140 +6956,6 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) } static gboolean -ip6_config_merge_and_apply (NMDevice *self, - gboolean commit) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; - gboolean success; - NMIP6Config *composite, *config; - gboolean ignore_auto_routes = FALSE; - gboolean ignore_auto_dns = FALSE; - gboolean ignore_default_routes = FALSE; - const char *token = NULL; - GSList *iter; - - if (nm_device_sys_iface_state_is_external (self)) - commit = 0; - - /* Apply ignore-auto-routes and ignore-auto-dns settings */ - connection = nm_device_get_applied_connection (self); - if (connection) { - NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); - - if (s_ip6) { - NMSettingIP6Config *ip6 = NM_SETTING_IP6_CONFIG (s_ip6); - - ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes (s_ip6); - ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns (s_ip6); - - /* if the connection has an explicit gateway, we also ignore - * the default routes from other sources. */ - ignore_default_routes = nm_setting_ip_config_get_never_default (s_ip6) - || nm_setting_ip_config_get_gateway (s_ip6); - - if (nm_setting_ip6_config_get_addr_gen_mode (ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) - token = nm_setting_ip6_config_get_token (ip6); - } - } - - composite = _ip6_config_new (self); - nm_ip6_config_set_privacy (composite, - priv->ndisc ? - priv->ndisc_use_tempaddr : - NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); - init_ip6_config_dns_priority (self, composite); - - if (commit) { - if (priv->queued_ip6_config_id) - update_ext_ip_config (self, AF_INET6, FALSE, FALSE); - ensure_con_ip6_config (self); - } - - if (commit) - priv->default_route_metric_penalty_ip6_has = default_route_metric_penalty_detect (self); - - /* Merge all the IP configs into the composite config */ - config = (NMIP6Config *) applied_config_get_current (&priv->ac_ip6_config); - if (config) { - nm_ip6_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get (self, AF_INET6)); - } - - config = (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config); - if (config) { - nm_ip6_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get (self, AF_INET6)); - } - - for (iter = priv->vpn6_configs; iter; iter = iter->next) - nm_ip6_config_merge (composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0); - - if (priv->ext_ip6_config) - nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT, 0); - - /* Merge WWAN config *last* to ensure modem-given settings overwrite - * any external stuff set by pppd or other scripts. - */ - config = (NMIP6Config *) applied_config_get_current (&priv->wwan_ip6_config); - if (config) { - nm_ip6_config_merge (composite, config, - (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) - | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0) - | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0), - default_route_metric_penalty_get (self, AF_INET6)); - } - - if (priv->rt6_temporary_not_available) { - const NMPObject *o; - GHashTableIter hiter; - - g_hash_table_iter_init (&hiter, priv->rt6_temporary_not_available); - while (g_hash_table_iter_next (&hiter, (gpointer *) &o, NULL)) { - nm_ip6_config_add_route (composite, - NMP_OBJECT_CAST_IP6_ROUTE (o), - NULL); - } - } - - /* Merge user overrides into the composite config. For assumed connections, - * con_ip6_config is empty. */ - if (priv->con_ip6_config) { - nm_ip6_config_merge (composite, priv->con_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT, - default_route_metric_penalty_get (self, AF_INET6)); - } - - if (commit) { - nm_ip6_config_add_dependent_routes (composite, - nm_device_get_route_table (self, AF_INET6, TRUE), - nm_device_get_route_metric (self, AF_INET6)); - } - - /* Allow setting MTU etc */ - if (commit) { - NMUtilsIPv6IfaceId iid; - - if (token && nm_utils_ipv6_interface_identifier_get_from_token (&iid, token)) { - nm_platform_link_set_ipv6_token (nm_device_get_platform (self), - nm_device_get_ip_ifindex (self), - iid); - } - } - - success = nm_device_set_ip6_config (self, composite, commit); - g_object_unref (composite); - if (commit) - priv->v6_commit_first_time = FALSE; - return success; -} - -static gboolean dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -6994,7 +6972,7 @@ dhcp6_lease_change (NMDevice *self) g_assert (settings_connection); /* Apply the updated config */ - if (!ip6_config_merge_and_apply (self, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) { _LOGW (LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event"); return FALSE; } @@ -7038,8 +7016,8 @@ dhcp6_fail (NMDevice *self, gboolean timeout) * on the interface. */ if ( priv->ip6_state == IP_DONE - && priv->con_ip6_config - && nm_ip6_config_get_num_addresses (priv->con_ip6_config)) + && priv->con_ip_config_6 + && nm_ip6_config_get_num_addresses (priv->con_ip_config_6)) goto clear_config; /* Fail the method in case of timeout or failure during initial @@ -7205,8 +7183,11 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) s_ip6 = nm_connection_get_setting_ip6_config (connection); g_assert (s_ip6); - if (priv->ext_ip6_config_captured) - ll_addr = nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE); + if (priv->ext_ip6_config_captured) { + ll_addr = nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL); + } if (!ll_addr) { _LOGW (LOGD_DHCP6, "can't start DHCPv6: no link-local address"); @@ -7272,17 +7253,12 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll) nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP6, TRUE); if (wait_for_ll) { - NMActStageReturn ret; - /* ensure link local is ready... */ - ret = linklocal6_start (self); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { - /* success; wait for the LL address to show up */ + if (!linklocal6_start (self)) { + /* wait for the LL address to show up */ return TRUE; } - - /* success; already have the LL address; kick off DHCP */ - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + /* already have the LL address; kick off DHCP */ } if (!dhcp6_start_with_link_ready (self, connection)) @@ -7356,7 +7332,7 @@ nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet) subnet->preferred); /* This also updates the ndisc if there are actual changes. */ - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing"); } @@ -7394,24 +7370,18 @@ nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device) nm_ip6_config_get_search (from_config, i)); } - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing"); } /*****************************************************************************/ static void -linklocal6_cleanup (NMDevice *self) +linklocal6_failed (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); nm_clear_g_source (&priv->linklocal6_timeout_id); -} - -static void -linklocal6_failed (NMDevice *self) -{ - linklocal6_cleanup (self); nm_device_activate_schedule_ip6_config_timeout (self); } @@ -7426,17 +7396,26 @@ linklocal6_timeout_cb (gpointer user_data) } static void -linklocal6_complete (NMDevice *self) +linklocal6_check_complete (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; const char *method; - g_assert (priv->linklocal6_timeout_id); - g_assert (priv->ext_ip6_config_captured); - g_assert (nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)); + if (!priv->linklocal6_timeout_id) { + /* we are not waiting for linklocal to complete. Nothing to do. */ + return; + } + + if ( !priv->ext_ip6_config_captured + || !nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) { + /* we don't have a non-tentative link local address yet. Wait longer. */ + return; + } - linklocal6_cleanup (self); + nm_clear_g_source (&priv->linklocal6_timeout_id); connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -7446,12 +7425,9 @@ linklocal6_complete (NMDevice *self) _LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses successful, continue with method %s", method); if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0 - || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) { - if (!addrconf6_start_with_link_ready (self)) { - /* Time out IPv6 instead of failing the entire activation */ - nm_device_activate_schedule_ip6_config_timeout (self); - } - } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { + || strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) + addrconf6_start_with_link_ready (self); + else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { if (!dhcp6_start_with_link_ready (self, connection)) { /* Time out IPv6 instead of failing the entire activation */ nm_device_activate_schedule_ip6_config_timeout (self); @@ -7472,20 +7448,16 @@ check_and_add_ipv6ll_addr (NMDevice *self) NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; - if (priv->nm_ipv6ll == FALSE) + if (!priv->ipv6ll_handle) return; - if (priv->ext_ip6_config_captured) { - NMDedupMultiIter ipconf_iter; - const NMPlatformIP6Address *addr; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, priv->ext_ip6_config_captured, &addr) { - if ( IN6_IS_ADDR_LINKLOCAL (&addr->address) - && !(addr->n_ifa_flags & IFA_F_DADFAILED)) { - /* Already have an LL address, nothing to do */ - return; - } - } + if ( priv->ext_ip6_config_captured + && nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) { + /* Already have an LL address, nothing to do */ + return; } memset (&lladdr, 0, sizeof (lladdr)); @@ -7547,18 +7519,20 @@ check_and_add_ipv6ll_addr (NMDevice *self) } } -static NMActStageReturn +static gboolean linklocal6_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; const char *method; - linklocal6_cleanup (self); + nm_clear_g_source (&priv->linklocal6_timeout_id); if ( priv->ext_ip6_config_captured - && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) - return NM_ACT_STAGE_RETURN_SUCCESS; + && nm_ip6_config_find_first_address (priv->ext_ip6_config_captured, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) + return TRUE; connection = nm_device_get_applied_connection (self); g_assert (connection); @@ -7574,8 +7548,7 @@ linklocal6_start (NMDevice *self) * (rh #1101809) */ priv->linklocal6_timeout_id = g_timeout_add_seconds (15, linklocal6_timeout_cb, self); - - return NM_ACT_STAGE_RETURN_POSTPONE; + return FALSE; } /*****************************************************************************/ @@ -7817,7 +7790,7 @@ nm_device_commit_mtu (NMDevice *self) if ( state >= NM_DEVICE_STATE_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { _LOGT (LOGD_DEVICE, "mtu: commit-mtu..."); - _commit_mtu (self, NM_DEVICE_GET_PRIVATE (self)->ip4_config); + _commit_mtu (self, NM_DEVICE_GET_PRIVATE (self)->ip_config_4); } else _LOGT (LOGD_DEVICE, "mtu: commit-mtu... skip due to state %s", nm_device_state_to_str (state)); } @@ -7955,16 +7928,21 @@ ndisc_ra_timeout (NMNDisc *ndisc, NMDevice *self) * ever receive one, then time out IPv6. But if there is other * IPv6 configuration, like manual IPv6 addresses or external IPv6 * config, consider that sufficient for IPv6 success. + * + * FIXME: it doesn't seem correct to determine this based on which + * addresses we find inside priv->ip_config_6. */ - if ( priv->ip6_config - && nm_ip6_config_get_address_first_nontentative (priv->ip6_config, FALSE)) + if ( priv->ip_config_6 + && nm_ip6_config_find_first_address (priv->ip_config_6, + NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL + | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)) nm_device_activate_schedule_ip6_config_result (self); else nm_device_activate_schedule_ip6_config_timeout (self); } } -static gboolean +static void addrconf6_start_with_link_ready (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -7982,9 +7960,9 @@ addrconf6_start_with_link_ready (NMDevice *self) } /* Apply any manual configuration before starting RA */ - if (!ip6_config_merge_and_apply (self, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) { _LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration"); - g_clear_object (&priv->con_ip6_config); + g_clear_object (&priv->con_ip_config_6); } /* FIXME: These sysctls would probably be better set by the lndp ndisc itself. */ @@ -8018,7 +7996,7 @@ addrconf6_start_with_link_ready (NMDevice *self) ndisc_set_router_config (priv->ndisc, self); nm_ndisc_start (priv->ndisc); - return TRUE; + return; } static NMNDiscNodeType @@ -8041,7 +8019,6 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; - NMActStageReturn ret; NMSettingIP6Config *s_ip6 = NULL; GError *error = NULL; NMUtilsStableType stable_type; @@ -8088,15 +8065,14 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) nm_device_add_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, TRUE); /* ensure link local is ready... */ - ret = linklocal6_start (self); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { - /* success; wait for the LL address to show up */ + if (!linklocal6_start (self)) { + /* wait for the LL address to show up */ return TRUE; } - /* success; already have the LL address; kick off neighbor discovery */ - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); - return addrconf6_start_with_link_ready (self); + /* already have the LL address; kick off neighbor discovery */ + addrconf6_start_with_link_ready (self); + return TRUE; } static void @@ -8163,7 +8139,8 @@ restore_ip6_properties (NMDevice *self) g_hash_table_iter_init (&iter, priv->ip6_saved_properties); while (g_hash_table_iter_next (&iter, &key, &value)) { /* Don't touch "disable_ipv6" if we're doing userland IPv6LL */ - if (priv->nm_ipv6ll && strcmp (key, "disable_ipv6") == 0) + if ( priv->ipv6ll_handle + && nm_streq (key, "disable_ipv6")) continue; nm_device_ipv6_sysctl_set (self, key, value); } @@ -8173,7 +8150,7 @@ static inline void set_disable_ipv6 (NMDevice *self, const char *value) { /* We only touch disable_ipv6 when NM is not managing the IPv6LL address */ - if (NM_DEVICE_GET_PRIVATE (self)->nm_ipv6ll == FALSE) + if (!NM_DEVICE_GET_PRIVATE (self)->ipv6ll_handle) nm_device_ipv6_sysctl_set (self, "disable_ipv6", value); } @@ -8188,7 +8165,7 @@ set_nm_ipv6ll (NMDevice *self, gboolean enable) NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) return; - priv->nm_ipv6ll = enable; + priv->ipv6ll_handle = enable; if (ifindex > 0) { NMPlatformError plerr; const char *detail = enable ? "enable" : "disable"; @@ -8337,14 +8314,14 @@ act_stage3_ip6_config_start (NMDevice *self, if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) == 0) { if ( !priv->master && !nm_device_sys_iface_state_is_external (self)) { - gboolean old_nm_ipv6ll = priv->nm_ipv6ll; + gboolean ipv6ll_handle_old = priv->ipv6ll_handle; /* When activating an IPv6 'ignore' connection we need to revert back * to kernel IPv6LL, but the kernel won't actually assign an address * to the interface until disable_ipv6 is bounced. */ set_nm_ipv6ll (self, FALSE); - if (old_nm_ipv6ll == TRUE) + if (ipv6ll_handle_old) nm_device_ipv6_sysctl_set (self, "disable_ipv6", "1"); restore_ip6_properties (self); } @@ -8355,7 +8332,7 @@ act_stage3_ip6_config_start (NMDevice *self, * expose any ipv6 sysctls or allow presence of any addresses on the interface, * including LL, which * would make it impossible to autoconfigure MTU to a * correct value. */ - _commit_mtu (self, priv->ip4_config); + _commit_mtu (self, priv->ip_config_4); /* Any method past this point requires an IPv6LL address. Use NM-controlled * IPv6LL if this is not an assumed connection, since assumed connections @@ -8376,7 +8353,6 @@ act_stage3_ip6_config_start (NMDevice *self, priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self), nm_device_get_platform (self), nm_device_get_ip_ifindex (self), - FALSE, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); ip6_privacy = _ip6_privacy_get (self); @@ -8389,7 +8365,9 @@ act_stage3_ip6_config_start (NMDevice *self, } else ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) { - ret = linklocal6_start (self); + ret = linklocal6_start (self) + ? NM_ACT_STAGE_RETURN_SUCCESS + : NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) { priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED; if (!dhcp6_start (self, TRUE)) { @@ -8959,7 +8937,7 @@ activate_stage5_ip4_config_result (NMDevice *self) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - if (!ip4_config_merge_and_apply (self, TRUE)) { + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; @@ -8971,7 +8949,7 @@ activate_stage5_ip4_config_result (NMDevice *self) if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { gs_free_error GError *error = NULL; - if (!start_sharing (self, priv->ip4_config, &error)) { + if (!start_sharing (self, priv->ip_config_4, &error)) { _LOGW (LOGD_SHARING, "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s", error->message); nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); return; @@ -9042,8 +9020,8 @@ dad6_get_pending_addresses (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMIP6Config *confs[] = { (NMIP6Config *) applied_config_get_current (&priv->ac_ip6_config), (NMIP6Config *) applied_config_get_current (&priv->dhcp6.ip6_config), - priv->con_ip6_config, - (NMIP6Config *) applied_config_get_current (&priv->wwan_ip6_config) }; + priv->con_ip_config_6, + (NMIP6Config *) applied_config_get_current (&priv->wwan_ip_config_6) }; const NMPlatformIP6Address *addr, *pl_addr; NMIP6Config *dad6_config = NULL; NMDedupMultiIter ipconf_iter; @@ -9107,7 +9085,7 @@ activate_stage5_ip6_config_commit (NMDevice *self) _LOGW (LOGD_DEVICE, "interface %s not up for IP configuration", nm_device_get_ip_iface (self)); } - if (ip6_config_merge_and_apply (self, TRUE)) { + if (ip_config_merge_and_apply (self, AF_INET6, TRUE)) { if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE && priv->ip6_state == IP_CONF) { if (applied_config_get_current (&priv->dhcp6.ip6_config)) { @@ -9277,9 +9255,9 @@ _update_ip4_address (NMDevice *self) g_return_if_fail (NM_IS_DEVICE (self)); - if ( priv->ip4_config + if ( priv->ip_config_4 && ip_config_valid (priv->state) - && (address = nm_ip4_config_get_first_address (priv->ip4_config))) { + && (address = nm_ip4_config_get_first_address (priv->ip_config_4))) { if (address->address != priv->ip4_address) { priv->ip4_address = address->address; _notify (self, PROP_IP4_ADDRESS); @@ -9373,37 +9351,31 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) } static void -_cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type) +_cleanup_ip_pre (NMDevice *self, int addr_family, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const gboolean IS_IPv4 = (addr_family == AF_INET); - _set_ip_state (self, AF_INET, IP_NONE); - - if (nm_clear_g_source (&priv->queued_ip4_config_id)) - _LOGD (LOGD_DEVICE, "clearing queued IP4 config change"); - priv->queued_ip4_config_pending = FALSE; + _set_ip_state (self, addr_family, IP_NONE); - dhcp4_cleanup (self, cleanup_type, FALSE); - arp_cleanup (self); - dnsmasq_cleanup (self); - ipv4ll_cleanup (self); -} - -static void -_cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - _set_ip_state (self, AF_INET6, IP_NONE); - - if (nm_clear_g_source (&priv->queued_ip6_config_id)) - _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); - priv->queued_ip6_config_pending = FALSE; + if (nm_clear_g_source (&priv->queued_ip_config_id_x[IS_IPv4])) { + _LOGD (LOGD_DEVICE, "clearing queued IP%c config change", + nm_utils_addr_family_to_char (addr_family)); + } - g_clear_object (&priv->dad6_ip6_config); - dhcp6_cleanup (self, cleanup_type, FALSE); - linklocal6_cleanup (self); - addrconf6_cleanup (self); + if (IS_IPv4) { + priv->queued_ip4_config_pending = FALSE; + dhcp4_cleanup (self, cleanup_type, FALSE); + arp_cleanup (self); + dnsmasq_cleanup (self); + ipv4ll_cleanup (self); + } else { + priv->queued_ip6_config_pending = FALSE; + g_clear_object (&priv->dad6_ip6_config); + dhcp6_cleanup (self, cleanup_type, FALSE); + nm_clear_g_source (&priv->linklocal6_timeout_id); + addrconf6_cleanup (self); + } } gboolean @@ -9482,12 +9454,12 @@ nm_device_reactivate_ip4_config (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ip4_state != IP_NONE) { - g_clear_object (&priv->con_ip4_config); - g_clear_object (&priv->ext_ip4_config); + g_clear_object (&priv->con_ip_config_4); + g_clear_object (&priv->ext_ip_config_4); g_clear_object (&priv->dev_ip4_config.current); - g_clear_object (&priv->wwan_ip4_config.current); - priv->con_ip4_config = _ip4_config_new (self); - nm_ip4_config_merge_setting (priv->con_ip4_config, + g_clear_object (&priv->wwan_ip_config_4.current); + priv->con_ip_config_4 = _ip4_config_new (self); + nm_ip4_config_merge_setting (priv->con_ip_config_4, s_ip4_new, _get_mdns (self), nm_device_get_route_table (self, AF_INET, TRUE), @@ -9501,12 +9473,12 @@ nm_device_reactivate_ip4_config (NMDevice *self, : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; if (!nm_streq0 (method_old, method_new)) { - _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip_pre (self, AF_INET, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET, IP_WAIT); if (!nm_device_activate_stage3_ip4_start (self)) _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); } else { - if (!ip4_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv4 configuration"); } } @@ -9524,13 +9496,13 @@ nm_device_reactivate_ip6_config (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); if (priv->ip6_state != IP_NONE) { - g_clear_object (&priv->con_ip6_config); - g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->con_ip_config_6); + g_clear_object (&priv->ext_ip_config_6); g_clear_object (&priv->ac_ip6_config.current); g_clear_object (&priv->dhcp6.ip6_config.current); - g_clear_object (&priv->wwan_ip6_config.current); - priv->con_ip6_config = _ip6_config_new (self); - nm_ip6_config_merge_setting (priv->con_ip6_config, + g_clear_object (&priv->wwan_ip_config_6.current); + priv->con_ip_config_6 = _ip6_config_new (self); + nm_ip6_config_merge_setting (priv->con_ip_config_6, s_ip6_new, nm_device_get_route_table (self, AF_INET6, TRUE), nm_device_get_route_metric (self, AF_INET6)); @@ -9543,12 +9515,12 @@ nm_device_reactivate_ip6_config (NMDevice *self, : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; if (!nm_streq0 (method_old, method_new)) { - _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip_pre (self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); _set_ip_state (self, AF_INET6, IP_WAIT); if (!nm_device_activate_stage3_ip6_start (self)) _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); } else { - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP4, "Failed to reapply IPv6 configuration"); } } @@ -10488,95 +10460,132 @@ nm_device_get_ip4_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->ip4_config; + return NM_DEVICE_GET_PRIVATE (self)->ip_config_4; } static gboolean -nm_device_set_ip4_config (NMDevice *self, - NMIP4Config *new_config, - gboolean commit, - GPtrArray *ip4_dev_route_blacklist) +nm_device_set_ip_config (NMDevice *self, + int addr_family, + NMIPConfig *new_config, + gboolean commit, + GPtrArray *ip4_dev_route_blacklist) { - NMDevicePrivate *priv; - NMIP4Config *old_config = NULL; + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const gboolean IS_IPv4 = (addr_family == AF_INET); + NMIPConfig *old_config; gboolean has_changes = FALSE; gboolean success = TRUE; + NMSettingsConnection *settings_connection; - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - _LOGD (LOGD_IP4, "ip4-config: update (commit=%d, new-config=%p)", - commit, new_config); - + nm_assert_addr_family (addr_family); + nm_assert (!new_config || nm_ip_config_get_addr_family (new_config) == addr_family); nm_assert ( !new_config || ( new_config && ({ int ip_ifindex = nm_device_get_ip_ifindex (self); ( ip_ifindex > 0 - && ip_ifindex == nm_ip4_config_get_ifindex (new_config)); + && ip_ifindex == nm_ip_config_get_ifindex (new_config)); }))); + nm_assert (IS_IPv4 || !ip4_dev_route_blacklist); - priv = NM_DEVICE_GET_PRIVATE (self); - - old_config = priv->ip4_config; + _LOGD (LOGD_IP_from_af (addr_family), + "ip%c-config: update (commit=%d, new-config=%p)", + nm_utils_addr_family_to_char (addr_family), + commit, + new_config); /* Always commit to nm-platform to update lifetimes */ if (commit && new_config) { - _commit_mtu (self, new_config); - success = nm_ip4_config_commit (new_config, - nm_device_get_platform (self), - nm_device_get_route_table (self, AF_INET, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN); - nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), - nm_ip4_config_get_ifindex (new_config), - ip4_dev_route_blacklist); - } - - if (new_config) { - if (old_config) { - /* has_changes is set only on relevant changes, because when the configuration changes, - * this causes a re-read and reset. This should only happen for relevant changes */ - nm_ip4_config_replace (old_config, new_config, &has_changes); - if (has_changes) { - _LOGD (LOGD_IP4, "ip4-config: update IP4Config instance (%s)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); - } + + _commit_mtu (self, + IS_IPv4 + ? NM_IP4_CONFIG (new_config) + : priv->ip_config_4); + + if (IS_IPv4) { + success = nm_ip4_config_commit (NM_IP4_CONFIG (new_config), + nm_device_get_platform (self), + nm_device_get_route_table (self, addr_family, FALSE) + ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL + : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN); + nm_platform_ip4_dev_route_blacklist_set (nm_device_get_platform (self), + nm_ip_config_get_ifindex (new_config), + ip4_dev_route_blacklist); } else { - has_changes = TRUE; - priv->ip4_config = g_object_ref (new_config); + gs_unref_ptrarray GPtrArray *temporary_not_available = NULL; - if (success && !nm_dbus_object_is_exported (NM_DBUS_OBJECT (new_config))) - nm_dbus_object_export (NM_DBUS_OBJECT (new_config)); + success = nm_ip6_config_commit (NM_IP6_CONFIG (new_config), + nm_device_get_platform (self), + nm_device_get_route_table (self, addr_family, FALSE) + ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL + : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, + &temporary_not_available); - _LOGD (LOGD_IP4, "ip4-config: set IP4Config instance (%s)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_config))); + if (!_rt6_temporary_not_available_set (self, temporary_not_available)) + success = FALSE; } - } else if (old_config) { + } + + old_config = priv->ip_config_x[IS_IPv4]; + + if (new_config && old_config) { + /* has_changes is set only on relevant changes, because when the configuration changes, + * this causes a re-read and reset. This should only happen for relevant changes */ + nm_ip_config_replace (old_config, new_config, &has_changes); + if (has_changes) { + _LOGD (LOGD_IP_from_af (addr_family), + "ip%c-config: update IP Config instance (%s)", + nm_utils_addr_family_to_char (addr_family), + nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); + } + } else if (new_config /*&& !old_config*/) { + has_changes = TRUE; + priv->ip_config_x[IS_IPv4] = g_object_ref (new_config); + if (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (new_config))) + nm_dbus_object_export (NM_DBUS_OBJECT (new_config)); + + _LOGD (LOGD_IP_from_af (addr_family), + "ip%c-config: set IP Config instance (%s)", + nm_utils_addr_family_to_char (addr_family), + nm_dbus_object_get_path (NM_DBUS_OBJECT (new_config))); + } else if (old_config /*&& !new_config*/) { has_changes = TRUE; - priv->ip4_config = NULL; - _LOGD (LOGD_IP4, "ip4-config: clear IP4Config instance (%s)", + priv->ip_config_x[IS_IPv4] = NULL; + _LOGD (LOGD_IP_from_af (addr_family), + "ip%c-config: clear IP Config instance (%s)", + nm_utils_addr_family_to_char (addr_family), nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); - /* Device config is invalid if combined config is invalid */ - applied_config_clear (&priv->dev_ip4_config); + if (IS_IPv4) { + /* Device config is invalid if combined config is invalid */ + applied_config_clear (&priv->dev_ip4_config); + } else + priv->needs_ip6_subnet = FALSE; } - concheck_periodic_update (self); + if (IS_IPv4) { + concheck_periodic_update (self); - if (!nm_device_sys_iface_state_is_external_or_assume (self)) - ip4_rp_filter_update (self); + if (!nm_device_sys_iface_state_is_external_or_assume (self)) + ip4_rp_filter_update (self); + } if (has_changes) { - NMSettingsConnection *settings_connection; - _update_ip4_address (self); + if (IS_IPv4) + _update_ip4_address (self); - if (old_config != priv->ip4_config) - _notify (self, PROP_IP4_CONFIG); - g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config); + if (old_config != priv->ip_config_x[IS_IPv4]) + _notify (self, IS_IPv4 ? PROP_IP4_CONFIG : PROP_IP6_CONFIG); - if (old_config != priv->ip4_config) + g_signal_emit (self, + signals[IS_IPv4 ? IP4_CONFIG_CHANGED : IP6_CONFIG_CHANGED], + 0, + priv->ip_config_x[IS_IPv4], + old_config); + + if (old_config != priv->ip_config_x[IS_IPv4]) nm_dbus_object_clear_and_unexport (&old_config); if ( nm_device_sys_iface_state_is_external (self) @@ -10584,20 +10593,24 @@ nm_device_set_ip4_config (NMDevice *self, && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { - NMSetting *s_ip4; - g_object_freeze_notify (G_OBJECT (settings_connection)); - - nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP4_CONFIG); - s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); - nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip4); - + nm_connection_add_setting (NM_CONNECTION (settings_connection), + IS_IPv4 + ? nm_ip4_config_create_setting (priv->ip_config_4) + : nm_ip6_config_create_setting (priv->ip_config_6)); g_object_thaw_notify (G_OBJECT (settings_connection)); } nm_device_queue_recheck_assume (self); + + if (!IS_IPv4) { + if (priv->ndisc) + ndisc_set_router_config (priv->ndisc, self); + } } + nm_assert (!old_config || old_config == priv->ip_config_x[IS_IPv4]); + return success; } @@ -10644,11 +10657,11 @@ nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *co nm_assert (!old || nm_ip4_config_get_ifindex (old) == nm_device_get_ip_ifindex (self)); nm_assert (!config || nm_ip4_config_get_ifindex (config) == nm_device_get_ip_ifindex (self)); - if (!_replace_vpn_config_in_list (&priv->vpn4_configs, (GObject *) old, (GObject *) config)) + if (!_replace_vpn_config_in_list (&priv->vpn_configs_4, (GObject *) old, (GObject *) config)) return; /* NULL to use existing configs */ - if (!ip4_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "failed to set VPN routes for device"); } @@ -10657,118 +10670,11 @@ nm_device_set_wwan_ip4_config (NMDevice *self, NMIP4Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - applied_config_init (&priv->wwan_ip4_config, config); - if (!ip4_config_merge_and_apply (self, TRUE)) + applied_config_init (&priv->wwan_ip_config_4, config); + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "failed to set WWAN IPv4 configuration"); } -static gboolean -nm_device_set_ip6_config (NMDevice *self, - NMIP6Config *new_config, - gboolean commit) -{ - NMDevicePrivate *priv; - NMIP6Config *old_config = NULL; - gboolean has_changes = FALSE; - gboolean success = TRUE; - - g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); - - _LOGD (LOGD_IP6, "ip6-config: update (commit=%d, new-config=%p)", - commit, new_config); - - nm_assert ( !new_config - || ( new_config - && ({ - int ip_ifindex = nm_device_get_ip_ifindex (self); - - ( ip_ifindex > 0 - && ip_ifindex == nm_ip6_config_get_ifindex (new_config)); - }))); - - priv = NM_DEVICE_GET_PRIVATE (self); - - old_config = priv->ip6_config; - - /* Always commit to nm-platform to update lifetimes */ - if (commit && new_config) { - gs_unref_ptrarray GPtrArray *temporary_not_available = NULL; - - _commit_mtu (self, priv->ip4_config); - - success = nm_ip6_config_commit (new_config, - nm_device_get_platform (self), - nm_device_get_route_table (self, AF_INET6, FALSE) - ? NM_IP_ROUTE_TABLE_SYNC_MODE_FULL - : NM_IP_ROUTE_TABLE_SYNC_MODE_MAIN, - &temporary_not_available); - - if (!_rt6_temporary_not_available_set (self, temporary_not_available)) - success = FALSE; - } - - if (new_config) { - if (old_config) { - /* has_changes is set only on relevant changes, because when the configuration changes, - * this causes a re-read and reset. This should only happen for relevant changes */ - nm_ip6_config_replace (old_config, new_config, &has_changes); - if (has_changes) { - _LOGD (LOGD_IP6, "ip6-config: update IP6Config instance (%s)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); - } - } else { - has_changes = TRUE; - priv->ip6_config = g_object_ref (new_config); - - if (success && !nm_dbus_object_is_exported (NM_DBUS_OBJECT (new_config))) - nm_dbus_object_export (NM_DBUS_OBJECT (new_config)); - - _LOGD (LOGD_IP6, "ip6-config: set IP6Config instance (%s)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (new_config))); - } - } else if (old_config) { - has_changes = TRUE; - priv->ip6_config = NULL; - priv->needs_ip6_subnet = FALSE; - _LOGD (LOGD_IP6, "ip6-config: clear IP6Config instance (%s)", - nm_dbus_object_get_path (NM_DBUS_OBJECT (old_config))); - } - - if (has_changes) { - NMSettingsConnection *settings_connection; - - if (old_config != priv->ip6_config) - _notify (self, PROP_IP6_CONFIG); - g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); - - if (old_config != priv->ip6_config) - nm_dbus_object_clear_and_unexport (&old_config); - - if ( nm_device_sys_iface_state_is_external (self) - && (settings_connection = nm_device_get_settings_connection (self)) - && NM_FLAGS_HAS (nm_settings_connection_get_flags (settings_connection), - NM_SETTINGS_CONNECTION_FLAGS_NM_GENERATED) - && nm_active_connection_get_activation_type (NM_ACTIVE_CONNECTION (priv->act_request)) == NM_ACTIVATION_TYPE_EXTERNAL) { - NMSetting *s_ip6; - - g_object_freeze_notify (G_OBJECT (settings_connection)); - - nm_connection_remove_setting (NM_CONNECTION (settings_connection), NM_TYPE_SETTING_IP6_CONFIG); - s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); - nm_connection_add_setting (NM_CONNECTION (settings_connection), s_ip6); - - g_object_thaw_notify (G_OBJECT (settings_connection)); - } - - nm_device_queue_recheck_assume (self); - - if (priv->ndisc) - ndisc_set_router_config (priv->ndisc, self); - } - - return success; -} - void nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *config) { @@ -10779,11 +10685,11 @@ nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *co nm_assert (!old || nm_ip6_config_get_ifindex (old) == nm_device_get_ip_ifindex (self)); nm_assert (!config || nm_ip6_config_get_ifindex (config) == nm_device_get_ip_ifindex (self)); - if (!_replace_vpn_config_in_list (&priv->vpn6_configs, (GObject *) old, (GObject *) config)) + if (!_replace_vpn_config_in_list (&priv->vpn_configs_6, (GObject *) old, (GObject *) config)) return; /* NULL to use existing configs */ - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed to set VPN routes for device"); } @@ -10792,8 +10698,8 @@ nm_device_set_wwan_ip6_config (NMDevice *self, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - applied_config_init (&priv->wwan_ip6_config, config); - if (!ip6_config_merge_and_apply (self, TRUE)) + applied_config_init (&priv->wwan_ip_config_6, config); + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed to set WWAN IPv6 configuration"); } @@ -10810,7 +10716,7 @@ nm_device_get_ip6_config (NMDevice *self) { g_return_val_if_fail (NM_IS_DEVICE (self), NULL); - return NM_DEVICE_GET_PRIVATE (self)->ip6_config; + return NM_DEVICE_GET_PRIVATE (self)->ip_config_6; } /*****************************************************************************/ @@ -11044,15 +10950,15 @@ nm_device_start_ip_check (NMDevice *self) if (timeout) { const NMPObject *gw; - if (priv->ip4_config && priv->ip4_state == IP_DONE) { - gw = nm_ip4_config_best_default_route_get (priv->ip4_config); + if (priv->ip_config_4 && priv->ip4_state == IP_DONE) { + gw = nm_ip4_config_best_default_route_get (priv->ip_config_4); if (gw) { nm_utils_inet4_ntop (NMP_OBJECT_CAST_IP4_ROUTE (gw)->gateway, buf); ping_binary = nm_utils_find_helper ("ping", "/usr/bin/ping", NULL); log_domain = LOGD_IP4; } - } else if (priv->ip6_config && priv->ip6_state == IP_DONE) { - gw = nm_ip6_config_best_default_route_get (priv->ip6_config); + } else if (priv->ip_config_6 && priv->ip6_state == IP_DONE) { + gw = nm_ip6_config_best_default_route_get (priv->ip_config_6); if (gw) { nm_utils_inet6_ntop (&NMP_OBJECT_CAST_IP6_ROUTE (gw)->gateway, buf); ping_binary = nm_utils_find_helper ("ping6", "/usr/bin/ping6", NULL); @@ -11192,11 +11098,11 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware) /* when the link comes up, we must restore IP configuration if necessary. */ if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET, TRUE)) _LOGW (LOGD_IP4, "failed applying IP4 config after bringing link up"); } if (priv->ip6_state == IP_DONE) { - if (!ip6_config_merge_and_apply (self, TRUE)) + if (!ip_config_merge_and_apply (self, AF_INET6, TRUE)) _LOGW (LOGD_IP6, "failed applying IP6 config after bringing link up"); } @@ -11261,116 +11167,6 @@ nm_device_get_firmware_missing (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->firmware_missing; } -static NMIP4Config * -find_ip4_lease_config (NMDevice *self, - NMConnection *connection, - NMIP4Config *ext_ip4_config) -{ - const char *ip_iface = nm_device_get_ip_iface (self); - int ip_ifindex = nm_device_get_ip_ifindex (self); - GSList *leases, *liter; - NMIP4Config *found = NULL; - - g_return_val_if_fail (NM_IS_IP4_CONFIG (ext_ip4_config), NULL); - g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - - leases = nm_dhcp_manager_get_lease_ip_configs (nm_dhcp_manager_get (), - nm_device_get_multi_index (self), - AF_INET, - ip_iface, - ip_ifindex, - nm_connection_get_uuid (connection), - nm_device_get_route_table (self, AF_INET, TRUE), - nm_device_get_route_metric (self, AF_INET)); - for (liter = leases; liter && !found; liter = liter->next) { - NMIP4Config *lease_config = liter->data; - const NMPlatformIP4Address *address = nm_ip4_config_get_first_address (lease_config); - const NMPObject *gw1, *gw2; - - g_assert (address); - if (!nm_ip4_config_address_exists (ext_ip4_config, address)) - continue; - gw1 = nm_ip4_config_best_default_route_get (lease_config); - if (!gw1) - continue; - gw2 = nm_ip4_config_best_default_route_get (ext_ip4_config); - if (!gw2) - continue; - if (NMP_OBJECT_CAST_IP4_ROUTE (gw1)->gateway != NMP_OBJECT_CAST_IP4_ROUTE (gw2)->gateway) - continue; - found = g_object_ref (lease_config); - } - - g_slist_free_full (leases, g_object_unref); - return found; -} - -static void -capture_lease_config (NMDevice *self, - NMIP4Config *ext_ip4_config, - NMIP4Config **out_ip4_config, - NMIP6Config *ext_ip6_config, - NMIP6Config **out_ip6_config) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMSettingsConnection *const*connections; - guint i; - gboolean dhcp_used = FALSE; - NMDedupMultiIter ipconf_iter; - - /* Ensure at least one address on the device has a non-infinite lifetime, - * otherwise DHCP cannot possibly be active on the device right now. - */ - if (ext_ip4_config && out_ip4_config) { - const NMPlatformIP4Address *addr; - - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ext_ip4_config, &addr) { - if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { - dhcp_used = TRUE; - break; - } - } - } else if (ext_ip6_config && out_ip6_config) { - const NMPlatformIP6Address *addr; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ext_ip6_config, &addr) { - if (addr->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) { - dhcp_used = TRUE; - break; - } - } - } else { - g_return_if_fail ( (ext_ip6_config && out_ip6_config) - || (ext_ip4_config && out_ip4_config)); - } - - if (!dhcp_used) - return; - - connections = nm_settings_get_connections (priv->settings, NULL); - for (i = 0; connections[i]; i++) { - NMConnection *candidate = (NMConnection *) connections[i]; - const char *method; - - if (!nm_device_check_connection_compatible (self, candidate)) - continue; - - /* IPv4 leases */ - method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP4_CONFIG); - if (out_ip4_config && strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) { - *out_ip4_config = find_ip4_lease_config (self, candidate, ext_ip4_config); - if (*out_ip4_config) - return; - } - - /* IPv6 leases */ - method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG); - if (out_ip6_config && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) { - /* FIXME: implement find_ip6_lease_config() */ - } - } -} - static void intersect_ext_config (NMDevice *self, AppliedConfig *config) { @@ -11385,8 +11181,8 @@ intersect_ext_config (NMDevice *self, AppliedConfig *config) family = nm_ip_config_get_addr_family (config->orig); penalty = default_route_metric_penalty_get (self, family); ext = family == AF_INET - ? (NMIPConfig *) priv->ext_ip4_config - : (NMIPConfig *) priv->ext_ip6_config; + ? (NMIPConfig *) priv->ext_ip_config_4 + : (NMIPConfig *) priv->ext_ip_config_6; if (config->current) nm_ip_config_intersect (config->current, ext, penalty); @@ -11398,11 +11194,10 @@ intersect_ext_config (NMDevice *self, AppliedConfig *config) } static gboolean -update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolean intersect_configs) +update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_configs) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex; - gboolean capture_resolv_conf; GSList *iter; nm_assert_addr_family (addr_family); @@ -11411,119 +11206,106 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea if (!ifindex) return FALSE; - capture_resolv_conf = initial - && nm_dns_manager_get_resolv_conf_explicit (nm_dns_manager_get ()); - if (addr_family == AF_INET) { - g_clear_object (&priv->ext_ip4_config); - priv->ext_ip4_config = nm_ip4_config_capture (nm_device_get_multi_index (self), + g_clear_object (&priv->ext_ip_config_4); + priv->ext_ip_config_4 = nm_ip4_config_capture (nm_device_get_multi_index (self), nm_device_get_platform (self), - ifindex, - capture_resolv_conf); - if (priv->ext_ip4_config) { - if (initial) { - applied_config_clear (&priv->dev_ip4_config); - capture_lease_config (self, - priv->ext_ip4_config, - (NMIP4Config **) &priv->dev_ip4_config.orig, - NULL, NULL); - } - + ifindex); + if (priv->ext_ip_config_4) { if (intersect_configs) { /* This function was called upon external changes. Remove the configuration * (addresses,routes) that is no longer present externally from the internal * config. This way, we don't re-add addresses that were manually removed * by the user. */ - if (priv->con_ip4_config) { - nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config, + if (priv->con_ip_config_4) { + nm_ip4_config_intersect (priv->con_ip_config_4, priv->ext_ip_config_4, default_route_metric_penalty_get (self, AF_INET)); } intersect_ext_config (self, &priv->dev_ip4_config); - intersect_ext_config (self, &priv->wwan_ip4_config); + intersect_ext_config (self, &priv->wwan_ip_config_4); - for (iter = priv->vpn4_configs; iter; iter = iter->next) - nm_ip4_config_intersect (iter->data, priv->ext_ip4_config, 0); + for (iter = priv->vpn_configs_4; iter; iter = iter->next) + nm_ip4_config_intersect (iter->data, priv->ext_ip_config_4, 0); } - /* Remove parts from ext_ip4_config to only contain the information that + /* Remove parts from ext_ip_config_4 to only contain the information that * was configured externally -- we already have the same configuration from * internal origins. */ - if (priv->con_ip4_config) { - nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config, + if (priv->con_ip_config_4) { + nm_ip4_config_subtract (priv->ext_ip_config_4, priv->con_ip_config_4, default_route_metric_penalty_get (self, AF_INET)); } if (applied_config_get_current (&priv->dev_ip4_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip4_config, + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_4, applied_config_get_current (&priv->dev_ip4_config), default_route_metric_penalty_get (self, AF_INET)); } - if (applied_config_get_current (&priv->wwan_ip4_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip4_config, - applied_config_get_current (&priv->wwan_ip4_config), + if (applied_config_get_current (&priv->wwan_ip_config_4)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_4, + applied_config_get_current (&priv->wwan_ip_config_4), default_route_metric_penalty_get (self, AF_INET)); } - for (iter = priv->vpn4_configs; iter; iter = iter->next) - nm_ip4_config_subtract (priv->ext_ip4_config, iter->data, 0); + for (iter = priv->vpn_configs_4; iter; iter = iter->next) + nm_ip4_config_subtract (priv->ext_ip_config_4, iter->data, 0); } } else { nm_assert (addr_family == AF_INET6); - g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->ext_ip_config_6); g_clear_object (&priv->ext_ip6_config_captured); priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self), nm_device_get_platform (self), ifindex, - capture_resolv_conf, NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN); if (priv->ext_ip6_config_captured) { - priv->ext_ip6_config = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); + priv->ext_ip_config_6 = nm_ip6_config_new_cloned (priv->ext_ip6_config_captured); if (intersect_configs) { /* This function was called upon external changes. Remove the configuration * (addresses,routes) that is no longer present externally from the internal * config. This way, we don't re-add addresses that were manually removed * by the user. */ - if (priv->con_ip6_config) { - nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config, + if (priv->con_ip_config_6) { + nm_ip6_config_intersect (priv->con_ip_config_6, priv->ext_ip_config_6, default_route_metric_penalty_get (self, AF_INET6)); } intersect_ext_config (self, &priv->ac_ip6_config); intersect_ext_config (self, &priv->dhcp6.ip6_config); - intersect_ext_config (self, &priv->wwan_ip6_config); + intersect_ext_config (self, &priv->wwan_ip_config_6); - for (iter = priv->vpn6_configs; iter; iter = iter->next) - nm_ip6_config_intersect (iter->data, priv->ext_ip6_config, 0); + for (iter = priv->vpn_configs_6; iter; iter = iter->next) + nm_ip6_config_intersect (iter->data, priv->ext_ip_config_6, 0); } - /* Remove parts from ext_ip6_config to only contain the information that + /* Remove parts from ext_ip_config_6 to only contain the information that * was configured externally -- we already have the same configuration from * internal origins. */ - if (priv->con_ip6_config) { - nm_ip6_config_subtract (priv->ext_ip6_config, priv->con_ip6_config, + if (priv->con_ip_config_6) { + nm_ip6_config_subtract (priv->ext_ip_config_6, priv->con_ip_config_6, default_route_metric_penalty_get (self, AF_INET6)); } if (applied_config_get_current (&priv->ac_ip6_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, applied_config_get_current (&priv->ac_ip6_config), default_route_metric_penalty_get (self, AF_INET6)); } if (applied_config_get_current (&priv->dhcp6.ip6_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, applied_config_get_current (&priv->dhcp6.ip6_config), default_route_metric_penalty_get (self, AF_INET6)); } - if (applied_config_get_current (&priv->wwan_ip6_config)) { - nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip6_config, - applied_config_get_current (&priv->wwan_ip6_config), + if (applied_config_get_current (&priv->wwan_ip_config_6)) { + nm_ip_config_subtract ((NMIPConfig *) priv->ext_ip_config_6, + applied_config_get_current (&priv->wwan_ip_config_6), default_route_metric_penalty_get (self, AF_INET6)); } - for (iter = priv->vpn6_configs; iter; iter = iter->next) - nm_ip6_config_subtract (priv->ext_ip6_config, iter->data, 0); + for (iter = priv->vpn_configs_6; iter; iter = iter->next) + nm_ip6_config_subtract (priv->ext_ip_config_6, iter->data, 0); } } @@ -11531,163 +11313,139 @@ update_ext_ip_config (NMDevice *self, int addr_family, gboolean initial, gboolea } static void -update_ip_config (NMDevice *self, int addr_family, gboolean initial) +update_ip_config (NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); nm_assert_addr_family (addr_family); - if (update_ext_ip_config (self, addr_family, initial, TRUE)) { + if (addr_family == AF_INET) + priv->update_ip_config_completed_v4 = TRUE; + else + priv->update_ip_config_completed_v6 = TRUE; + + if (update_ext_ip_config (self, addr_family, TRUE)) { if (addr_family == AF_INET) { - if (priv->ext_ip4_config) - ip4_config_merge_and_apply (self, FALSE); + if (priv->ext_ip_config_4) + ip_config_merge_and_apply (self, AF_INET, FALSE); } else { if (priv->ext_ip6_config_captured) - ip6_config_merge_and_apply (self, FALSE); + ip_config_merge_and_apply (self, AF_INET6, FALSE); } } - - if ( addr_family == AF_INET6 - && priv->linklocal6_timeout_id - && priv->ext_ip6_config_captured - && nm_ip6_config_get_address_first_nontentative (priv->ext_ip6_config_captured, TRUE)) { - /* linklocal6 is ready now, do the state transition... we are also - * invoked as g_idle_add, so no problems with reentrance doing it now. - */ - linklocal6_complete (self); - } } void nm_device_capture_initial_config (NMDevice *self) { - update_ip_config (self, AF_INET, TRUE); - update_ip_config (self, AF_INET6, TRUE); -} - -static gboolean -queued_ip4_config_change (gpointer user_data) -{ - NMDevice *self = user_data; - NMDevicePrivate *priv; - - g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); - - priv = NM_DEVICE_GET_PRIVATE (self); - - nm_assert (!priv->queued_ip4_config_pending); - - /* Wait for any queued state changes */ - if (priv->queued_state.id) - return TRUE; - - priv->queued_ip4_config_id = 0; - - /* If a commit is scheduled, this function would potentially interfere with - * it changing IP configurations before they are applied. Postpone the - * update in such case. - */ - if (activation_source_is_scheduled (self, - activate_stage5_ip4_config_result, - AF_INET)) { - priv->queued_ip4_config_pending = FALSE; - priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); - _LOGT (LOGD_DEVICE, "IP4 update was postponed"); - } else - update_ip_config (self, AF_INET, FALSE); - - set_unmanaged_external_down (self, TRUE); - - if (!nm_device_sys_iface_state_is_external_or_assume (self)) { - priv->v4_has_shadowed_routes = _v4_has_shadowed_routes_detect (self);; - ip4_rp_filter_update (self); - } + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - return FALSE; + if (!priv->update_ip_config_completed_v4) + update_ip_config (self, AF_INET); + if (!priv->update_ip_config_completed_v6) + update_ip_config (self, AF_INET6); } static gboolean -queued_ip6_config_change (gpointer user_data) +queued_ip_config_change (NMDevice *self, int addr_family) { - NMDevice *self = user_data; NMDevicePrivate *priv; gboolean need_ipv6ll = FALSE; + const gboolean IS_IPv4 = (addr_family == AF_INET); NMPlatform *platform; g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); priv = NM_DEVICE_GET_PRIVATE (self); - nm_assert (!priv->queued_ip4_config_pending); + nm_assert (IS_IPv4 ? !priv->queued_ip4_config_pending : !priv->queued_ip6_config_pending); /* Wait for any queued state changes */ if (priv->queued_state.id) - return TRUE; + return G_SOURCE_CONTINUE; - priv->queued_ip6_config_id = 0; + priv->queued_ip_config_id_x[IS_IPv4] = 0; /* If a commit is scheduled, this function would potentially interfere with * it changing IP configurations before they are applied. Postpone the * update in such case. */ if (activation_source_is_scheduled (self, - activate_stage5_ip6_config_commit, - AF_INET6)) { - priv->queued_ip6_config_pending = FALSE; - priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); - _LOGT (LOGD_DEVICE, "IP6 update was postponed"); - } else - update_ip_config (self, AF_INET6, FALSE); + IS_IPv4 + ? activate_stage5_ip4_config_result + : activate_stage5_ip6_config_commit, + addr_family)) { + if (IS_IPv4) { + priv->queued_ip4_config_pending = FALSE; + priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); + } else { + priv->queued_ip6_config_pending = FALSE; + priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); + } + _LOGT (LOGD_DEVICE, "IP%c update was postponed", + nm_utils_addr_family_to_char (addr_family)); + } else { + update_ip_config (self, addr_family); - if ( priv->state < NM_DEVICE_STATE_DEACTIVATING - && (platform = nm_device_get_platform (self)) - && nm_platform_link_get (platform, priv->ifindex)) { - /* Handle DAD failures */ - while (priv->dad6_failed_addrs) { - nm_auto_nmpobj const NMPObject *obj = NULL; - const NMPlatformIP6Address *addr; + if (!IS_IPv4) { + /* Check whether we need to complete waiting for link-local. + * We are also called from an idle handler, so no problem doing state transitions + * now. */ + linklocal6_check_complete (self); + } + } - obj = priv->dad6_failed_addrs->data; - priv->dad6_failed_addrs = g_slist_delete_link (priv->dad6_failed_addrs, priv->dad6_failed_addrs); + if (!IS_IPv4) { + if ( priv->state < NM_DEVICE_STATE_DEACTIVATING + && (platform = nm_device_get_platform (self)) + && nm_platform_link_get (platform, priv->ifindex)) { + /* Handle DAD failures */ + while (priv->dad6_failed_addrs) { + nm_auto_nmpobj const NMPObject *obj = NULL; + const NMPlatformIP6Address *addr; - if (!nm_ndisc_dad_addr_is_fail_candidate (platform, obj)) - continue; + obj = priv->dad6_failed_addrs->data; + priv->dad6_failed_addrs = g_slist_delete_link (priv->dad6_failed_addrs, priv->dad6_failed_addrs); - addr = NMP_OBJECT_CAST_IP6_ADDRESS (obj); + if (!nm_ndisc_dad_addr_is_fail_candidate (platform, obj)) + continue; - _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", - nm_platform_ip6_address_to_string (addr, NULL, 0)); + addr = NMP_OBJECT_CAST_IP6_ADDRESS (obj); - if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) - need_ipv6ll = TRUE; - else if (priv->ndisc) - nm_ndisc_dad_failed (priv->ndisc, &addr->address); - } + _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", + nm_platform_ip6_address_to_string (addr, NULL, 0)); - /* If no IPv6 link-local address exists but other addresses do then we - * must add the LL address to remain conformant with RFC 3513 chapter 2.1 - * ("Addressing Model"): "All interfaces are required to have at least - * one link-local unicast address". - */ - if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) - need_ipv6ll = TRUE; + if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) + need_ipv6ll = TRUE; + else if (priv->ndisc) + nm_ndisc_dad_failed (priv->ndisc, &addr->address); + } - if (need_ipv6ll) - check_and_add_ipv6ll_addr (self); - } else { - g_slist_free_full (priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); - priv->dad6_failed_addrs = NULL; - } + /* If no IPv6 link-local address exists but other addresses do then we + * must add the LL address to remain conformant with RFC 3513 chapter 2.1 + * ("Addressing Model"): "All interfaces are required to have at least + * one link-local unicast address". + */ + if ( priv->ip_config_6 + && nm_ip6_config_get_num_addresses (priv->ip_config_6)) + need_ipv6ll = TRUE; + + if (need_ipv6ll) + check_and_add_ipv6ll_addr (self); + } else { + g_slist_free_full (priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref); + priv->dad6_failed_addrs = NULL; + } - /* Check if DAD is still pending */ - if ( priv->ip6_state == IP_CONF - && priv->dad6_ip6_config - && priv->ext_ip6_config_captured) { - if (!nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured, - priv->dad6_ip6_config)) { + /* Check if DAD is still pending */ + if ( priv->ip6_state == IP_CONF + && priv->dad6_ip6_config + && priv->ext_ip6_config_captured + && !nm_ip6_config_has_any_dad_pending (priv->ext_ip6_config_captured, + priv->dad6_ip6_config)) { _LOGD (LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated"); g_clear_object (&priv->dad6_ip6_config); - _set_ip_state (self, AF_INET6, IP_DONE); + _set_ip_state (self, addr_family, IP_DONE); check_ip_state (self, FALSE, TRUE); if (priv->rt6_temporary_not_available) nm_device_activate_schedule_ip6_config_result (self); @@ -11696,7 +11454,26 @@ queued_ip6_config_change (gpointer user_data) set_unmanaged_external_down (self, TRUE); - return FALSE; + if (IS_IPv4) { + if (!nm_device_sys_iface_state_is_external_or_assume (self)) { + priv->v4_has_shadowed_routes = _v4_has_shadowed_routes_detect (self);; + ip4_rp_filter_update (self); + } + } + + return G_SOURCE_REMOVE; +} + +static gboolean +queued_ip4_config_change (gpointer user_data) +{ + return queued_ip_config_change (user_data, AF_INET); +} + +static gboolean +queued_ip6_config_change (gpointer user_data) +{ + return queued_ip_config_change (user_data, AF_INET6); } static void @@ -11722,10 +11499,10 @@ device_ipx_changed (NMPlatform *platform, case NMP_OBJECT_TYPE_IP4_ROUTE: if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { priv->queued_ip4_config_pending = TRUE; - nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id)); - } else if (!priv->queued_ip4_config_id) { + nm_assert_se (!nm_clear_g_source (&priv->queued_ip_config_id_4)); + } else if (!priv->queued_ip_config_id_4) { priv->queued_ip4_config_pending = FALSE; - priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); + priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); _LOGD (LOGD_DEVICE, "queued IP4 config change"); } break; @@ -11742,10 +11519,10 @@ device_ipx_changed (NMPlatform *platform, case NMP_OBJECT_TYPE_IP6_ROUTE: if (nm_device_get_unmanaged_flags (self, NM_UNMANAGED_PLATFORM_INIT)) { priv->queued_ip6_config_pending = TRUE; - nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); - } else if (!priv->queued_ip6_config_id) { + nm_assert_se (!nm_clear_g_source (&priv->queued_ip_config_id_6)); + } else if (!priv->queued_ip_config_id_6) { priv->queued_ip6_config_pending = FALSE; - priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); + priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); _LOGD (LOGD_DEVICE, "queued IP6 config change"); } break; @@ -12013,14 +11790,14 @@ _set_unmanaged_flags (NMDevice *self, if (priv->queued_ip4_config_pending) { priv->queued_ip4_config_pending = FALSE; - nm_assert_se (!nm_clear_g_source (&priv->queued_ip4_config_id)); - priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); + nm_assert_se (!nm_clear_g_source (&priv->queued_ip_config_id_4)); + priv->queued_ip_config_id_4 = g_idle_add (queued_ip4_config_change, self); } if (priv->queued_ip6_config_pending) { priv->queued_ip6_config_pending = FALSE; - nm_assert_se (!nm_clear_g_source (&priv->queued_ip6_config_id)); - priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); + nm_assert_se (!nm_clear_g_source (&priv->queued_ip_config_id_6)); + priv->queued_ip_config_id_6 = g_idle_add (queued_ip6_config_change, self); } if (!priv->pending_actions) { @@ -12354,9 +12131,9 @@ nm_device_update_metered (NMDevice *self) /* Try to guess a value using the metered flag in IP configuration */ if (value == NM_METERED_INVALID) { - if ( priv->ip4_config + if ( priv->ip_config_4 && priv->ip4_state == IP_DONE - && nm_ip4_config_get_metered (priv->ip4_config)) + && nm_ip4_config_get_metered (priv->ip_config_4)) value = NM_METERED_GUESS_YES; } @@ -12851,8 +12628,8 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) queued_state_clear (self); - _cleanup_ip4_pre (self, cleanup_type); - _cleanup_ip6_pre (self, cleanup_type); + _cleanup_ip_pre (self, AF_INET, cleanup_type); + _cleanup_ip_pre (self, AF_INET6, cleanup_type); } static void @@ -12874,31 +12651,31 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ - nm_device_set_ip4_config (self, NULL, TRUE, NULL); - nm_device_set_ip6_config (self, NULL, TRUE); + nm_device_set_ip_config (self, AF_INET, NULL, TRUE, NULL); + nm_device_set_ip_config (self, AF_INET6, NULL, TRUE, NULL); g_clear_object (&priv->proxy_config); - g_clear_object (&priv->con_ip4_config); + g_clear_object (&priv->con_ip_config_4); applied_config_clear (&priv->dev_ip4_config); - applied_config_clear (&priv->wwan_ip4_config); - g_clear_object (&priv->ext_ip4_config); - g_clear_object (&priv->ip4_config); - g_clear_object (&priv->con_ip6_config); + applied_config_clear (&priv->wwan_ip_config_4); + g_clear_object (&priv->ext_ip_config_4); + g_clear_object (&priv->ip_config_4); + g_clear_object (&priv->con_ip_config_6); applied_config_clear (&priv->ac_ip6_config); - g_clear_object (&priv->ext_ip6_config); + g_clear_object (&priv->ext_ip_config_6); g_clear_object (&priv->ext_ip6_config_captured); - applied_config_clear (&priv->wwan_ip6_config); - g_clear_object (&priv->ip6_config); + applied_config_clear (&priv->wwan_ip_config_6); + g_clear_object (&priv->ip_config_6); g_clear_object (&priv->dad6_ip6_config); g_clear_pointer (&priv->rt6_temporary_not_available, g_hash_table_unref); nm_clear_g_source (&priv->rt6_temporary_not_available_id); - g_slist_free_full (priv->vpn4_configs, g_object_unref); - priv->vpn4_configs = NULL; - g_slist_free_full (priv->vpn6_configs, g_object_unref); - priv->vpn6_configs = NULL; + g_slist_free_full (priv->vpn_configs_4, g_object_unref); + priv->vpn_configs_4 = NULL; + g_slist_free_full (priv->vpn_configs_6, g_object_unref); + priv->vpn_configs_6 = NULL; - /* We no longer accept the delegations. nm_device_set_ip6_config(NULL) + /* We no longer accept the delegations. nm_device_set_ip_config(NULL) * above disables them. */ nm_assert (priv->needs_ip6_subnet == FALSE); @@ -13048,10 +12825,10 @@ find_dhcp4_address (NMDevice *self) const NMPlatformIP4Address *a; NMDedupMultiIter ipconf_iter; - if (!priv->ip4_config) + if (!priv->ip_config_4) return NULL; - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip4_config, &a) { + nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip_config_4, &a) { if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP) return g_strdup (nm_utils_inet4_ntop (a->address, NULL)); } @@ -13466,8 +13243,8 @@ _set_state_full (NMDevice *self, /* Clean up any half-done IP operations if the device's layer2 * finds out it needs authentication during IP config. */ - _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); - _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip_pre (self, AF_INET, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip_pre (self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); } break; default: @@ -15001,13 +14778,13 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->mtu); break; case PROP_IP4_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL); + nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip_config_4 : NULL); break; case PROP_DHCP4_CONFIG: nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4.config : NULL); break; case PROP_IP6_CONFIG: - nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL); + nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip_config_6 : NULL); break; case PROP_DHCP6_CONFIG: nm_dbus_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6.config : NULL); |