diff options
Diffstat (limited to 'src/nm-policy.c')
| -rw-r--r-- | src/nm-policy.c | 714 |
1 files changed, 472 insertions, 242 deletions
diff --git a/src/nm-policy.c b/src/nm-policy.c index 7c74a6b4..3cfb1f7c 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -31,7 +31,6 @@ #include "NetworkManagerUtils.h" #include "nm-act-request.h" #include "devices/nm-device.h" -#include "nm-default-route-manager.h" #include "nm-setting-ip4-config.h" #include "nm-setting-connection.h" #include "platform/nm-platform.h" @@ -49,6 +48,7 @@ #include "nm-dhcp6-config.h" #include "nm-config.h" #include "nm-netns.h" +#include "nm-hostname-manager.h" /*****************************************************************************/ @@ -68,17 +68,23 @@ typedef struct { GSList *pending_activation_checks; GHashTable *devices; + GHashTable *pending_active_connections; GSList *pending_secondaries; NMSettings *settings; + NMHostnameManager *hostname_manager; + NMDevice *default_device4, *activating_device4; NMDevice *default_device6, *activating_device6; - GResolver *resolver; - GInetAddress *lookup_addr; - GCancellable *lookup_cancellable; + struct { + GInetAddress *addr; + GResolver *resolver; + GCancellable *cancellable; + } lookup; + NMDnsManager *dns_manager; gulong config_changed_id; @@ -136,6 +142,7 @@ _PRIV_TO_SELF (NMPolicyPrivate *priv) /*****************************************************************************/ static void schedule_activate_all (NMPolicy *self); +static void schedule_activate_check (NMPolicy *self, NMDevice *device); /*****************************************************************************/ @@ -369,25 +376,81 @@ device_ip6_subnet_needed (NMDevice *device, /*****************************************************************************/ static NMDevice * -get_best_ip4_device (NMPolicy *self, gboolean fully_activated) +get_best_ip_device (NMPolicy *self, + int addr_family, + gboolean fully_activated) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + const GSList *iter; + NMDevice *best_device; + NMDevice *prev_device; + guint32 best_metric = G_MAXUINT32; + gboolean best_is_fully_activated = FALSE; + + nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); + + /* we prefer the current device in case of identical metric. + * Hence, try that one first.*/ + best_device = NULL; + prev_device = addr_family == AF_INET + ? (fully_activated ? priv->default_device4 : priv->activating_device4) + : (fully_activated ? priv->default_device6 : priv->activating_device6); + + for (iter = nm_manager_get_devices (priv->manager); iter; iter = iter->next) { + NMDevice *device = NM_DEVICE (iter->data); + NMDeviceState state; + const NMPObject *r; + NMConnection *connection; + guint32 metric; + gboolean is_fully_activated; - return nm_default_route_manager_ip4_get_best_device (nm_netns_get_default_route_manager (priv->netns), - nm_manager_get_devices (priv->manager), - fully_activated, - priv->default_device4); -} + state = nm_device_get_state (device); + if ( state <= NM_DEVICE_STATE_DISCONNECTED + || state >= NM_DEVICE_STATE_DEACTIVATING) + continue; -static NMDevice * -get_best_ip6_device (NMPolicy *self, gboolean fully_activated) -{ - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + if (nm_device_sys_iface_state_is_external (device)) + continue; + + r = nm_device_get_best_default_route (device, addr_family); + if (r) { + /* XXX: the best route might have rt_source NM_IP_CONFIG_SOURCE_VPN, + * which means it was injected by a VPN, not added by device. + * + * In this case, is it really the best device? Why do we even need the best + * device?? */ + metric = nm_utils_ip_route_metric_normalize (addr_family, + NMP_OBJECT_CAST_IP_ROUTE (r)->metric); + is_fully_activated = TRUE; + } else if ( !fully_activated + && (connection = nm_device_get_applied_connection (device)) + && nm_utils_connection_has_default_route (connection, addr_family, NULL)) { + metric = nm_utils_ip_route_metric_normalize (addr_family, + nm_device_get_route_metric (device, addr_family)); + is_fully_activated = FALSE; + } else + continue; + + if ( !best_device + || (!best_is_fully_activated && is_fully_activated) + || ( metric < best_metric + || (metric == best_metric && device == prev_device))) { + best_device = device; + best_metric = metric; + best_is_fully_activated = is_fully_activated; + } + } - return nm_default_route_manager_ip6_get_best_device (nm_netns_get_default_route_manager (priv->netns), - nm_manager_get_devices (priv->manager), - fully_activated, - priv->default_device6); + if ( !fully_activated + && best_device + && best_is_fully_activated) { + /* There's only a best activating device if the best device + * among all activating and already-activated devices is a + * still-activating one. */ + return NULL; + } + + return best_device; } static gboolean @@ -443,50 +506,46 @@ settings_set_hostname_cb (const char *hostname, #define HOST_NAME_BUFSIZE (HOST_NAME_MAX + 2) static char * -_get_hostname (NMPolicy *self, char **hostname) +_get_hostname (NMPolicy *self) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - char *buf; - - g_assert (hostname && *hostname == NULL); + char *hostname = NULL; /* If there is an in-progress hostname change, return * the last hostname set as would be set soon... */ if (priv->changing_hostname) { _LOGT (LOGD_DNS, "get-hostname: \"%s\" (last on set)", priv->last_hostname); - *hostname = g_strdup (priv->last_hostname); - return *hostname; + return g_strdup (priv->last_hostname); } /* try to get the hostname via dbus... */ - if (nm_settings_get_transient_hostname (priv->settings, hostname)) { - _LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", *hostname); - return *hostname; + if (nm_hostname_manager_get_transient_hostname (priv->hostname_manager, &hostname)) { + _LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", hostname); + return hostname; } /* ...or retrieve it by yourself */ - buf = g_malloc (HOST_NAME_BUFSIZE); - if (gethostname (buf, HOST_NAME_BUFSIZE -1) != 0) { + hostname = g_malloc (HOST_NAME_BUFSIZE); + if (gethostname (hostname, HOST_NAME_BUFSIZE -1) != 0) { int errsv = errno; _LOGT (LOGD_DNS, "get-hostname: couldn't get the system hostname: (%d) %s", errsv, g_strerror (errsv)); - g_free (buf); + g_free (hostname); return NULL; } /* the name may be truncated... */ - buf[HOST_NAME_BUFSIZE - 1] = '\0'; - if (strlen (buf) >= HOST_NAME_BUFSIZE -1) { - _LOGT (LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", buf); - g_free (buf); + hostname[HOST_NAME_BUFSIZE - 1] = '\0'; + if (strlen (hostname) >= HOST_NAME_BUFSIZE -1) { + _LOGT (LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", hostname); + g_free (hostname); return NULL; } - _LOGT (LOGD_DNS, "get-hostname: \"%s\"", buf); - *hostname = buf; - return *hostname; + _LOGT (LOGD_DNS, "get-hostname: \"%s\"", hostname); + return hostname; } static void @@ -508,7 +567,7 @@ _set_hostname (NMPolicy *self, * restart the reverse lookup thread later. */ if (new_hostname) - g_clear_object (&priv->lookup_addr); + g_clear_object (&priv->lookup.addr); /* Update the DNS only if the hostname is actually * going to change. @@ -534,7 +593,7 @@ _set_hostname (NMPolicy *self, name = new_hostname; /* Don't set the hostname if it isn't actually changing */ - if ( _get_hostname (self, &old_hostname) + if ( (old_hostname = _get_hostname (self)) && (nm_streq (name, old_hostname))) { _LOGT (LOGD_DNS, "set-hostname: hostname already set to '%s' (%s)", name, msg); return; @@ -549,10 +608,10 @@ _set_hostname (NMPolicy *self, /* Ask NMSettings to update the transient hostname using its * systemd-hostnamed proxy */ - nm_settings_set_transient_hostname (priv->settings, - name, - settings_set_hostname_cb, - g_object_ref (self)); + nm_hostname_manager_set_transient_hostname (priv->hostname_manager, + name, + settings_set_hostname_cb, + g_object_ref (self)); } static void @@ -572,7 +631,7 @@ lookup_callback (GObject *source, self = user_data; priv = NM_POLICY_GET_PRIVATE (self); - g_clear_object (&priv->lookup_cancellable); + g_clear_object (&priv->lookup.cancellable); if (hostname) _set_hostname (self, hostname, "from address lookup"); @@ -581,15 +640,30 @@ lookup_callback (GObject *source, } static void -update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const char *msg) +lookup_by_address (NMPolicy *self) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + nm_clear_g_cancellable (&priv->lookup.cancellable); + priv->lookup.cancellable = g_cancellable_new (); + g_resolver_lookup_by_address_async (priv->lookup.resolver, + priv->lookup.addr, + priv->lookup.cancellable, + lookup_callback, self); +} + +static void +update_system_hostname (NMPolicy *self, const char *msg) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - char *configured_hostname = NULL; + const char *configured_hostname; gs_free char *temp_hostname = NULL; const char *dhcp_hostname, *p; NMIP4Config *ip4_config; NMIP6Config *ip6_config; gboolean external_hostname = FALSE; + const NMPlatformIP4Address *addr4; + const NMPlatformIP6Address *addr6; g_return_if_fail (self != NULL); @@ -600,12 +674,12 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const _LOGT (LOGD_DNS, "set-hostname: updating hostname (%s)", msg); - nm_clear_g_cancellable (&priv->lookup_cancellable); + nm_clear_g_cancellable (&priv->lookup.cancellable); /* Check if the hostname was set externally to NM, so that in that case * we can avoid to fallback to the one we got when we started. * Consider "not specific" hostnames as equal. */ - if ( _get_hostname (self, &temp_hostname) + if ( (temp_hostname = _get_hostname (self)) && !nm_streq0 (temp_hostname, priv->last_hostname) && ( nm_utils_is_specific_hostname (temp_hostname) || nm_utils_is_specific_hostname (priv->last_hostname))) { @@ -614,14 +688,14 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const temp_hostname); priv->dhcp_hostname = FALSE; + if (!nm_utils_is_specific_hostname (temp_hostname)) + nm_clear_g_free (&temp_hostname); if (!nm_streq0 (temp_hostname, priv->orig_hostname)) { /* Update original (fallback) hostname */ g_free (priv->orig_hostname); - if (nm_utils_is_specific_hostname (temp_hostname)) { - priv->orig_hostname = temp_hostname; - temp_hostname = NULL; - } else - priv->orig_hostname = NULL; + priv->orig_hostname = g_steal_pointer (&temp_hostname); + _LOGT (LOGD_DNS, "hostname-original: update to %s%s%s", + NM_PRINT_FMT_QUOTE_STRING (priv->orig_hostname)); } } @@ -635,56 +709,46 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const */ /* Try a persistent hostname first */ - g_object_get (G_OBJECT (priv->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL); + configured_hostname = nm_hostname_manager_get_hostname (priv->hostname_manager); if (configured_hostname && nm_utils_is_specific_hostname (configured_hostname)) { _set_hostname (self, configured_hostname, "from system configuration"); priv->dhcp_hostname = FALSE; - g_free (configured_hostname); return; } - g_free (configured_hostname); - /* Try automatically determined hostname from the best device's IP config */ - if (!best4) - best4 = get_best_ip4_device (self, TRUE); - if (!best6) - best6 = get_best_ip6_device (self, TRUE); - - if (best4) { + if (priv->default_device4) { NMDhcp4Config *dhcp4_config; /* Grab a hostname out of the device's DHCP4 config */ - dhcp4_config = nm_device_get_dhcp4_config (best4); + dhcp4_config = nm_device_get_dhcp4_config (priv->default_device4); if (dhcp4_config) { - p = dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name"); - if (dhcp_hostname && strlen (dhcp_hostname)) { - /* Sanity check; strip leading spaces */ - while (*p) { - if (!g_ascii_isspace (*p++)) { - _set_hostname (self, p-1, "from DHCPv4"); - priv->dhcp_hostname = TRUE; - return; - } + dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name"); + if (dhcp_hostname && dhcp_hostname[0]) { + p = nm_str_skip_leading_spaces (dhcp_hostname); + if (p[0]) { + _set_hostname (self, p, "from DHCPv4"); + priv->dhcp_hostname = TRUE; + return; } _LOGW (LOGD_DNS, "set-hostname: DHCPv4-provided hostname '%s' looks invalid; ignoring it", dhcp_hostname); } } - } else if (best6) { + } + + if (priv->default_device6) { NMDhcp6Config *dhcp6_config; /* Grab a hostname out of the device's DHCP6 config */ - dhcp6_config = nm_device_get_dhcp6_config (best6); + dhcp6_config = nm_device_get_dhcp6_config (priv->default_device6); if (dhcp6_config) { - p = dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "host_name"); - if (dhcp_hostname && strlen (dhcp_hostname)) { - /* Sanity check; strip leading spaces */ - while (*p) { - if (!g_ascii_isspace (*p++)) { - _set_hostname (self, p-1, "from DHCPv6"); - priv->dhcp_hostname = TRUE; - return; - } + dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "host_name"); + if (dhcp_hostname && dhcp_hostname[0]) { + p = nm_str_skip_leading_spaces (dhcp_hostname); + if (p[0]) { + _set_hostname (self, p, "from DHCPv6"); + priv->dhcp_hostname = TRUE; + return; } _LOGW (LOGD_DNS, "set-hostname: DHCPv6-provided hostname '%s' looks invalid; ignoring it", dhcp_hostname); @@ -711,7 +775,7 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const priv->dhcp_hostname = FALSE; - if (!best4 && !best6) { + if (!priv->default_device4 && !priv->default_device6) { /* No best device; fall back to the last hostname set externally * to NM or if there wasn't one, 'localhost.localdomain' */ @@ -730,22 +794,18 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const /* No configured hostname, no automatically determined hostname, and no * bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address. */ - ip4_config = best4 ? nm_device_get_ip4_config (best4) : NULL; - ip6_config = best6 ? nm_device_get_ip6_config (best6) : NULL; - - if (ip4_config && nm_ip4_config_get_num_addresses (ip4_config) > 0) { - const NMPlatformIP4Address *addr4; + ip4_config = priv->default_device4 ? nm_device_get_ip4_config (priv->default_device4) : NULL; + ip6_config = priv->default_device6 ? nm_device_get_ip6_config (priv->default_device6) : NULL; - addr4 = nm_ip4_config_get_address (ip4_config, 0); - g_clear_object (&priv->lookup_addr); - priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address, + if ( ip4_config + && (addr4 = nm_ip4_config_get_first_address (ip4_config))) { + g_clear_object (&priv->lookup.addr); + priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address, G_SOCKET_FAMILY_IPV4); - } else if (ip6_config && nm_ip6_config_get_num_addresses (ip6_config) > 0) { - const NMPlatformIP6Address *addr6; - - addr6 = nm_ip6_config_get_address (ip6_config, 0); - g_clear_object (&priv->lookup_addr); - priv->lookup_addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address, + } else if ( ip6_config + && (addr6 = nm_ip6_config_get_first_address (ip6_config))) { + g_clear_object (&priv->lookup.addr); + priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address, G_SOCKET_FAMILY_IPV6); } else { /* No valid IP config; fall back to localhost.localdomain */ @@ -753,11 +813,7 @@ update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6, const return; } - priv->lookup_cancellable = g_cancellable_new (); - g_resolver_lookup_by_address_async (priv->resolver, - priv->lookup_addr, - priv->lookup_cancellable, - lookup_callback, self); + lookup_by_address (self); } static void @@ -783,20 +839,83 @@ update_default_ac (NMPolicy *self, set_active_func (best, TRUE); } -static NMIP4Config * -get_best_ip4_config (NMPolicy *self, - gboolean ignore_never_default, - const char **out_ip_iface, - NMActiveConnection **out_ac, - NMDevice **out_device, - NMVpnConnection **out_vpn) +static gpointer +get_best_ip_config (NMPolicy *self, + int addr_family, + const char **out_ip_iface, + NMActiveConnection **out_ac, + NMDevice **out_device, + NMVpnConnection **out_vpn) { - return nm_default_route_manager_ip4_get_best_config (nm_netns_get_default_route_manager (NM_POLICY_GET_PRIVATE (self)->netns), - ignore_never_default, - out_ip_iface, - out_ac, - out_device, - out_vpn); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + NMDevice *device; + gpointer conf; + const GSList *iter; + + nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); + + for (iter = nm_manager_get_active_connections (priv->manager); iter; iter = iter->next) { + NMActiveConnection *active = NM_ACTIVE_CONNECTION (iter->data); + NMVpnConnection *candidate; + NMVpnConnectionState vpn_state; + + if (!NM_IS_VPN_CONNECTION (active)) + continue; + + candidate = NM_VPN_CONNECTION (active); + + vpn_state = nm_vpn_connection_get_vpn_state (candidate); + if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) + continue; + + if (addr_family == AF_INET) + conf = nm_vpn_connection_get_ip4_config (candidate); + else + conf = nm_vpn_connection_get_ip6_config (candidate); + if (!conf) + continue; + + if (addr_family == AF_INET) { + if (!nm_ip4_config_best_default_route_get (conf)) + continue; + } else { + if (!nm_ip6_config_best_default_route_get (conf)) + continue; + } + + /* FIXME: in case of multiple VPN candidates, choose the one with the + * best metric. */ + NM_SET_OUT (out_device, NULL); + NM_SET_OUT (out_vpn, candidate); + NM_SET_OUT (out_ac, active); + NM_SET_OUT (out_ip_iface, nm_vpn_connection_get_ip_iface (candidate, TRUE)); + return conf; + } + + device = get_best_ip_device (self, addr_family, TRUE); + if (device) { + NMActRequest *req; + + if (addr_family == AF_INET) + conf = nm_device_get_ip4_config (device); + else + conf = nm_device_get_ip6_config (device); + req = nm_device_get_act_request (device); + + if (conf && req) { + NM_SET_OUT (out_device, device); + NM_SET_OUT (out_vpn, NULL); + NM_SET_OUT (out_ac, NM_ACTIVE_CONNECTION (req)); + NM_SET_OUT (out_ip_iface, nm_device_get_ip_iface (device)); + return conf; + } + } + + NM_SET_OUT (out_device, NULL); + NM_SET_OUT (out_vpn, NULL); + NM_SET_OUT (out_ac, NULL); + NM_SET_OUT (out_ip_iface, NULL); + return NULL; } static void @@ -807,7 +926,7 @@ update_ip4_dns (NMPolicy *self, NMDnsManager *dns_mgr) NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip4_config = get_best_ip4_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); + ip4_config = get_best_ip_config (self, AF_INET, &ip_iface, NULL, NULL, &vpn); if (ip4_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -823,8 +942,7 @@ static void update_ip4_routing (NMPolicy *self, gboolean force_update) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - NMDevice *best = NULL, *default_device; - NMConnection *connection = NULL; + NMDevice *best = NULL; NMVpnConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; const char *ip_iface = NULL; @@ -832,19 +950,18 @@ update_ip4_routing (NMPolicy *self, gboolean force_update) /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip4_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { - gboolean changed; - - changed = (priv->default_device4 != NULL); - priv->default_device4 = NULL; - if (changed) + if (!get_best_ip_config (self, AF_INET, &ip_iface, &best_ac, &best, &vpn)) { + if (nm_clear_g_object (&priv->default_device4)) { + _LOGt (LOGD_DNS, "set-default-device-4: %p", NULL); _notify (self, PROP_DEFAULT_IP4_DEVICE); - + } return; } g_assert ((best || vpn) && best_ac); - if (!force_update && best && (best == priv->default_device4)) + if ( !force_update + && best + && best == priv->default_device4) return; if (best) { @@ -862,38 +979,20 @@ update_ip4_routing (NMPolicy *self, gboolean force_update) } if (vpn) - default_device = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - else - default_device = best; + best = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); update_default_ac (self, best_ac, nm_active_connection_set_default); - if (default_device == priv->default_device4) + if (!nm_g_object_ref_set (&priv->default_device4, best)) return; + _LOGt (LOGD_DNS, "set-default-device-4: %p", priv->default_device4); - priv->default_device4 = default_device; - connection = nm_active_connection_get_applied_connection (best_ac); _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv4 routing and DNS", - nm_connection_get_id (connection), ip_iface); + nm_connection_get_id (nm_active_connection_get_applied_connection (best_ac)), + ip_iface); _notify (self, PROP_DEFAULT_IP4_DEVICE); } -static NMIP6Config * -get_best_ip6_config (NMPolicy *self, - gboolean ignore_never_default, - const char **out_ip_iface, - NMActiveConnection **out_ac, - NMDevice **out_device, - NMVpnConnection **out_vpn) -{ - return nm_default_route_manager_ip6_get_best_config (nm_netns_get_default_route_manager (NM_POLICY_GET_PRIVATE (self)->netns), - ignore_never_default, - out_ip_iface, - out_ac, - out_device, - out_vpn); -} - static void update_ip6_dns_delegation (NMPolicy *self) { @@ -917,7 +1016,7 @@ update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr) NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip6_config = get_best_ip6_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); + ip6_config = get_best_ip_config (self, AF_INET6, &ip_iface, NULL, NULL, &vpn); if (ip6_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -951,8 +1050,7 @@ static void update_ip6_routing (NMPolicy *self, gboolean force_update) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - NMDevice *best = NULL, *default_device6; - NMConnection *connection = NULL; + NMDevice *best = NULL; NMVpnConnection *vpn = NULL; NMActiveConnection *best_ac = NULL; const char *ip_iface = NULL; @@ -960,19 +1058,18 @@ update_ip6_routing (NMPolicy *self, gboolean force_update) /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip6_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { - gboolean changed; - - changed = (priv->default_device6 != NULL); - priv->default_device6 = NULL; - if (changed) + if (!get_best_ip_config (self, AF_INET6, &ip_iface, &best_ac, &best, &vpn)) { + if (nm_clear_g_object (&priv->default_device6)) { + _LOGt (LOGD_DNS, "set-default-device-6: %p", NULL); _notify (self, PROP_DEFAULT_IP6_DEVICE); - + } return; } g_assert ((best || vpn) && best_ac); - if (!force_update && best && (best == priv->default_device6)) + if ( !force_update + && best + && best == priv->default_device6) return; if (best) { @@ -990,21 +1087,19 @@ update_ip6_routing (NMPolicy *self, gboolean force_update) } if (vpn) - default_device6 = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); - else - default_device6 = best; + best = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn)); update_default_ac (self, best_ac, nm_active_connection_set_default6); - if (default_device6 == priv->default_device6) + if (!nm_g_object_ref_set (&priv->default_device6, best)) return; - priv->default_device6 = default_device6; + _LOGt (LOGD_DNS, "set-default-device-6: %p", priv->default_device6); update_ip6_prefix_delegation (self); - connection = nm_active_connection_get_applied_connection (best_ac); _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv6 routing and DNS", - nm_connection_get_id (connection), ip_iface); + nm_connection_get_id (nm_active_connection_get_applied_connection (best_ac)), + ip_iface); _notify (self, PROP_DEFAULT_IP6_DEVICE); } @@ -1022,7 +1117,7 @@ update_routing_and_dns (NMPolicy *self, gboolean force_update) update_ip6_routing (self, force_update); /* Update the system hostname */ - update_system_hostname (self, priv->default_device4, priv->default_device6, "routing and dns"); + update_system_hostname (self, "routing and dns"); nm_dns_manager_end_updates (priv->dns_manager, __func__); } @@ -1031,24 +1126,23 @@ static void check_activating_devices (NMPolicy *self) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); - GObject *object = G_OBJECT (self); NMDevice *best4, *best6 = NULL; - best4 = get_best_ip4_device (self, FALSE); - best6 = get_best_ip6_device (self, FALSE); + best4 = get_best_ip_device (self, AF_INET, FALSE); + best6 = get_best_ip_device (self, AF_INET6, FALSE); - g_object_freeze_notify (object); + g_object_freeze_notify (G_OBJECT (self)); - if (best4 != priv->activating_device4) { - priv->activating_device4 = best4; + if (nm_g_object_ref_set (&priv->activating_device4, best4)) { + _LOGt (LOGD_DNS, "set-activating-device-4: %p", priv->activating_device4); _notify (self, PROP_ACTIVATING_IP4_DEVICE); } - if (best6 != priv->activating_device6) { - priv->activating_device6 = best6; + if (nm_g_object_ref_set (&priv->activating_device6, best6)) { + _LOGt (LOGD_DNS, "set-activating-device-6: %p", priv->activating_device6); _notify (self, PROP_ACTIVATING_IP6_DEVICE); } - g_object_thaw_notify (object); + g_object_thaw_notify (G_OBJECT (self)); } typedef struct { @@ -1073,6 +1167,45 @@ activate_data_free (ActivateData *data) } static void +pending_ac_gone (gpointer data, GObject *where_the_object_was) +{ + NMPolicy *self = NM_POLICY (data); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + /* Active connections should reach the DEACTIVATED state + * before disappearing. */ + nm_assert_not_reached(); + + if (g_hash_table_remove (priv->pending_active_connections, where_the_object_was)) + g_object_unref (self); +} + +static void +pending_ac_state_changed (NMActiveConnection *ac, guint state, guint reason, NMPolicy *self) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + NMSettingsConnection *con; + + if (state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + /* The AC is being deactivated before the device had a chance + * to move to PREPARE. Schedule a new auto-activation on the + * device, but block the current connection to avoid an activation + * loop. + */ + con = nm_active_connection_get_settings_connection (ac); + nm_settings_connection_autoconnect_blocked_reason_set (con, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED); + schedule_activate_check (self, nm_active_connection_get_device (ac)); + + /* Cleanup */ + g_signal_handlers_disconnect_by_func (ac, pending_ac_state_changed, self); + if (!g_hash_table_remove (priv->pending_active_connections, ac)) + nm_assert_not_reached (); + g_object_weak_unref (G_OBJECT (ac), pending_ac_gone, self); + g_object_unref (self); + } +} + +static void auto_activate_device (NMPolicy *self, NMDevice *device) { @@ -1102,9 +1235,23 @@ auto_activate_device (NMPolicy *self, best_connection = NULL; for (i = 0; i < len; i++) { NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (connections[i]); + NMSettingConnection *s_con; + const char *permission; - if (!nm_settings_connection_can_autoconnect (candidate)) + if ( !nm_settings_connection_is_visible (candidate) + || nm_settings_connection_autoconnect_retries_get (candidate) == 0 + || nm_settings_connection_autoconnect_blocked_reason_get (candidate) != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE) continue; + + s_con = nm_connection_get_setting_connection (NM_CONNECTION (candidate)); + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + permission = nm_utils_get_shared_wifi_permission (NM_CONNECTION (candidate)); + if ( permission + && !nm_settings_connection_check_permission (candidate, permission)) + continue; + if (nm_device_can_auto_connect (device, (NMConnection *) candidate, &specific_object)) { best_connection = candidate; break; @@ -1114,24 +1261,41 @@ auto_activate_device (NMPolicy *self, if (best_connection) { GError *error = NULL; NMAuthSubject *subject; + NMActiveConnection *ac; _LOGI (LOGD_DEVICE, "auto-activating connection '%s'", nm_settings_connection_get_id (best_connection)); subject = nm_auth_subject_new_internal (); - if (!nm_manager_activate_connection (priv->manager, + ac = nm_manager_activate_connection (priv->manager, best_connection, NULL, specific_object, device, subject, NM_ACTIVATION_TYPE_MANAGED, - &error)) { + &error); + if (!ac) { _LOGI (LOGD_DEVICE, "connection '%s' auto-activation failed: (%d) %s", nm_settings_connection_get_id (best_connection), error->code, error->message); g_error_free (error); + nm_settings_connection_autoconnect_blocked_reason_set (best_connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED); + schedule_activate_check (self, device); + return; } + + /* Subscribe to AC state-changed signal to detect when the + * activation fails in early stages without changing device + * state. + */ + if (nm_g_hash_table_add (priv->pending_active_connections, ac)) { + g_signal_connect (ac, NM_ACTIVE_CONNECTION_STATE_CHANGED, + G_CALLBACK (pending_ac_state_changed), g_object_ref (self)); + g_object_weak_ref (G_OBJECT (ac), (GWeakNotify) pending_ac_gone, self); + } + g_object_unref (subject); } } @@ -1248,12 +1412,12 @@ process_secondaries (NMPolicy *self, } static void -hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) +hostname_changed (NMHostnameManager *hostname_manager, GParamSpec *pspec, gpointer user_data) { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF (priv); - update_system_hostname (self, NULL, NULL, "hostname changed"); + update_system_hostname (self, "hostname changed"); } static void @@ -1274,8 +1438,8 @@ reset_autoconnect_all (NMPolicy *self, NMDevice *device) NMSettingsConnection *connection = connections[i]; if (!device || nm_device_check_connection_compatible (device, NM_CONNECTION (connection))) { - nm_settings_connection_reset_autoconnect_retries (connection); - nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_UNBLOCKED); + nm_settings_connection_autoconnect_retries_reset (connection); + nm_settings_connection_autoconnect_blocked_reason_set (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE); } } } @@ -1293,9 +1457,9 @@ reset_autoconnect_for_failed_secrets (NMPolicy *self) for (i = 0; connections[i]; i++) { NMSettingsConnection *connection = connections[i]; - if (nm_settings_connection_get_autoconnect_blocked_reason (connection) == NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS) { - nm_settings_connection_reset_autoconnect_retries (connection); - nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_UNBLOCKED); + if (nm_settings_connection_autoconnect_blocked_reason_get (connection) == NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS) { + nm_settings_connection_autoconnect_retries_reset (connection); + nm_settings_connection_autoconnect_blocked_reason_set (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE); } } } @@ -1322,8 +1486,8 @@ block_autoconnect_for_device (NMPolicy *self, NMDevice *device) NMSettingsConnection *connection = connections[i]; if (nm_device_check_connection_compatible (device, NM_CONNECTION (connection))) { - nm_settings_connection_set_autoconnect_blocked_reason (connection, - NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_BLOCKED); + nm_settings_connection_autoconnect_blocked_reason_set (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST); } } } @@ -1406,12 +1570,12 @@ reset_connections_retries (gpointer user_data) for (i = 0; connections[i]; i++) { NMSettingsConnection *connection = connections[i]; - con_stamp = nm_settings_connection_get_autoconnect_retry_time (connection); + con_stamp = nm_settings_connection_autoconnect_blocked_until_get (connection); if (con_stamp == 0) continue; if (con_stamp <= now) { - nm_settings_connection_reset_autoconnect_retries (connection); + nm_settings_connection_autoconnect_retries_reset (connection); changed = TRUE; } else if (min_stamp == 0 || min_stamp > con_stamp) min_stamp = con_stamp; @@ -1436,6 +1600,7 @@ activate_slave_connections (NMPolicy *self, NMDevice *device) guint i; NMActRequest *req; gboolean internal_activation = FALSE; + gs_free NMSettingsConnection **connections = NULL; master_device = nm_device_get_iface (device); g_assert (master_device); @@ -1459,28 +1624,34 @@ activate_slave_connections (NMPolicy *self, NMDevice *device) internal_activation = subject && nm_auth_subject_is_internal (subject); } - if (!internal_activation) { - gs_free NMSettingsConnection **connections = NULL; + connections = nm_settings_get_connections_sorted (priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMConnection *slave; + NMSettingConnection *s_slave_con; + const char *slave_master; - connections = nm_settings_get_connections_sorted (priv->settings, NULL); + slave = NM_CONNECTION (connections[i]); - for (i = 0; connections[i]; i++) { - NMConnection *slave; - NMSettingConnection *s_slave_con; - const char *slave_master; + s_slave_con = nm_connection_get_setting_connection (slave); + g_assert (s_slave_con); + slave_master = nm_setting_connection_get_master (s_slave_con); + if (!slave_master) + continue; - slave = NM_CONNECTION (connections[i]); + if ( nm_streq0 (slave_master, master_device) + || nm_streq0 (slave_master, master_uuid_applied) + || nm_streq0 (slave_master, master_uuid_settings)) { + NMSettingsConnection *settings = NM_SETTINGS_CONNECTION (slave); + NMSettingsAutoconnectBlockedReason reason; - s_slave_con = nm_connection_get_setting_connection (slave); - g_assert (s_slave_con); - slave_master = nm_setting_connection_get_master (s_slave_con); - if (!slave_master) - continue; + if (!internal_activation) + nm_settings_connection_autoconnect_retries_reset (settings); - if ( !g_strcmp0 (slave_master, master_device) - || !g_strcmp0 (slave_master, master_uuid_applied) - || !g_strcmp0 (slave_master, master_uuid_settings)) - nm_settings_connection_reset_autoconnect_retries (NM_SETTINGS_CONNECTION (slave)); + reason = nm_settings_connection_autoconnect_blocked_reason_get (settings); + if (reason == NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED) { + reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE; + nm_settings_connection_autoconnect_blocked_reason_set (settings, reason); + } } } @@ -1568,6 +1739,7 @@ device_state_changed (NMDevice *device, { NMPolicyPrivate *priv = user_data; NMPolicy *self = _PRIV_TO_SELF (priv); + NMActiveConnection *ac; NMSettingsConnection *connection = nm_device_get_settings_connection (device); @@ -1576,6 +1748,28 @@ device_state_changed (NMDevice *device, NMIP6Config *ip6_config; NMSettingConnection *s_con = NULL; + switch (nm_device_state_reason_check (reason)) { + case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: + case NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: + case NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: + case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: + case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: + case NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: + case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: + case NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: + case NM_DEVICE_STATE_REASON_GSM_APN_FAILED: + /* Block autoconnect of the just-failed connection for situations + * where a retry attempt would just fail again. + */ + if (connection) { + nm_settings_connection_autoconnect_blocked_reason_set (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED); + } + break; + default: + break; + } + switch (new_state) { case NM_DEVICE_STATE_FAILED: /* Mark the connection invalid if it failed during activation so that @@ -1584,26 +1778,31 @@ device_state_changed (NMDevice *device, if ( connection && old_state >= NM_DEVICE_STATE_PREPARE && old_state <= NM_DEVICE_STATE_ACTIVATED) { - int tries = nm_settings_connection_get_autoconnect_retries (connection); + int tries; + tries = nm_settings_connection_autoconnect_retries_get (connection); if (nm_device_state_reason_check (reason) == NM_DEVICE_STATE_REASON_NO_SECRETS) { _LOGD (LOGD_DEVICE, "connection '%s' now blocked from autoconnect due to no secrets", nm_settings_connection_get_id (connection)); - nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS); + nm_settings_connection_autoconnect_blocked_reason_set (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS); } else if (tries != 0) { - _LOGD (LOGD_DEVICE, "connection '%s' failed to autoconnect; %d tries left", - nm_settings_connection_get_id (connection), tries); - if (tries > 0) - nm_settings_connection_set_autoconnect_retries (connection, tries - 1); + if (tries > 0) { + _LOGD (LOGD_DEVICE, "connection '%s' failed to autoconnect; %d tries left", + nm_settings_connection_get_id (connection), tries); + nm_settings_connection_autoconnect_retries_set (connection, --tries); + } else { + _LOGD (LOGD_DEVICE, "connection '%s' failed to autoconnect; infinite tries left", + nm_settings_connection_get_id (connection)); + } } - if (nm_settings_connection_get_autoconnect_retries (connection) == 0) { + if (nm_settings_connection_autoconnect_retries_get (connection) == 0) { _LOGI (LOGD_DEVICE, "disabling autoconnect for connection '%s'.", nm_settings_connection_get_id (connection)); /* Schedule a handler to reset retries count */ if (!priv->reset_retries_id) { - gint32 retry_time = nm_settings_connection_get_autoconnect_retry_time (connection); + gint32 retry_time = nm_settings_connection_autoconnect_blocked_until_get (connection); g_warn_if_fail (retry_time != 0); priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, self); @@ -1615,7 +1814,7 @@ device_state_changed (NMDevice *device, case NM_DEVICE_STATE_ACTIVATED: if (connection) { /* Reset auto retries back to default since connection was successful */ - nm_settings_connection_reset_autoconnect_retries (connection); + nm_settings_connection_autoconnect_retries_reset (connection); /* And clear secrets so they will always be requested from the * settings service when the next connection is made. @@ -1654,8 +1853,8 @@ device_state_changed (NMDevice *device, /* The connection was deactivated, so block just this connection */ _LOGD (LOGD_DEVICE, "blocking autoconnect of connection '%s' by user request", nm_settings_connection_get_id (connection)); - nm_settings_connection_set_autoconnect_blocked_reason (connection, - NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_BLOCKED); + nm_settings_connection_autoconnect_blocked_reason_set (connection, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST); } } } @@ -1680,11 +1879,20 @@ device_state_changed (NMDevice *device, /* Reset auto-connect retries of all slaves and schedule them for * activation. */ activate_slave_connections (self, device); + + /* Now that the device state is progressing, we don't care + * anymore for the AC state. */ + ac = (NMActiveConnection *) nm_device_get_act_request (device); + if (ac && g_hash_table_remove (priv->pending_active_connections, ac)) { + g_signal_handlers_disconnect_by_func (ac, pending_ac_state_changed, self); + g_object_weak_unref (G_OBJECT (ac), pending_ac_gone, self); + g_object_unref (self); + } break; case NM_DEVICE_STATE_IP_CONFIG: /* We must have secrets if we got here. */ if (connection) - nm_settings_connection_set_autoconnect_blocked_reason (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_UNBLOCKED); + nm_settings_connection_autoconnect_blocked_reason_set (connection, NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE); break; case NM_DEVICE_STATE_SECONDARIES: if (connection) @@ -1735,7 +1943,7 @@ device_ip4_config_changed (NMDevice *device, } update_ip4_dns (self, priv->dns_manager); update_ip4_routing (self, TRUE); - update_system_hostname (self, priv->default_device4, priv->default_device6, "ip4 conf"); + update_system_hostname (self, "ip4 conf"); } else { /* Old configs get removed immediately */ if (old_config) @@ -1771,7 +1979,7 @@ device_ip6_config_changed (NMDevice *device, } update_ip6_dns (self, priv->dns_manager); update_ip6_routing (self, TRUE); - update_system_hostname (self, priv->default_device4, priv->default_device6, "ip6 conf"); + update_system_hostname (self, "ip6 conf"); } else { /* Old configs get removed immediately */ if (old_config) @@ -2088,30 +2296,26 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) * (race in updating DNS and doing the reverse lookup). */ - nm_clear_g_cancellable (&priv->lookup_cancellable); + nm_clear_g_cancellable (&priv->lookup.cancellable); /* Re-start the hostname lookup thread if we don't have hostname yet. */ - if (priv->lookup_addr) { + if (priv->lookup.addr) { char *str = NULL; gs_free char *hostname = NULL; /* Check if the hostname was externally set */ - if ( _get_hostname (self, &hostname) + if ( (hostname = _get_hostname (self)) && nm_utils_is_specific_hostname (hostname) && !nm_streq0 (hostname, priv->last_hostname)) { - g_clear_object (&priv->lookup_addr); + g_clear_object (&priv->lookup.addr); return; } _LOGD (LOGD_DNS, "restarting reverse-lookup thread for address %s", - (str = g_inet_address_to_string (priv->lookup_addr))); + (str = g_inet_address_to_string (priv->lookup.addr))); g_free (str); - priv->lookup_cancellable = g_cancellable_new (); - g_resolver_lookup_by_address_async (priv->resolver, - priv->lookup_addr, - priv->lookup_cancellable, - lookup_callback, self); + lookup_by_address (self); } } @@ -2141,7 +2345,7 @@ connection_updated (NMSettings *settings, nm_device_reapply_settings_immediately (device); /* Reset auto retries back to default since connection was updated */ - nm_settings_connection_reset_autoconnect_retries (connection); + nm_settings_connection_autoconnect_retries_reset (connection); } schedule_activate_all (self); @@ -2240,6 +2444,15 @@ nm_policy_get_activating_ip6_device (NMPolicy *self) /*****************************************************************************/ +NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_hostname_mode_to_string, NMPolicyHostnameMode, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_NONE, "none"), + NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_DHCP, "dhcp"), + NM_UTILS_LOOKUP_STR_ITEM (NM_POLICY_HOSTNAME_MODE_FULL, "full"), +); + +/*****************************************************************************/ + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -2300,6 +2513,8 @@ nm_policy_init (NMPolicy *self) priv->netns = g_object_ref (nm_netns_get ()); + priv->hostname_manager = g_object_ref (nm_hostname_manager_get ()); + hostname_mode = nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG, NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE, @@ -2311,8 +2526,8 @@ nm_policy_init (NMPolicy *self) else /* default - full mode */ priv->hostname_mode = NM_POLICY_HOSTNAME_MODE_FULL; - _LOGI (LOGD_DNS, "hostname management mode: %s", hostname_mode ? hostname_mode : "default"); priv->devices = g_hash_table_new (NULL, NULL); + priv->pending_active_connections = g_hash_table_new (NULL, NULL); priv->ip6_prefix_delegations = g_array_new (FALSE, FALSE, sizeof (IP6PrefixDelegation)); g_array_set_clear_func (priv->ip6_prefix_delegations, clear_ip6_prefix_delegation); } @@ -2325,7 +2540,7 @@ constructed (GObject *object) char *hostname = NULL; /* Grab hostname on startup and use that if nothing provides one */ - if (_get_hostname (self, &hostname)) { + if ((hostname = _get_hostname (self))) { /* init last_hostname */ priv->last_hostname = hostname; @@ -2333,6 +2548,8 @@ constructed (GObject *object) if (nm_utils_is_specific_hostname (hostname)) priv->orig_hostname = g_strdup (hostname); } + _LOGT (LOGD_DNS, "hostname-original: set to %s%s%s", + NM_PRINT_FMT_QUOTE_STRING (priv->orig_hostname)); priv->firewall_manager = g_object_ref (nm_firewall_manager_get ()); g_signal_connect (priv->firewall_manager, NM_FIREWALL_MANAGER_STATE_CHANGED, @@ -2343,9 +2560,10 @@ constructed (GObject *object) priv->config_changed_id = g_signal_connect (priv->dns_manager, NM_DNS_MANAGER_CONFIG_CHANGED, G_CALLBACK (dns_config_changed), self); - priv->resolver = g_resolver_get_default (); + priv->lookup.resolver = g_resolver_get_default (); + + g_signal_connect (priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, (GCallback) hostname_changed, priv); - g_signal_connect (priv->manager, "notify::" NM_MANAGER_HOSTNAME, (GCallback) hostname_changed, priv); g_signal_connect (priv->manager, "notify::" NM_MANAGER_SLEEPING, (GCallback) sleeping_changed, priv); g_signal_connect (priv->manager, "notify::" NM_MANAGER_NETWORKING_ENABLED, (GCallback) sleeping_changed, priv); g_signal_connect (priv->manager, NM_MANAGER_INTERNAL_DEVICE_ADDED, (GCallback) device_added, priv); @@ -2360,6 +2578,8 @@ constructed (GObject *object) g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, (GCallback) secret_agent_registered, priv); G_OBJECT_CLASS (nm_policy_parent_class)->constructed (object); + + _LOGD (LOGD_DNS, "hostname-mode: %s", _hostname_mode_to_string (priv->hostname_mode)); } NMPolicy * @@ -2383,10 +2603,15 @@ dispose (GObject *object) GHashTableIter h_iter; NMDevice *device; - nm_clear_g_cancellable (&priv->lookup_cancellable); + nm_clear_g_cancellable (&priv->lookup.cancellable); + g_clear_object (&priv->lookup.addr); + g_clear_object (&priv->lookup.resolver); - g_clear_object (&priv->lookup_addr); - g_clear_object (&priv->resolver); + nm_clear_g_object (&priv->default_device4); + nm_clear_g_object (&priv->default_device6); + nm_clear_g_object (&priv->activating_device4); + nm_clear_g_object (&priv->activating_device6); + g_clear_pointer (&priv->pending_active_connections, g_hash_table_unref); while (priv->pending_activation_checks) activate_data_free (priv->pending_activation_checks->data); @@ -2424,6 +2649,11 @@ dispose (GObject *object) g_clear_pointer (&priv->cur_hostname, g_free); g_clear_pointer (&priv->last_hostname, g_free); + if (priv->hostname_manager) { + g_signal_handlers_disconnect_by_data (priv->hostname_manager, priv); + g_clear_object (&priv->hostname_manager); + } + if (priv->settings) { g_signal_handlers_disconnect_by_data (priv->settings, priv); g_clear_object (&priv->settings); |