mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-03-07 04:00:30 +01:00
policy,dns: fix a race in looking up hostname and updating DNS (rh #877084)
"config-changed" signal is added to dns-manager and emited when resolv.conf is changed. Policy listens for the signal and restarts reverse-lookup in order to get correct results.
This commit is contained in:
parent
32b38693f1
commit
07c5651a36
3 changed files with 93 additions and 6 deletions
|
|
@ -16,7 +16,7 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com>
|
||||
* Copyright (C) 2004 - 2012 Red Hat, Inc.
|
||||
* Copyright (C) 2004 - 2013 Red Hat, Inc.
|
||||
* Copyright (C) 2005 - 2008 Novell, Inc.
|
||||
* and others
|
||||
*/
|
||||
|
|
@ -77,6 +77,14 @@ typedef struct {
|
|||
gboolean dns_touched;
|
||||
} NMDnsManagerPrivate;
|
||||
|
||||
enum {
|
||||
CONFIG_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
||||
typedef struct {
|
||||
GPtrArray *nameservers;
|
||||
|
|
@ -746,6 +754,10 @@ update_dns (NMDnsManager *self,
|
|||
if (success == FALSE)
|
||||
success = update_resolv_conf (domain, searches, nameservers, error);
|
||||
|
||||
/* signal that resolv.conf was changed */
|
||||
if (success)
|
||||
g_signal_emit (self, signals[CONFIG_CHANGED], 0);
|
||||
|
||||
if (searches)
|
||||
g_strfreev (searches);
|
||||
if (nameservers)
|
||||
|
|
@ -1145,9 +1157,20 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDnsManagerPrivate));
|
||||
|
||||
/* virtual methods */
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDnsManagerPrivate));
|
||||
/* signals */
|
||||
signals[CONFIG_CHANGED] =
|
||||
g_signal_new ("config-changed",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMDnsManagerClass, config_changed),
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com>
|
||||
* Copyright (C) 2004 - 2010 Red Hat, Inc.
|
||||
* Copyright (C) 2004 - 2013 Red Hat, Inc.
|
||||
* Copyright (C) 2005 - 2008 Novell, Inc.
|
||||
* and others
|
||||
*/
|
||||
|
|
@ -60,6 +60,9 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
/* Signals */
|
||||
void (*config_changed) (NMDnsManager *mgr);
|
||||
} NMDnsManagerClass;
|
||||
|
||||
GType nm_dns_manager_get_type (void);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2004 - 2012 Red Hat, Inc.
|
||||
* Copyright (C) 2004 - 2013 Red Hat, Inc.
|
||||
* Copyright (C) 2007 - 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
|
|
@ -62,6 +62,10 @@ struct NMPolicy {
|
|||
NMDevice *default_device6;
|
||||
|
||||
HostnameThread *lookup;
|
||||
guint32 lookup_ipv4_addr; /* IPv4 for reverse lookup */
|
||||
struct in6_addr *lookup_ipv6_addr; /* IPv6 for reverse lookup */
|
||||
NMDnsManager *dns_manager;
|
||||
gulong config_changed_id;
|
||||
|
||||
gint reset_retries_id; /* idle handler for resetting the retries count */
|
||||
|
||||
|
|
@ -237,6 +241,15 @@ _set_hostname (NMPolicy *policy,
|
|||
* there was no valid hostname to start with.
|
||||
*/
|
||||
|
||||
/* Clear lookup adresses if we have a hostname, so that we didn't
|
||||
* restart reverse lookup thread later.
|
||||
*/
|
||||
if (new_hostname) {
|
||||
policy->lookup_ipv4_addr = 0;
|
||||
g_free (policy->lookup_ipv6_addr);
|
||||
policy->lookup_ipv6_addr = NULL;
|
||||
}
|
||||
|
||||
/* Don't change the hostname or update DNS this is the first time we're
|
||||
* trying to change the hostname, and it's not actually changing.
|
||||
*/
|
||||
|
|
@ -398,7 +411,8 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6)
|
|||
g_assert (addr4); /* checked for > 1 address above */
|
||||
|
||||
/* Start the hostname lookup thread */
|
||||
policy->lookup = hostname4_thread_new (nm_ip4_address_get_address (addr4), lookup_callback, policy);
|
||||
policy->lookup_ipv4_addr = nm_ip4_address_get_address (addr4);
|
||||
policy->lookup = hostname4_thread_new (policy->lookup_ipv4_addr, lookup_callback, policy);
|
||||
} else if (best6) {
|
||||
NMIP6Config *ip6_config;
|
||||
NMIP6Address *addr6;
|
||||
|
|
@ -416,7 +430,9 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6)
|
|||
g_assert (addr6); /* checked for > 1 address above */
|
||||
|
||||
/* Start the hostname lookup thread */
|
||||
policy->lookup = hostname6_thread_new (nm_ip6_address_get_address (addr6), lookup_callback, policy);
|
||||
policy->lookup_ipv6_addr = g_malloc0 (sizeof (struct in6_addr));
|
||||
memcpy (policy->lookup_ipv6_addr, nm_ip6_address_get_address (addr6), sizeof (struct in6_addr));
|
||||
policy->lookup = hostname6_thread_new (policy->lookup_ipv6_addr, lookup_callback, policy);
|
||||
}
|
||||
|
||||
if (!policy->lookup) {
|
||||
|
|
@ -1791,6 +1807,43 @@ firewall_started (NMFirewallManager *manager,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dns_config_changed (NMDnsManager *dns_manager, gpointer user_data)
|
||||
{
|
||||
NMPolicy *policy = (NMPolicy *) user_data;
|
||||
|
||||
/* Restart a thread for reverse-DNS lookup after we are signalled that
|
||||
* DNS changed. Because the result from a previous run may not be right
|
||||
* (race in updating DNS and doing the reverse lookup).
|
||||
*/
|
||||
|
||||
/* Stop a lookup thread if any. */
|
||||
if (policy->lookup) {
|
||||
hostname_thread_kill (policy->lookup);
|
||||
policy->lookup = NULL;
|
||||
}
|
||||
|
||||
/* Re-start the hostname lookup thread if we don't have hostname yet. */
|
||||
if (policy->lookup_ipv4_addr) {
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
struct in_addr addr = { .s_addr = policy->lookup_ipv4_addr };
|
||||
|
||||
if (!inet_ntop (AF_INET, &addr, buf, sizeof (buf)))
|
||||
strcpy (buf, "(unknown)");
|
||||
nm_log_dbg (LOGD_DNS, "restarting IPv4 reverse-lookup thread for address %s'", buf);
|
||||
|
||||
policy->lookup = hostname4_thread_new (policy->lookup_ipv4_addr, lookup_callback, policy);
|
||||
} else if (policy->lookup_ipv6_addr) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!inet_ntop (AF_INET6, policy->lookup_ipv6_addr, buf, sizeof (buf)))
|
||||
strcpy (buf, "(unknown)");
|
||||
nm_log_dbg (LOGD_DNS, "restarting IPv6 reverse-lookup thread for address %s'", buf);
|
||||
|
||||
policy->lookup = hostname6_thread_new (policy->lookup_ipv6_addr, lookup_callback, policy);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connection_updated (NMSettings *settings,
|
||||
NMConnection *connection,
|
||||
|
|
@ -1917,6 +1970,10 @@ nm_policy_new (NMManager *manager, NMSettings *settings)
|
|||
G_CALLBACK (firewall_started), policy);
|
||||
policy->fw_started_id = id;
|
||||
|
||||
policy->dns_manager = nm_dns_manager_get (NULL);
|
||||
policy->config_changed_id = g_signal_connect (policy->dns_manager, "config-changed",
|
||||
G_CALLBACK (dns_config_changed), policy);
|
||||
|
||||
_connect_manager_signal (policy, "state-changed", global_state_changed);
|
||||
_connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed);
|
||||
_connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed);
|
||||
|
|
@ -1955,6 +2012,7 @@ nm_policy_destroy (NMPolicy *policy)
|
|||
hostname_thread_kill (policy->lookup);
|
||||
policy->lookup = NULL;
|
||||
}
|
||||
g_free (policy->lookup_ipv6_addr);
|
||||
|
||||
g_slist_foreach (policy->pending_activation_checks, (GFunc) activate_data_free, NULL);
|
||||
g_slist_free (policy->pending_activation_checks);
|
||||
|
|
@ -1965,6 +2023,9 @@ nm_policy_destroy (NMPolicy *policy)
|
|||
g_signal_handler_disconnect (policy->fw_manager, policy->fw_started_id);
|
||||
g_object_unref (policy->fw_manager);
|
||||
|
||||
g_signal_handler_disconnect (policy->dns_manager, policy->config_changed_id);
|
||||
g_object_unref (policy->dns_manager);
|
||||
|
||||
for (iter = policy->manager_ids; iter; iter = g_slist_next (iter))
|
||||
g_signal_handler_disconnect (policy->manager, GPOINTER_TO_UINT (iter->data));
|
||||
g_slist_free (policy->manager_ids);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue