mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-04 03:40:27 +01:00
2008-09-25 Dan Williams <dcbw@redhat.com>
Fix bgo #549401 (inspired by patch from Alexander Sack) * src/nm-device-ethernet.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): rename from supplicant_interface_clean to match nm-device-wifi.c; clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler, supplicant_connection_timeout_cb): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_ethernet_dispose): clean up any pending supplicant state tasks * src/nm-device-wifi.c - (finish_supplicant_task): clean up scheduled tasks and free memory - (remove_supplicant_interface_error_handler): remove the supplicant error idle callback too - (supplicant_interface_release): clean up supplicant interface-related state tasks when the supplicant interface is disposed of - (schedule_state_handler): add scheduled tasks to a list so they can be cleaned up later - (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler, supplicant_iface_connection_state_cb_handler): use finish_supplicant_task() to clean up each completed task - (supplicant_iface_connection_error_cb_handler): clear source id when the task is complete - (supplicant_iface_connection_error_cb): save scheduled task id for later cleanup - (nm_device_wifi_dispose): clean up any pending supplicant state tasks git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@4105 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
parent
323f61531a
commit
79256975d1
3 changed files with 314 additions and 153 deletions
41
ChangeLog
41
ChangeLog
|
|
@ -1,3 +1,44 @@
|
|||
2008-09-25 Dan Williams <dcbw@redhat.com>
|
||||
|
||||
Fix bgo #549401 (inspired by patch from Alexander Sack)
|
||||
|
||||
* src/nm-device-ethernet.c
|
||||
- (finish_supplicant_task): clean up scheduled tasks and free memory
|
||||
- (remove_supplicant_interface_error_handler): remove the supplicant
|
||||
error idle callback too
|
||||
- (supplicant_interface_release): rename from supplicant_interface_clean
|
||||
to match nm-device-wifi.c; clean up supplicant interface-related
|
||||
state tasks when the supplicant interface is disposed of
|
||||
- (schedule_state_handler): add scheduled tasks to a list so they can
|
||||
be cleaned up later
|
||||
- (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler,
|
||||
supplicant_iface_connection_state_cb_handler): use
|
||||
finish_supplicant_task() to clean up each completed task
|
||||
- (supplicant_iface_connection_error_cb_handler,
|
||||
supplicant_connection_timeout_cb): clear source id when the task is
|
||||
complete
|
||||
- (supplicant_iface_connection_error_cb): save scheduled task id for
|
||||
later cleanup
|
||||
- (nm_device_ethernet_dispose): clean up any pending supplicant state
|
||||
tasks
|
||||
|
||||
* src/nm-device-wifi.c
|
||||
- (finish_supplicant_task): clean up scheduled tasks and free memory
|
||||
- (remove_supplicant_interface_error_handler): remove the supplicant
|
||||
error idle callback too
|
||||
- (supplicant_interface_release): clean up supplicant interface-related
|
||||
state tasks when the supplicant interface is disposed of
|
||||
- (schedule_state_handler): add scheduled tasks to a list so they can
|
||||
be cleaned up later
|
||||
- (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler,
|
||||
supplicant_iface_connection_state_cb_handler): use
|
||||
finish_supplicant_task() to clean up each completed task
|
||||
- (supplicant_iface_connection_error_cb_handler): clear source id when
|
||||
the task is complete
|
||||
- (supplicant_iface_connection_error_cb): save scheduled task id for
|
||||
later cleanup
|
||||
- (nm_device_wifi_dispose): clean up any pending supplicant state tasks
|
||||
|
||||
2008-09-24 Tambet Ingo <tambet@gmail.com>
|
||||
|
||||
* system-settings/plugins/keyfile/plugin.c: Implement unmanaged_devices
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
* 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 <glib.h>
|
||||
|
|
@ -73,17 +73,30 @@ typedef enum
|
|||
#define NM_ETHERNET_ERROR (nm_ethernet_error_quark ())
|
||||
#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ())
|
||||
|
||||
typedef struct SupplicantStateTask {
|
||||
NMDeviceEthernet *self;
|
||||
guint32 new_state;
|
||||
guint32 old_state;
|
||||
gboolean mgr_task;
|
||||
guint source_id;
|
||||
} SupplicantStateTask;
|
||||
|
||||
typedef struct Supplicant {
|
||||
NMSupplicantManager *mgr;
|
||||
NMSupplicantInterface *iface;
|
||||
|
||||
/* signal handler ids */
|
||||
guint mgr_state_id;
|
||||
guint iface_error_id;
|
||||
guint iface_state_id;
|
||||
guint iface_con_state_id;
|
||||
guint mgr_state_id;
|
||||
guint iface_error_id;
|
||||
guint iface_state_id;
|
||||
guint iface_con_state_id;
|
||||
|
||||
guint con_timeout_id;
|
||||
/* Timeouts and idles */
|
||||
guint iface_con_error_cb_id;
|
||||
guint con_timeout_id;
|
||||
|
||||
GSList *iface_tasks;
|
||||
GSList *mgr_tasks;
|
||||
} Supplicant;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -664,7 +677,31 @@ remove_supplicant_timeouts (NMDeviceEthernet *self)
|
|||
}
|
||||
|
||||
static void
|
||||
remove_supplicant_interface_connection_error_handler (NMDeviceEthernet *self)
|
||||
finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source)
|
||||
{
|
||||
NMDeviceEthernet *self = task->self;
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
|
||||
/* idle/timeout handlers should pass FALSE for remove_source, since they
|
||||
* will tell glib to remove their source from the mainloop by returning
|
||||
* FALSE when they exit. When called from this NMDevice's dispose handler,
|
||||
* remove_source should be TRUE to cancel all outstanding idle/timeout
|
||||
* handlers asynchronously.
|
||||
*/
|
||||
if (task->source_id && remove_source)
|
||||
g_source_remove (task->source_id);
|
||||
|
||||
if (task->mgr_task)
|
||||
priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task);
|
||||
else
|
||||
priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task);
|
||||
|
||||
memset (task, 0, sizeof (SupplicantStateTask));
|
||||
g_slice_free (SupplicantStateTask, task);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_supplicant_interface_error_handler (NMDeviceEthernet *self)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
|
||||
|
|
@ -672,15 +709,24 @@ remove_supplicant_interface_connection_error_handler (NMDeviceEthernet *self)
|
|||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_con_error_cb_id > 0) {
|
||||
g_source_remove (priv->supplicant.iface_con_error_cb_id);
|
||||
priv->supplicant.iface_con_error_cb_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_interface_clean (NMDeviceEthernet *self)
|
||||
supplicant_interface_release (NMDeviceEthernet *self)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
|
||||
remove_supplicant_timeouts (self);
|
||||
remove_supplicant_interface_connection_error_handler (self);
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
|
||||
/* Clean up all pending supplicant interface state idle tasks */
|
||||
while (priv->supplicant.iface_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
|
||||
|
||||
if (priv->supplicant.iface_con_state_id) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id);
|
||||
|
|
@ -739,7 +785,7 @@ link_timeout_cb (gpointer user_data)
|
|||
|
||||
nm_info ("Activation (%s/wired): disconnected during authentication,"
|
||||
" asking for new key.", nm_device_get_iface (dev));
|
||||
supplicant_interface_clean (self);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
|
||||
nm_act_request_request_connection_secrets (req, setting_name, TRUE,
|
||||
|
|
@ -754,42 +800,47 @@ time_out:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
struct state_cb_data {
|
||||
NMDeviceEthernet *self;
|
||||
guint32 new_state;
|
||||
guint32 old_state;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
schedule_state_handler (NMDeviceEthernet *self,
|
||||
GSourceFunc handler,
|
||||
guint32 new_state,
|
||||
guint32 old_state)
|
||||
guint32 old_state,
|
||||
gboolean mgr_task)
|
||||
{
|
||||
struct state_cb_data * cb_data;
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
SupplicantStateTask *task;
|
||||
|
||||
if (new_state == old_state)
|
||||
return TRUE;
|
||||
|
||||
cb_data = g_slice_new0 (struct state_cb_data);
|
||||
cb_data->self = self;
|
||||
cb_data->new_state = new_state;
|
||||
cb_data->old_state = old_state;
|
||||
task = g_slice_new0 (SupplicantStateTask);
|
||||
if (!task) {
|
||||
nm_warning ("Not enough memory to process supplicant manager state change.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_idle_add (handler, cb_data);
|
||||
task->self = self;
|
||||
task->new_state = new_state;
|
||||
task->old_state = old_state;
|
||||
task->mgr_task = mgr_task;
|
||||
|
||||
task->source_id = g_idle_add (handler, task);
|
||||
if (mgr_task)
|
||||
priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task);
|
||||
else
|
||||
priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supplicant_mgr_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data *info = (struct state_cb_data *) user_data;
|
||||
NMDevice *device = NM_DEVICE (info->self);
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDevice *device = NM_DEVICE (task->self);
|
||||
|
||||
/* If the supplicant went away, release the supplicant interface */
|
||||
if (info->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
supplicant_interface_clean (info->self);
|
||||
if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
supplicant_interface_release (task->self);
|
||||
|
||||
if (nm_device_get_state (device) > NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE,
|
||||
|
|
@ -797,8 +848,7 @@ supplicant_mgr_state_cb_handler (gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, info);
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -814,8 +864,10 @@ supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
|||
old_state);
|
||||
|
||||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_mgr_state_cb_handler,
|
||||
new_state, old_state);
|
||||
supplicant_mgr_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static NMSupplicantConfig *
|
||||
|
|
@ -848,17 +900,17 @@ build_supplicant_config (NMDeviceEthernet *self)
|
|||
static gboolean
|
||||
supplicant_iface_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data *info = (struct state_cb_data *) user_data;
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (info->self);
|
||||
NMDevice *device = NM_DEVICE (info->self);
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self);
|
||||
NMDevice *device = NM_DEVICE (task->self);
|
||||
|
||||
if (info->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
NMSupplicantConfig *config;
|
||||
const char *iface;
|
||||
gboolean success = FALSE;
|
||||
|
||||
iface = nm_device_get_iface (device);
|
||||
config = build_supplicant_config (info->self);
|
||||
config = build_supplicant_config (task->self);
|
||||
if (config) {
|
||||
success = nm_supplicant_interface_set_config (priv->supplicant.iface, config);
|
||||
g_object_unref (config);
|
||||
|
|
@ -871,17 +923,16 @@ supplicant_iface_state_cb_handler (gpointer user_data)
|
|||
|
||||
if (!success)
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
|
||||
} else if (info->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
NMDeviceState state = nm_device_get_state (device);
|
||||
|
||||
supplicant_interface_clean (info->self);
|
||||
supplicant_interface_release (task->self);
|
||||
|
||||
if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED)
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, info);
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -900,18 +951,19 @@ supplicant_iface_state_cb (NMSupplicantInterface * iface,
|
|||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_iface_state_cb_handler,
|
||||
new_state,
|
||||
old_state);
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data *info = (struct state_cb_data *) user_data;
|
||||
NMDevice *dev = NM_DEVICE (info->self);
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDevice *dev = NM_DEVICE (task->self);
|
||||
|
||||
if (info->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
remove_supplicant_interface_connection_error_handler (info->self);
|
||||
remove_supplicant_timeouts (info->self);
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
remove_supplicant_interface_error_handler (task->self);
|
||||
remove_supplicant_timeouts (task->self);
|
||||
|
||||
/* If this is the initial association during device activation,
|
||||
* schedule the next activation stage.
|
||||
|
|
@ -921,9 +973,9 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
|||
nm_device_get_iface (dev));
|
||||
nm_device_activate_schedule_stage3_ip_config_start (dev);
|
||||
}
|
||||
} else if (info->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
|
||||
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
|
||||
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) {
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (info->self);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self);
|
||||
|
||||
/* Start the link timeout so we allow some time for reauthentication */
|
||||
if (!priv->link_timeout_id)
|
||||
|
|
@ -931,8 +983,7 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, info);
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -948,17 +999,20 @@ supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
|||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_iface_connection_state_cb_handler,
|
||||
new_state,
|
||||
old_state);
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_error_cb_handler (gpointer user_data)
|
||||
{
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
|
||||
supplicant_interface_clean (self);
|
||||
supplicant_interface_release (self);
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
|
||||
|
||||
priv->supplicant.iface_con_error_cb_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -968,12 +1022,18 @@ supplicant_iface_connection_error_cb (NMSupplicantInterface *iface,
|
|||
const char *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE (user_data);
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
guint id;
|
||||
|
||||
nm_info ("Activation (%s/wired): association request to the supplicant failed: %s - %s",
|
||||
nm_device_get_iface (device), name, message);
|
||||
nm_device_get_iface (NM_DEVICE (self)), name, message);
|
||||
|
||||
g_idle_add (supplicant_iface_connection_error_cb_handler, device);
|
||||
if (priv->supplicant.iface_con_error_cb_id)
|
||||
g_source_remove (priv->supplicant.iface_con_error_cb_id);
|
||||
|
||||
id = g_idle_add (supplicant_iface_connection_error_cb_handler, self);
|
||||
priv->supplicant.iface_con_error_cb_id = id;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
|
|
@ -1017,16 +1077,19 @@ static gboolean
|
|||
supplicant_connection_timeout_cb (gpointer user_data)
|
||||
{
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
NMDevice *device = NM_DEVICE (self);
|
||||
NMActRequest *req;
|
||||
const char *iface;
|
||||
|
||||
priv->supplicant.con_timeout_id = 0;
|
||||
|
||||
iface = nm_device_get_iface (device);
|
||||
|
||||
/* Authentication failed, encryption key is probably bad */
|
||||
nm_info ("Activation (%s/wired): association took too long.", iface);
|
||||
|
||||
supplicant_interface_clean (self);
|
||||
supplicant_interface_release (self);
|
||||
req = nm_device_get_act_request (device);
|
||||
g_assert (req);
|
||||
|
||||
|
|
@ -1050,7 +1113,7 @@ supplicant_interface_init (NMDeviceEthernet *self)
|
|||
priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr, iface, FALSE);
|
||||
if (!priv->supplicant.iface) {
|
||||
nm_warning ("Couldn't initialize supplicant interface for %s.", iface);
|
||||
supplicant_interface_clean (self);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1290,7 +1353,7 @@ real_deactivate_quickly (NMDevice *device)
|
|||
priv->ppp_manager = NULL;
|
||||
}
|
||||
|
||||
supplicant_interface_clean (NM_DEVICE_ETHERNET (device));
|
||||
supplicant_interface_release (NM_DEVICE_ETHERNET (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1345,7 +1408,8 @@ real_check_connection_compatible (NMDevice *device,
|
|||
static void
|
||||
nm_device_ethernet_dispose (GObject *object)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
NMNetlinkMonitor *monitor;
|
||||
|
||||
if (priv->dispose_has_run) {
|
||||
|
|
@ -1355,6 +1419,12 @@ nm_device_ethernet_dispose (GObject *object)
|
|||
|
||||
priv->dispose_has_run = TRUE;
|
||||
|
||||
/* Clean up all pending supplicant tasks */
|
||||
while (priv->supplicant.iface_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
|
||||
while (priv->supplicant.mgr_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE);
|
||||
|
||||
monitor = nm_netlink_monitor_get ();
|
||||
if (priv->link_connected_id) {
|
||||
g_signal_handler_disconnect (monitor, priv->link_connected_id);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
* 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.
|
||||
* (C) Copyright 2007 - 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
|
@ -106,20 +107,32 @@ typedef enum
|
|||
#define NM_WIFI_ERROR (nm_wifi_error_quark ())
|
||||
#define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ())
|
||||
|
||||
typedef struct SupplicantStateTask {
|
||||
NMDeviceWifi *self;
|
||||
guint32 new_state;
|
||||
guint32 old_state;
|
||||
gboolean mgr_task;
|
||||
guint source_id;
|
||||
} SupplicantStateTask;
|
||||
|
||||
typedef struct Supplicant {
|
||||
NMSupplicantManager * mgr;
|
||||
NMSupplicantInterface * iface;
|
||||
|
||||
/* signal handler ids */
|
||||
guint mgr_state_id;
|
||||
guint iface_error_id;
|
||||
guint iface_state_id;
|
||||
guint iface_scanned_ap_id;
|
||||
guint iface_scan_result_id;
|
||||
guint iface_con_state_id;
|
||||
guint mgr_state_id;
|
||||
guint iface_error_id;
|
||||
guint iface_state_id;
|
||||
guint iface_scanned_ap_id;
|
||||
guint iface_scan_result_id;
|
||||
guint iface_con_state_id;
|
||||
|
||||
guint con_timeout_id;
|
||||
/* Timeouts and idles */
|
||||
guint iface_con_error_cb_id;
|
||||
guint con_timeout_id;
|
||||
|
||||
GSList *mgr_tasks;
|
||||
GSList *iface_tasks;
|
||||
} Supplicant;
|
||||
|
||||
struct _NMDeviceWifiPrivate
|
||||
|
|
@ -147,11 +160,11 @@ struct _NMDeviceWifiPrivate
|
|||
guint8 scan_interval; /* seconds */
|
||||
guint pending_scan_id;
|
||||
|
||||
Supplicant supplicant;
|
||||
Supplicant supplicant;
|
||||
|
||||
guint32 failed_link_count;
|
||||
guint periodic_source_id;
|
||||
guint link_timeout_id;
|
||||
guint32 failed_link_count;
|
||||
guint periodic_source_id;
|
||||
guint link_timeout_id;
|
||||
|
||||
/* Static options from driver */
|
||||
guint8 we_version;
|
||||
|
|
@ -405,7 +418,6 @@ nm_device_wifi_init (NMDeviceWifi * self)
|
|||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
priv->dispose_has_run = FALSE;
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
priv->scanning = FALSE;
|
||||
priv->ap_list = NULL;
|
||||
priv->we_version = 0;
|
||||
|
|
@ -589,6 +601,49 @@ supplicant_interface_acquire (NMDeviceWifi *self)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source)
|
||||
{
|
||||
NMDeviceWifi *self = task->self;
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
/* idle/timeout handlers should pass FALSE for remove_source, since they
|
||||
* will tell glib to remove their source from the mainloop by returning
|
||||
* FALSE when they exit. When called from this NMDevice's dispose handler,
|
||||
* remove_source should be TRUE to cancel all outstanding idle/timeout
|
||||
* handlers asynchronously.
|
||||
*/
|
||||
if (task->source_id && remove_source)
|
||||
g_source_remove (task->source_id);
|
||||
|
||||
if (task->mgr_task)
|
||||
priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task);
|
||||
else
|
||||
priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task);
|
||||
|
||||
memset (task, 0, sizeof (SupplicantStateTask));
|
||||
g_slice_free (SupplicantStateTask, task);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_supplicant_interface_error_handler (NMDeviceWifi *self)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->supplicant.iface)
|
||||
return;
|
||||
|
||||
if (priv->supplicant.iface_error_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_con_error_cb_id > 0) {
|
||||
g_source_remove (priv->supplicant.iface_con_error_cb_id);
|
||||
priv->supplicant.iface_con_error_cb_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_interface_release (NMDeviceWifi *self)
|
||||
{
|
||||
|
|
@ -603,10 +658,11 @@ supplicant_interface_release (NMDeviceWifi *self)
|
|||
/* Reset the scan interval to be pretty frequent when disconnected */
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
|
||||
|
||||
if (priv->supplicant.iface_error_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
|
||||
/* Clean up all pending supplicant interface state idle tasks */
|
||||
while (priv->supplicant.iface_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
|
||||
|
||||
if (priv->supplicant.iface_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
|
||||
|
|
@ -1944,27 +2000,12 @@ supplicant_iface_scanned_ap_cb (NMSupplicantInterface *iface,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_supplicant_interface_connection_error_handler (NMDeviceWifi *self)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->supplicant.iface)
|
||||
return;
|
||||
|
||||
if (priv->supplicant.iface_error_id != 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface,
|
||||
priv->supplicant.iface_error_id);
|
||||
priv->supplicant.iface_error_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
remove_supplicant_interface_connection_error_handler (self);
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
if (disconnect && priv->supplicant.iface)
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
|
|
@ -2074,20 +2115,15 @@ time_out:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
struct state_cb_data {
|
||||
NMDeviceWifi * self;
|
||||
guint32 new_state;
|
||||
guint32 old_state;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
schedule_state_handler (NMDeviceWifi * self,
|
||||
schedule_state_handler (NMDeviceWifi *self,
|
||||
GSourceFunc handler,
|
||||
guint32 new_state,
|
||||
guint32 old_state)
|
||||
guint32 old_state,
|
||||
gboolean mgr_task)
|
||||
{
|
||||
struct state_cb_data * cb_data;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
SupplicantStateTask *task;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (handler != NULL, FALSE);
|
||||
|
|
@ -2095,18 +2131,24 @@ schedule_state_handler (NMDeviceWifi * self,
|
|||
if (new_state == old_state)
|
||||
return TRUE;
|
||||
|
||||
cb_data = g_slice_new0 (struct state_cb_data);
|
||||
if (cb_data == NULL) {
|
||||
nm_warning ("Not enough memory to process supplicant manager state"
|
||||
" change.");
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
task = g_slice_new0 (SupplicantStateTask);
|
||||
if (!task) {
|
||||
nm_warning ("Not enough memory to process supplicant manager state change.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cb_data->self = self;
|
||||
cb_data->new_state = new_state;
|
||||
cb_data->old_state = old_state;
|
||||
task->self = self;
|
||||
task->new_state = new_state;
|
||||
task->old_state = old_state;
|
||||
task->mgr_task = mgr_task;
|
||||
|
||||
g_idle_add (handler, cb_data);
|
||||
task->source_id = g_idle_add (handler, task);
|
||||
if (mgr_task)
|
||||
priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task);
|
||||
else
|
||||
priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -2114,37 +2156,34 @@ schedule_state_handler (NMDeviceWifi * self,
|
|||
static gboolean
|
||||
supplicant_iface_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data *cb_data = (struct state_cb_data *) user_data;
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
guint32 new_state, old_state;
|
||||
|
||||
g_return_val_if_fail (cb_data != NULL, FALSE);
|
||||
g_return_val_if_fail (task != NULL, FALSE);
|
||||
|
||||
self = cb_data->self;
|
||||
self = task->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
new_state = cb_data->new_state;
|
||||
old_state = cb_data->old_state;
|
||||
|
||||
nm_info ("(%s): supplicant interface state change: %d -> %d.",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
old_state,
|
||||
new_state);
|
||||
task->old_state,
|
||||
task->new_state);
|
||||
|
||||
if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN;
|
||||
|
||||
/* Request a scan to get latest results */
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
supplicant_interface_release (self);
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, cb_data);
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -2160,19 +2199,18 @@ supplicant_iface_state_cb (NMSupplicantInterface * iface,
|
|||
schedule_state_handler (self,
|
||||
supplicant_iface_state_cb_handler,
|
||||
new_state,
|
||||
old_state);
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data *cb_data = (struct state_cb_data *) user_data;
|
||||
NMDeviceWifi *self = cb_data->self;
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self = task->self;
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMDevice *dev = NM_DEVICE (self);
|
||||
guint32 new_state = cb_data->new_state;
|
||||
guint32 old_state = cb_data->old_state;
|
||||
|
||||
if (!nm_device_get_act_request (dev)) {
|
||||
/* The device is not activating or already activated; do nothing. */
|
||||
|
|
@ -2180,12 +2218,12 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
|||
}
|
||||
|
||||
nm_info ("(%s): supplicant connection state change: %d -> %d",
|
||||
nm_device_get_iface (dev), old_state, new_state);
|
||||
nm_device_get_iface (dev), task->old_state, task->new_state);
|
||||
|
||||
priv->scanning = (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING);
|
||||
priv->scanning = (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING);
|
||||
|
||||
if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
remove_supplicant_interface_connection_error_handler (self);
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
|
||||
/* If this is the initial association during device activation,
|
||||
|
|
@ -2201,7 +2239,7 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
|||
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
|
||||
nm_device_activate_schedule_stage3_ip_config_start (dev);
|
||||
}
|
||||
} else if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
|
||||
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
|
||||
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) {
|
||||
/* Start the link timeout so we allow some time for reauthentication,
|
||||
* use a longer timeout if we are scanning since some cards take a
|
||||
|
|
@ -2215,7 +2253,7 @@ supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
|||
}
|
||||
|
||||
out:
|
||||
g_slice_free (struct state_cb_data, cb_data);
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -2231,35 +2269,32 @@ supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
|||
schedule_state_handler (self,
|
||||
supplicant_iface_connection_state_cb_handler,
|
||||
new_state,
|
||||
old_state);
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_mgr_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
struct state_cb_data * cb_data = (struct state_cb_data *) user_data;
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
NMDevice *dev;
|
||||
guint32 new_state, old_state;
|
||||
NMDeviceState dev_state;
|
||||
|
||||
g_return_val_if_fail (cb_data != NULL, FALSE);
|
||||
g_return_val_if_fail (task != NULL, FALSE);
|
||||
|
||||
self = cb_data->self;
|
||||
self = task->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
dev = NM_DEVICE (self);
|
||||
new_state = cb_data->new_state;
|
||||
old_state = cb_data->old_state;
|
||||
|
||||
nm_info ("(%s): supplicant manager is now in state %d (from %d).",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
new_state,
|
||||
old_state);
|
||||
task->new_state, task->old_state);
|
||||
|
||||
/* If the supplicant went away, release the supplicant interface */
|
||||
if (new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
if (priv->supplicant.iface) {
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
supplicant_interface_release (self);
|
||||
|
|
@ -2269,7 +2304,7 @@ supplicant_mgr_state_cb_handler (gpointer user_data)
|
|||
nm_device_state_changed (dev, NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
} else if (new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
|
||||
} else if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
|
||||
dev_state = nm_device_get_state (dev);
|
||||
if ( priv->enabled
|
||||
&& !priv->supplicant.iface
|
||||
|
|
@ -2287,7 +2322,7 @@ supplicant_mgr_state_cb_handler (gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
g_slice_free (struct state_cb_data, cb_data);
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -2302,25 +2337,27 @@ supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
|||
schedule_state_handler (self,
|
||||
supplicant_mgr_state_cb_handler,
|
||||
new_state,
|
||||
old_state);
|
||||
old_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
struct iface_con_error_cb_data {
|
||||
NMDeviceWifi * self;
|
||||
char * name;
|
||||
char * message;
|
||||
NMDeviceWifi *self;
|
||||
char *name;
|
||||
char *message;
|
||||
};
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_error_cb_handler (gpointer user_data)
|
||||
{
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
struct iface_con_error_cb_data * cb_data = (struct iface_con_error_cb_data *) user_data;
|
||||
NMDeviceWifi * self;
|
||||
|
||||
g_return_val_if_fail (cb_data != NULL, FALSE);
|
||||
|
||||
self = cb_data->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
if (!nm_device_is_activating (NM_DEVICE (self)))
|
||||
goto out;
|
||||
|
|
@ -2335,6 +2372,7 @@ supplicant_iface_connection_error_cb_handler (gpointer user_data)
|
|||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
|
||||
out:
|
||||
priv->supplicant.iface_con_error_cb_id = 0;
|
||||
g_free (cb_data->name);
|
||||
g_free (cb_data->message);
|
||||
g_slice_free (struct iface_con_error_cb_data, cb_data);
|
||||
|
|
@ -2348,10 +2386,12 @@ supplicant_iface_connection_error_cb (NMSupplicantInterface * iface,
|
|||
const char * message,
|
||||
NMDeviceWifi * self)
|
||||
{
|
||||
struct iface_con_error_cb_data * cb_data;
|
||||
guint id;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
struct iface_con_error_cb_data *cb_data;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
cb_data = g_slice_new0 (struct iface_con_error_cb_data);
|
||||
if (cb_data == NULL) {
|
||||
|
|
@ -2363,7 +2403,11 @@ supplicant_iface_connection_error_cb (NMSupplicantInterface * iface,
|
|||
cb_data->name = g_strdup (name);
|
||||
cb_data->message = g_strdup (message);
|
||||
|
||||
if (priv->supplicant.iface_con_error_cb_id)
|
||||
g_source_remove (priv->supplicant.iface_con_error_cb_id);
|
||||
|
||||
id = g_idle_add (supplicant_iface_connection_error_cb_handler, cb_data);
|
||||
priv->supplicant.iface_con_error_cb_id = id;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3095,6 +3139,12 @@ nm_device_wifi_dispose (GObject *object)
|
|||
priv->periodic_source_id = 0;
|
||||
}
|
||||
|
||||
/* Clean up all pending supplicant tasks */
|
||||
while (priv->supplicant.iface_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
|
||||
while (priv->supplicant.mgr_tasks)
|
||||
finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE);
|
||||
|
||||
cleanup_association_attempt (self, TRUE);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue