2008-09-18 Dan Williams <dcbw@redhat.com>
Implement support for honoring configured and automatic hostnames, and for setting the configured hostname. * introspection/nm-ip4-config.xml src/nm-ip4-config.c src/nm-ip4-config.h src/dhcp-manager/nm-dhcp-manager.c - Remove useless hostname property; it's not really part of the IPv4 config * introspection/nm-settings-system.xml libnm-glib/nm-dbus-settings-system.c libnm-glib/nm-dbus-settings-system.h - Add SetHostname() call to system settings D-Bus interface - Add Hostname property to system settings D-Bus interface - (nm_dbus_settings_system_save_hostname, nm_dbus_settings_system_get_hostname): implement * src/nm-device.c src/nm-device.h - (nm_device_get_dhcp4_config): implement * src/nm-manager.c src/nm-manager.h - Fetch and track system settings service hostname changes, and proxy the changes via a GObject property of the manager * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - Replace nm_system_config_interface_supports_add() with a capabilities bitfield * system-settings/src/nm-system-config-error.c system-settings/src/nm-system-config-error.h - Add additional errors * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - (get_property, nm_sysconfig_settings_class_init): add hostname property; first plugin returning a hostname wins - (impl_settings_add_connection): use plugin capabilities instead of nm_system_config_interface_supports_add() - (impl_settings_save_hostname): implement hostname saving * src/NetworkManagerPolicy.c - (lookup_thread_run_cb, lookup_thread_worker, lookup_thread_new, lookup_thread_die): implement an asynchronous hostname lookup thread which given an IPv4 address tries to look up the hostname for that address with reverse DNS - (get_best_device): split out best device code from update_routing_and_dns() - (update_etc_hosts): update /etc/hosts with the machine's new hostname to preserve the 127.0.0.1 reverse mapping that so many things require - (set_system_hostname): set a given hostname - (update_system_hostname): implement hostname policy; a configured hostname (from the system settings service) is used if available, otherwise an automatically determined hostname from DHCP, VPN, etc. If there was no automatically determined hostname, reverse DNS of the best device's IP address will be used, and as a last resort the hostname 'localhost.localdomain' is set. - (update_routing_and_dns): use get_best_device(); update the system hostname when the network config changes - (hostname_changed): update system hostname if the system settings service signals a hostname change - (nm_policy_new): list for system settings service hostname changes - (nm_policy_destroy): ensure that an in-progress hostname lookup thread gets told to die * system-settings/plugins/keyfile/plugin.c system-settings/plugins/ifcfg-suse/plugin.c - (get_property, sc_plugin_ifcfg_class_init): implement hostname and capabilities properties * system-settings/plugins/ifcfg-fedora/shvar.c - (svOpenFile): re-enable R/W access of ifcfg files since the plugin writes out /etc/sysconfig/network now * system-settings/plugins/ifcfg-fedora/plugin.c - (plugin_get_hostname): get hostname from /etc/sysconfig/network - (plugin_set_hostname): save hostname to /etc/sysconfig/network - (sc_network_changed_cb): handle changes to /etc/sysconfig/network - (sc_plugin_ifcfg_init): monitor /etc/sysconfig/network for changes - (get_property, set_property, sc_plugin_ifcfg_class_init): implement hostname get/set and capabilities get git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4077 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
@@ -17,10 +17,14 @@
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* (C) Copyright 2005 Red Hat, Inc.
|
||||
* (C) Copyright 2005 - 2008 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "NetworkManagerPolicy.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
@@ -40,6 +44,25 @@
|
||||
#include "NetworkManagerSystem.h"
|
||||
#include "nm-named-manager.h"
|
||||
|
||||
typedef struct LookupThread LookupThread;
|
||||
|
||||
typedef void (*LookupCallback) (LookupThread *thread, gpointer user_data);
|
||||
|
||||
struct LookupThread {
|
||||
GThread *thread;
|
||||
|
||||
GMutex *lock;
|
||||
gboolean die;
|
||||
int ret;
|
||||
|
||||
guint32 ip4_addr;
|
||||
char hostname[NI_MAXHOST + 1];
|
||||
|
||||
guint done_id;
|
||||
LookupCallback callback;
|
||||
gpointer user_data;
|
||||
};
|
||||
|
||||
struct NMPolicy {
|
||||
NMManager *manager;
|
||||
guint update_state_id;
|
||||
@@ -48,8 +71,92 @@ struct NMPolicy {
|
||||
GSList *dev_signal_ids;
|
||||
|
||||
NMDevice *default_device;
|
||||
|
||||
LookupThread *lookup;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
lookup_thread_run_cb (gpointer user_data)
|
||||
{
|
||||
LookupThread *thread = (LookupThread *) user_data;
|
||||
|
||||
(*thread->callback) (thread, thread->user_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
lookup_thread_worker (gpointer data)
|
||||
{
|
||||
LookupThread *thread = (LookupThread *) data;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
g_mutex_lock (thread->lock);
|
||||
if (thread->die) {
|
||||
g_mutex_unlock (thread->lock);
|
||||
return (gpointer) NULL;
|
||||
}
|
||||
g_mutex_unlock (thread->lock);
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = thread->ip4_addr;
|
||||
|
||||
thread->ret = getnameinfo ((struct sockaddr *) &addr, sizeof (struct sockaddr_in),
|
||||
thread->hostname, NI_MAXHOST, NULL, 0,
|
||||
NI_NAMEREQD);
|
||||
if (thread->ret == 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < strlen (thread->hostname); i++)
|
||||
thread->hostname[i] = tolower (thread->hostname[i]);
|
||||
}
|
||||
|
||||
thread->done_id = g_idle_add (lookup_thread_run_cb, thread);
|
||||
return (gpointer) TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_thread_free (LookupThread *thread)
|
||||
{
|
||||
g_return_if_fail (thread != NULL);
|
||||
|
||||
g_mutex_free (thread->lock);
|
||||
memset (thread, 0, sizeof (LookupThread));
|
||||
g_free (thread);
|
||||
}
|
||||
|
||||
static LookupThread *
|
||||
lookup_thread_new (guint32 ip4_addr, LookupCallback callback, gpointer user_data)
|
||||
{
|
||||
LookupThread *thread;
|
||||
|
||||
thread = g_malloc0 (sizeof (LookupThread));
|
||||
if (!thread)
|
||||
return NULL;
|
||||
|
||||
thread->lock = g_mutex_new ();
|
||||
thread->callback = callback;
|
||||
thread->user_data = user_data;
|
||||
thread->ip4_addr = ip4_addr;
|
||||
|
||||
thread->thread = g_thread_create (lookup_thread_worker, thread, FALSE, NULL);
|
||||
if (!thread->thread) {
|
||||
lookup_thread_free (thread);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_thread_die (LookupThread *thread)
|
||||
{
|
||||
g_return_if_fail (thread != NULL);
|
||||
|
||||
g_mutex_lock (thread->lock);
|
||||
thread->die = TRUE;
|
||||
g_mutex_unlock (thread->lock);
|
||||
}
|
||||
|
||||
#define INVALID_TAG "invalid"
|
||||
|
||||
static const char *
|
||||
@@ -65,28 +172,6 @@ get_connection_id (NMConnection *connection)
|
||||
return s_con->id;
|
||||
}
|
||||
|
||||
static void
|
||||
update_default_route (NMPolicy *policy, NMDevice *new)
|
||||
{
|
||||
const char *ip_iface;
|
||||
|
||||
/* FIXME: Not sure if the following makes any sense. */
|
||||
/* If iface and ip_iface are the same, it's a regular network device and we
|
||||
treat it as such. However, if they differ, it's most likely something like
|
||||
a serial device with ppp interface, so route all the traffic to it. */
|
||||
ip_iface = nm_device_get_ip_iface (new);
|
||||
if (strcmp (ip_iface, nm_device_get_iface (new))) {
|
||||
nm_system_device_replace_default_ip4_route (ip_iface, 0, 0);
|
||||
} else {
|
||||
NMIP4Config *config;
|
||||
const NMSettingIP4Address *def_addr;
|
||||
|
||||
config = nm_device_get_ip4_config (new);
|
||||
def_addr = nm_ip4_config_get_address (config, 0);
|
||||
nm_system_device_replace_default_ip4_route (ip_iface, def_addr->gateway, nm_ip4_config_get_mss (config));
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_device_priority (NMDevice *dev)
|
||||
{
|
||||
@@ -105,16 +190,19 @@ get_device_priority (NMDevice *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
update_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
||||
static NMDevice *
|
||||
get_best_device (NMManager *manager, NMActRequest **out_req)
|
||||
{
|
||||
GSList *devices, *iter;
|
||||
NMDevice *best = NULL;
|
||||
guint32 best_prio = 0;
|
||||
NMActRequest *best_req = NULL;
|
||||
GSList *devices, *iter;
|
||||
NMNamedManager *named_mgr;
|
||||
|
||||
devices = nm_manager_get_devices (policy->manager);
|
||||
g_return_val_if_fail (manager != NULL, NULL);
|
||||
g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (out_req != NULL, NULL);
|
||||
g_return_val_if_fail (*out_req == NULL, NULL);
|
||||
|
||||
devices = nm_manager_get_devices (manager);
|
||||
for (iter = devices; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *dev = NM_DEVICE (iter->data);
|
||||
NMActRequest *req;
|
||||
@@ -161,10 +249,259 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
||||
if (prio > best_prio) {
|
||||
best = dev;
|
||||
best_prio = prio;
|
||||
best_req = req;
|
||||
*out_req = req;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
#define FALLBACK_HOSTNAME "localhost.localdomain"
|
||||
|
||||
static gboolean
|
||||
update_etc_hosts (const char *hostname)
|
||||
{
|
||||
char *contents = NULL;
|
||||
char **lines = NULL, **line;
|
||||
GError *error = NULL;
|
||||
gboolean initial_comments = TRUE;
|
||||
gboolean added = FALSE;
|
||||
gsize contents_len = 0;
|
||||
GString *new_contents;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail (hostname != NULL, FALSE);
|
||||
|
||||
if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
|
||||
nm_warning ("%s: couldn't read " SYSCONFDIR "/hosts: (%d) %s",
|
||||
__func__, error ? error->code : 0,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
} else {
|
||||
lines = g_strsplit_set (contents, "\n\r", 0);
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
new_contents = g_string_sized_new (contents_len ? contents_len + 100 : 200);
|
||||
if (!new_contents) {
|
||||
nm_warning ("%s: not enough memory to update " SYSCONFDIR "/hosts", __func__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Replace any 127.0.0.1 entry that is at the beginning of the file or right
|
||||
* after initial comments. If there is no 127.0.0.1 entry at the beginning
|
||||
* or after initial comments, add one there and ignore any other 127.0.0.1
|
||||
* entries.
|
||||
*/
|
||||
for (line = lines; lines && *line; line++) {
|
||||
gboolean add_line = TRUE;
|
||||
|
||||
/* This is the first line after the initial comments */
|
||||
if (initial_comments && (*line[0] != '#')) {
|
||||
initial_comments = FALSE;
|
||||
g_string_append_printf (new_contents, "127.0.0.1\t%s", hostname);
|
||||
if (strcmp (hostname, FALLBACK_HOSTNAME))
|
||||
g_string_append_printf (new_contents, "\t" FALLBACK_HOSTNAME);
|
||||
g_string_append (new_contents, "\tlocalhost\n");
|
||||
added = TRUE;
|
||||
|
||||
/* Don't add the entry if it's supposed to be the actual localhost reverse mapping */
|
||||
if (!strncmp (*line, "127.0.0.1", strlen ("127.0.0.1")) && strstr (*line, "localhost"))
|
||||
add_line = FALSE;
|
||||
}
|
||||
|
||||
if (add_line) {
|
||||
g_string_append (new_contents, *line);
|
||||
g_string_append_c (new_contents, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* Hmm, /etc/hosts was empty for some reason */
|
||||
if (!added) {
|
||||
g_string_append (new_contents, "# Do not remove the following line, or various programs");
|
||||
g_string_append (new_contents, "# that require network functionality will fail.");
|
||||
g_string_append (new_contents, "127.0.0.1\t" FALLBACK_HOSTNAME "\tlocalhost");
|
||||
}
|
||||
|
||||
if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
|
||||
nm_warning ("%s: couldn't update " SYSCONFDIR "/hosts: (%d) %s",
|
||||
__func__, error ? error->code : 0,
|
||||
(error && error->message) ? error->message : "(unknown)");
|
||||
} else
|
||||
success = TRUE;
|
||||
|
||||
g_string_free (new_contents, TRUE);
|
||||
return success;
|
||||
}
|
||||
|
||||
static void
|
||||
set_system_hostname (const char *new_hostname, const char *msg)
|
||||
{
|
||||
char old_hostname[HOST_NAME_MAX + 1];
|
||||
int ret = 0;
|
||||
const char *name = new_hostname ? new_hostname : FALLBACK_HOSTNAME;
|
||||
|
||||
old_hostname[HOST_NAME_MAX] = '\0';
|
||||
errno = 0;
|
||||
ret = gethostname (old_hostname, HOST_NAME_MAX);
|
||||
if (ret != 0) {
|
||||
nm_warning ("%s: couldn't get the system hostname: (%d) %s",
|
||||
__func__, errno, strerror (errno));
|
||||
} else {
|
||||
/* Do nothing if the hostname isn't actually changing */
|
||||
if ( (new_hostname && !strcmp (old_hostname, new_hostname))
|
||||
|| (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME)))
|
||||
return;
|
||||
}
|
||||
|
||||
nm_info ("Setting system hostname to '%s' (%s)", name, msg);
|
||||
|
||||
ret = sethostname (name, strlen (name));
|
||||
if (ret == 0) {
|
||||
if (!update_etc_hosts (name)) {
|
||||
/* error updating /etc/hosts; fallback to localhost.localdomain */
|
||||
nm_info ("Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)");
|
||||
sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME));
|
||||
}
|
||||
} else {
|
||||
nm_warning ("%s: couldn't set the system hostname to '%s': (%d) %s",
|
||||
__func__, name, errno, strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_callback (LookupThread *thread, gpointer user_data)
|
||||
{
|
||||
NMPolicy *policy = (NMPolicy *) user_data;
|
||||
|
||||
/* If the thread was told to die or it's not the current in-progress
|
||||
* hostname lookup, nothing to do.
|
||||
*/
|
||||
if (thread->die || (thread != policy->lookup))
|
||||
goto done;
|
||||
|
||||
policy->lookup = NULL;
|
||||
if (!strlen (thread->hostname)) {
|
||||
char *msg;
|
||||
|
||||
/* No valid IP4 config (!!); fall back to localhost.localdomain */
|
||||
msg = g_strdup_printf ("address lookup failed: %d", thread->ret);
|
||||
set_system_hostname (NULL, msg);
|
||||
g_free (msg);
|
||||
} else
|
||||
set_system_hostname (thread->hostname, "from address lookup");
|
||||
|
||||
done:
|
||||
lookup_thread_free (thread);
|
||||
}
|
||||
|
||||
static void
|
||||
update_system_hostname (NMPolicy *policy, NMDevice *best)
|
||||
{
|
||||
char *configured_hostname = NULL;
|
||||
NMActRequest *best_req = NULL;
|
||||
NMDHCP4Config *dhcp4_config;
|
||||
NMIP4Config *ip4_config;
|
||||
const NMSettingIP4Address *addr;
|
||||
|
||||
g_return_if_fail (policy != NULL);
|
||||
|
||||
if (policy->lookup) {
|
||||
lookup_thread_die (policy->lookup);
|
||||
policy->lookup = NULL;
|
||||
}
|
||||
|
||||
/* A configured hostname (via the system-settings service) overrides
|
||||
* all automatic hostname determination. If there is no configured hostname,
|
||||
* the best device's automatically determined hostname (from DHCP, VPN, PPP,
|
||||
* etc) is used. If there is no automatically determined hostname, reverse
|
||||
* DNS lookup using the best device's IP address is started to determined the
|
||||
* the hostname.
|
||||
*/
|
||||
|
||||
/* Try a configured hostname first */
|
||||
g_object_get (G_OBJECT (policy->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL);
|
||||
if (configured_hostname) {
|
||||
set_system_hostname (configured_hostname, "from system configuration");
|
||||
g_free (configured_hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try automatically determined hostname from the best device's IP config */
|
||||
if (!best)
|
||||
best = get_best_device (policy->manager, &best_req);
|
||||
|
||||
if (!best) {
|
||||
/* No best device; fall back to localhost.localdomain */
|
||||
set_system_hostname (NULL, "no default device");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Grab a hostname out of the device's DHCP4 config */
|
||||
dhcp4_config = nm_device_get_dhcp4_config (best);
|
||||
if (dhcp4_config) {
|
||||
const char *dhcp4_hostname;
|
||||
|
||||
dhcp4_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name");
|
||||
if (dhcp4_hostname && strlen (dhcp4_hostname)) {
|
||||
set_system_hostname (dhcp4_hostname, "from DHCP");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No configured hostname, no automatically determined hostname either. Start
|
||||
* reverse DNS of the current IP address to try and find it.
|
||||
*/
|
||||
ip4_config = nm_device_get_ip4_config (best);
|
||||
if ( !ip4_config
|
||||
|| (nm_ip4_config_get_num_nameservers (ip4_config) == 0)
|
||||
|| (nm_ip4_config_get_num_addresses (ip4_config) == 0)) {
|
||||
/* No valid IP4 config (!!); fall back to localhost.localdomain */
|
||||
set_system_hostname (NULL, "no IPv4 config");
|
||||
return;
|
||||
}
|
||||
|
||||
addr = nm_ip4_config_get_address (ip4_config, 0);
|
||||
g_assert (addr); /* checked for > 1 address above */
|
||||
|
||||
/* Start the hostname lookup thread */
|
||||
policy->lookup = lookup_thread_new (addr->address, lookup_callback, policy);
|
||||
if (!policy->lookup) {
|
||||
/* Fall back to 'localhost.localdomain' */
|
||||
set_system_hostname (NULL, "error starting hostname thread");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_default_route (NMPolicy *policy, NMDevice *new)
|
||||
{
|
||||
const char *ip_iface;
|
||||
|
||||
/* FIXME: Not sure if the following makes any sense. */
|
||||
/* If iface and ip_iface are the same, it's a regular network device and we
|
||||
treat it as such. However, if they differ, it's most likely something like
|
||||
a serial device with ppp interface, so route all the traffic to it. */
|
||||
ip_iface = nm_device_get_ip_iface (new);
|
||||
if (strcmp (ip_iface, nm_device_get_iface (new))) {
|
||||
nm_system_device_replace_default_ip4_route (ip_iface, 0, 0);
|
||||
} else {
|
||||
NMIP4Config *config;
|
||||
const NMSettingIP4Address *def_addr;
|
||||
|
||||
config = nm_device_get_ip4_config (new);
|
||||
def_addr = nm_ip4_config_get_address (config, 0);
|
||||
nm_system_device_replace_default_ip4_route (ip_iface, def_addr->gateway, nm_ip4_config_get_mss (config));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
||||
{
|
||||
NMDevice *best = NULL;
|
||||
NMActRequest *best_req = NULL;
|
||||
NMNamedManager *named_mgr;
|
||||
GSList *devices = NULL, *iter;
|
||||
|
||||
best = get_best_device (policy->manager, &best_req);
|
||||
if (!best)
|
||||
goto out;
|
||||
if (!force_update && (best == policy->default_device))
|
||||
@@ -177,6 +514,7 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
||||
* first. The order is important, we don't want two connections marked
|
||||
* default at the same time ever.
|
||||
*/
|
||||
devices = nm_manager_get_devices (policy->manager);
|
||||
for (iter = devices; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *dev = NM_DEVICE (iter->data);
|
||||
NMActRequest *req;
|
||||
@@ -203,6 +541,9 @@ update_routing_and_dns (NMPolicy *policy, gboolean force_update)
|
||||
nm_device_get_iface (best));
|
||||
|
||||
out:
|
||||
/* Update the system hostname */
|
||||
update_system_hostname (policy, best);
|
||||
|
||||
policy->default_device = best;
|
||||
}
|
||||
|
||||
@@ -291,6 +632,12 @@ global_state_changed (NMManager *manager, NMState state, gpointer user_data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data)
|
||||
{
|
||||
update_system_hostname ((NMPolicy *) user_data, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
schedule_activate_check (NMPolicy *policy, NMDevice *device)
|
||||
{
|
||||
@@ -547,6 +894,10 @@ nm_policy_new (NMManager *manager)
|
||||
G_CALLBACK (global_state_changed), policy);
|
||||
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
|
||||
|
||||
id = g_signal_connect (manager, "notify::hostname",
|
||||
G_CALLBACK (hostname_changed), policy);
|
||||
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
|
||||
|
||||
id = g_signal_connect (manager, "device-added",
|
||||
G_CALLBACK (device_added), policy);
|
||||
policy->signal_ids = g_slist_append (policy->signal_ids, (gpointer) id);
|
||||
@@ -585,6 +936,14 @@ nm_policy_destroy (NMPolicy *policy)
|
||||
|
||||
g_return_if_fail (policy != NULL);
|
||||
|
||||
/* Tell any existing hostname lookup thread to die, it'll get cleaned up
|
||||
* by the lookup thread callback.
|
||||
*/
|
||||
if (policy->lookup) {
|
||||
lookup_thread_die (policy->lookup);
|
||||
policy->lookup = NULL;
|
||||
}
|
||||
|
||||
for (iter = policy->pending_activation_checks; iter; iter = g_slist_next (iter)) {
|
||||
ActivateData *data = (ActivateData *) iter->data;
|
||||
|
||||
|
Reference in New Issue
Block a user