From 12df3efccdff81a26fec8cb1893964564f476a7d Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Thu, 17 Dec 2020 14:13:45 +0100 Subject: hostname: start a new lookup every time the DNS configuration changes If the DNS configuration changes, the hostname previously determined via reverse DNS lookup could be stale. Clear the resolver data of every interface and try again. Fixes: 09c83871144a ('policy: use the hostname setting') --- src/devices/nm-device.c | 10 ++++++++++ src/devices/nm-device.h | 2 ++ src/nm-policy.c | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 84d43e245e..21662aaa61 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -17580,6 +17580,16 @@ _resolver_state_to_string(ResolverState state) } } +void +nm_device_clear_dns_lookup_data(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + guint i; + + for (i = 0; i < 2; i++) + nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free); +} + /* return value is valid only immediately */ const char * nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_wait) diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 2885bcbb80..2d53e7b566 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -869,4 +869,6 @@ gboolean nm_device_is_vpn(NMDevice *self); const char * nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_pending); +void nm_device_clear_dns_lookup_data(NMDevice *self); + #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/nm-policy.c b/src/nm-policy.c index 568c55eefb..114cd7790a 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -65,6 +65,7 @@ typedef struct { NMActiveConnection *default_ac6, *activating_ac6; NMDnsManager *dns_manager; + gulong config_changed_id; guint reset_retries_id; /* idle handler for resetting the retries count */ @@ -75,8 +76,10 @@ typedef struct { char * cur_hostname; /* hostname we want to assign */ char * last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */ - gboolean changing_hostname; /* hostname set operation still in progress */ - gboolean dhcp_hostname; /* current hostname was set from dhcp */ + + bool changing_hostname : 1; /* hostname set operation in progress */ + bool dhcp_hostname : 1; /* current hostname was set from dhcp */ + bool updating_dns : 1; GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */ } NMPolicyPrivate; @@ -592,11 +595,14 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) priv->cur_hostname = g_strdup(new_hostname); /* Notify the DNS manager of the hostname change so that the domain part, if - * present, can be added to the search list. + * present, can be added to the search list. Set the @updating_dns flag + * so that dns_config_changed() doesn't try again to restart DNS lookup. */ + priv->updating_dns = TRUE; nm_dns_manager_set_hostname(priv->dns_manager, priv->cur_hostname, all_devices_not_active(self)); + priv->updating_dns = FALSE; } /* Finally, set kernel hostname */ @@ -2515,6 +2521,26 @@ firewall_state_changed(NMFirewallManager *manager, gboolean initialized_now, gpo nm_device_update_firewall_zone(device); } +static void +dns_config_changed(NMDnsManager *dns_manager, gpointer user_data) +{ + NMPolicy * self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMDevice * device; + const CList * tmp_lst; + + /* We are currently updating the hostname in the DNS manager. + * This doesn't warrant a new DNS lookup.*/ + if (priv->updating_dns) + return; + + nm_manager_for_each_device (priv->manager, device, tmp_lst) { + nm_device_clear_dns_lookup_data(device); + } + + update_system_hostname(self, "DNS configuration changed"); +} + static void connection_updated(NMSettings * settings, NMSettingsConnection *connection, @@ -2747,6 +2773,10 @@ constructed(GObject *object) priv->dns_manager = g_object_ref(nm_dns_manager_get()); nm_dns_manager_set_initial_hostname(priv->dns_manager, priv->orig_hostname); + priv->config_changed_id = g_signal_connect(priv->dns_manager, + NM_DNS_MANAGER_CONFIG_CHANGED, + G_CALLBACK(dns_config_changed), + self); g_signal_connect(priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, @@ -2850,7 +2880,10 @@ dispose(GObject *object) g_clear_object(&priv->agent_mgr); } - g_clear_object(&priv->dns_manager); + if (priv->dns_manager) { + nm_clear_g_signal_handler(priv->dns_manager, &priv->config_changed_id); + g_clear_object(&priv->dns_manager); + } g_hash_table_iter_init(&h_iter, priv->devices); if (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) { -- cgit v1.2.1