mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 13:40:20 +01:00
Merge remote branch 'origin/sup-rework'
This commit is contained in:
commit
b368b8fea3
6 changed files with 894 additions and 1501 deletions
|
|
@ -78,30 +78,17 @@ 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;
|
||||
|
||||
/* Timeouts and idles */
|
||||
guint iface_con_error_cb_id;
|
||||
guint con_timeout_id;
|
||||
|
||||
GSList *iface_tasks;
|
||||
GSList *mgr_tasks;
|
||||
} Supplicant;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -996,30 +983,6 @@ remove_supplicant_timeouts (NMDeviceEthernet *self)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
|
|
@ -1044,28 +1007,14 @@ supplicant_interface_release (NMDeviceEthernet *self)
|
|||
remove_supplicant_timeouts (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);
|
||||
priv->supplicant.iface_con_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
|
||||
priv->supplicant.iface_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.mgr_state_id) {
|
||||
g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id);
|
||||
priv->supplicant.mgr_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface) {
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
nm_supplicant_manager_release_iface (priv->supplicant.mgr, priv->supplicant.iface);
|
||||
nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface);
|
||||
priv->supplicant.iface = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1127,77 +1076,6 @@ time_out:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
schedule_state_handler (NMDeviceEthernet *self,
|
||||
GSourceFunc handler,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gboolean mgr_task)
|
||||
{
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
SupplicantStateTask *task;
|
||||
|
||||
if (new_state == old_state)
|
||||
return TRUE;
|
||||
|
||||
task = g_slice_new0 (SupplicantStateTask);
|
||||
if (!task) {
|
||||
nm_log_err (LOGD_DEVICE, "Not enough memory to process supplicant manager state change.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDevice *device = NM_DEVICE (task->self);
|
||||
|
||||
/* If the supplicant went away, release the supplicant interface */
|
||||
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,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
nm_log_info (LOGD_DEVICE | LOGD_ETHER,
|
||||
"(%s): supplicant manager state: %s -> %s",
|
||||
nm_device_get_iface (NM_DEVICE (user_data)),
|
||||
nm_supplicant_manager_state_to_string (old_state),
|
||||
nm_supplicant_manager_state_to_string (new_state));
|
||||
|
||||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_mgr_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static NMSupplicantConfig *
|
||||
build_supplicant_config (NMDeviceEthernet *self)
|
||||
{
|
||||
|
|
@ -1224,20 +1102,33 @@ build_supplicant_config (NMDeviceEthernet *self)
|
|||
return config;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_state_cb_handler (gpointer user_data)
|
||||
static void
|
||||
supplicant_iface_state_cb (NMSupplicantInterface *iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self);
|
||||
NMDevice *device = NM_DEVICE (task->self);
|
||||
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
|
||||
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||
NMDevice *device = NM_DEVICE (self);
|
||||
NMSupplicantConfig *config;
|
||||
gboolean success = FALSE;
|
||||
NMDeviceState devstate;
|
||||
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
NMSupplicantConfig *config;
|
||||
const char *iface;
|
||||
gboolean success = FALSE;
|
||||
if (new_state == old_state)
|
||||
return;
|
||||
|
||||
iface = nm_device_get_iface (device);
|
||||
config = build_supplicant_config (task->self);
|
||||
nm_log_info (LOGD_DEVICE | LOGD_ETHER,
|
||||
"(%s): supplicant interface state: %s -> %s",
|
||||
nm_device_get_iface (device),
|
||||
nm_supplicant_interface_state_to_string (old_state),
|
||||
nm_supplicant_interface_state_to_string (new_state));
|
||||
|
||||
devstate = nm_device_get_state (device);
|
||||
|
||||
switch (new_state) {
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_READY:
|
||||
config = build_supplicant_config (self);
|
||||
if (config) {
|
||||
success = nm_supplicant_interface_set_config (priv->supplicant.iface, config);
|
||||
g_object_unref (config);
|
||||
|
|
@ -1246,99 +1137,54 @@ supplicant_iface_state_cb_handler (gpointer user_data)
|
|||
nm_log_err (LOGD_DEVICE | LOGD_ETHER,
|
||||
"Activation (%s/wired): couldn't send security "
|
||||
"configuration to the supplicant.",
|
||||
iface);
|
||||
nm_device_get_iface (device));
|
||||
}
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE | LOGD_ETHER,
|
||||
"Activation (%s/wired): couldn't build security configuration.",
|
||||
iface);
|
||||
nm_device_get_iface (device));
|
||||
}
|
||||
|
||||
if (!success)
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
|
||||
} else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
||||
NMDeviceState state = nm_device_get_state (device);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_iface_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
nm_log_info (LOGD_DEVICE | LOGD_ETHER,
|
||||
"(%s): supplicant interface state: %s -> %s",
|
||||
nm_device_get_iface (NM_DEVICE (user_data)),
|
||||
nm_supplicant_interface_state_to_string (old_state),
|
||||
nm_supplicant_interface_state_to_string (new_state));
|
||||
|
||||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_iface_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDevice *dev = NM_DEVICE (task->self);
|
||||
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
remove_supplicant_interface_error_handler (task->self);
|
||||
remove_supplicant_timeouts (task->self);
|
||||
if (!success) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
|
||||
}
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
|
||||
/* If this is the initial association during device activation,
|
||||
* schedule the next activation stage.
|
||||
*/
|
||||
if (nm_device_get_state (dev) == NM_DEVICE_STATE_CONFIG) {
|
||||
if (devstate == NM_DEVICE_STATE_CONFIG) {
|
||||
nm_log_info (LOGD_DEVICE | LOGD_ETHER,
|
||||
"Activation (%s/wired) Stage 2 of 5 (Device Configure) successful.",
|
||||
nm_device_get_iface (dev));
|
||||
nm_device_activate_schedule_stage3_ip_config_start (dev);
|
||||
nm_device_get_iface (device));
|
||||
nm_device_activate_schedule_stage3_ip_config_start (device);
|
||||
}
|
||||
} 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 (task->self);
|
||||
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
|
||||
if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
|
||||
/* Start the link timeout so we allow some time for reauthentication */
|
||||
if (!priv->supplicant_timeout_id)
|
||||
priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, dev);
|
||||
priv->supplicant_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, device);
|
||||
}
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
|
||||
supplicant_interface_release (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
|
||||
if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_FAILED,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
nm_log_info (LOGD_DEVICE | LOGD_ETHER,
|
||||
"(%s) supplicant connection state: %s -> %s",
|
||||
nm_device_get_iface (NM_DEVICE (user_data)),
|
||||
nm_supplicant_interface_connection_state_to_string (old_state),
|
||||
nm_supplicant_interface_connection_state_to_string (new_state));
|
||||
|
||||
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
|
||||
supplicant_iface_connection_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1456,38 +1302,26 @@ supplicant_interface_init (NMDeviceEthernet *self)
|
|||
iface = nm_device_get_iface (NM_DEVICE (self));
|
||||
|
||||
/* Create supplicant interface */
|
||||
priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr, iface, FALSE);
|
||||
priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr, iface, FALSE);
|
||||
if (!priv->supplicant.iface) {
|
||||
nm_log_err (LOGD_DEVICE | LOGD_ETHER,
|
||||
"Couldn't initialize supplicant interface for %s.",
|
||||
iface);
|
||||
supplicant_interface_release (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Listen for it's state signals */
|
||||
priv->supplicant.iface_state_id = g_signal_connect (priv->supplicant.iface,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_iface_state_cb),
|
||||
self);
|
||||
"state",
|
||||
G_CALLBACK (supplicant_iface_state_cb),
|
||||
self);
|
||||
|
||||
/* Hook up error signal handler to capture association errors */
|
||||
priv->supplicant.iface_error_id = g_signal_connect (priv->supplicant.iface,
|
||||
"connection-error",
|
||||
G_CALLBACK (supplicant_iface_connection_error_cb),
|
||||
self);
|
||||
|
||||
priv->supplicant.iface_con_state_id = g_signal_connect (priv->supplicant.iface,
|
||||
"connection-state",
|
||||
G_CALLBACK (supplicant_iface_connection_state_cb),
|
||||
self);
|
||||
|
||||
/* Listen for supplicant manager state changes */
|
||||
priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_mgr_state_cb),
|
||||
self);
|
||||
"connection-error",
|
||||
G_CALLBACK (supplicant_iface_connection_error_cb),
|
||||
self);
|
||||
|
||||
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
|
||||
priv->supplicant.con_timeout_id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
|
||||
|
|
@ -2047,12 +1881,6 @@ dispose (GObject *object)
|
|||
|
||||
priv->disposed = 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);
|
||||
|
||||
if (priv->link_connected_id) {
|
||||
g_signal_handler_disconnect (priv->monitor, priv->link_connected_id);
|
||||
priv->link_connected_id = 0;
|
||||
|
|
|
|||
|
|
@ -113,34 +113,18 @@ 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;
|
||||
#define SUP_SIG_ID_LEN 5
|
||||
|
||||
typedef struct Supplicant {
|
||||
NMSupplicantManager *mgr;
|
||||
NMSupplicantInterface *iface;
|
||||
|
||||
/* signal handler ids */
|
||||
guint mgr_state_id;
|
||||
guint sig_ids[SUP_SIG_ID_LEN];
|
||||
guint iface_error_id;
|
||||
guint iface_state_id;
|
||||
guint iface_scanned_ap_id;
|
||||
guint iface_scan_request_result_id;
|
||||
guint iface_scan_results_id;
|
||||
guint iface_con_state_id;
|
||||
guint iface_notify_scanning_id;
|
||||
|
||||
/* Timeouts and idles */
|
||||
guint iface_con_error_cb_id;
|
||||
guint con_timeout_id;
|
||||
|
||||
GSList *mgr_tasks;
|
||||
GSList *iface_tasks;
|
||||
} Supplicant;
|
||||
|
||||
struct _NMDeviceWifiPrivate {
|
||||
|
|
@ -199,15 +183,10 @@ static void cleanup_association_attempt (NMDeviceWifi * self,
|
|||
|
||||
static void remove_supplicant_timeouts (NMDeviceWifi *self);
|
||||
|
||||
static void supplicant_iface_state_cb (NMSupplicantInterface * iface,
|
||||
static void supplicant_iface_state_cb (NMSupplicantInterface *iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self);
|
||||
|
||||
static void supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self);
|
||||
gpointer user_data);
|
||||
|
||||
static void supplicant_iface_scanned_ap_cb (NMSupplicantInterface * iface,
|
||||
GHashTable *properties,
|
||||
|
|
@ -221,11 +200,6 @@ static void supplicant_iface_scan_results_cb (NMSupplicantInterface * iface,
|
|||
guint32 num_bssids,
|
||||
NMDeviceWifi * self);
|
||||
|
||||
static void supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self);
|
||||
|
||||
static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface,
|
||||
GParamSpec * pspec,
|
||||
NMDeviceWifi * self);
|
||||
|
|
@ -625,10 +599,7 @@ constructor (GType type,
|
|||
|
||||
/* Connect to the supplicant manager */
|
||||
priv->supplicant.mgr = nm_supplicant_manager_get ();
|
||||
priv->supplicant.mgr_state_id = g_signal_connect (priv->supplicant.mgr,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_mgr_state_cb),
|
||||
self);
|
||||
g_assert (priv->supplicant.mgr);
|
||||
|
||||
/* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until
|
||||
* 2.6.33. Thus all our nice libgudev magic is useless. So we get to poll.
|
||||
|
|
@ -657,17 +628,13 @@ static gboolean
|
|||
supplicant_interface_acquire (NMDeviceWifi *self)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
guint id, mgr_state;
|
||||
guint id, i = 0;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (priv->supplicant.mgr != NULL, FALSE);
|
||||
/* interface already acquired? */
|
||||
g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE);
|
||||
|
||||
mgr_state = nm_supplicant_manager_get_state (priv->supplicant.mgr);
|
||||
g_return_val_if_fail (mgr_state == NM_SUPPLICANT_MANAGER_STATE_IDLE, FALSE);
|
||||
|
||||
priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr,
|
||||
priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr,
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
TRUE);
|
||||
if (priv->supplicant.iface == NULL) {
|
||||
|
|
@ -676,69 +643,41 @@ supplicant_interface_acquire (NMDeviceWifi *self)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids));
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"state",
|
||||
G_CALLBACK (supplicant_iface_state_cb),
|
||||
self);
|
||||
priv->supplicant.iface_state_id = id;
|
||||
priv->supplicant.sig_ids[i++] = id;
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"scanned-ap",
|
||||
G_CALLBACK (supplicant_iface_scanned_ap_cb),
|
||||
self);
|
||||
priv->supplicant.iface_scanned_ap_id = id;
|
||||
priv->supplicant.sig_ids[i++] = id;
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"scan-req-result",
|
||||
G_CALLBACK (supplicant_iface_scan_request_result_cb),
|
||||
self);
|
||||
priv->supplicant.iface_scan_request_result_id = id;
|
||||
priv->supplicant.sig_ids[i++] = id;
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"scan-results",
|
||||
G_CALLBACK (supplicant_iface_scan_results_cb),
|
||||
self);
|
||||
priv->supplicant.iface_scan_results_id = id;
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"connection-state",
|
||||
G_CALLBACK (supplicant_iface_connection_state_cb),
|
||||
self);
|
||||
priv->supplicant.iface_con_state_id = id;
|
||||
priv->supplicant.sig_ids[i++] = id;
|
||||
|
||||
id = g_signal_connect (priv->supplicant.iface,
|
||||
"notify::scanning",
|
||||
G_CALLBACK (supplicant_iface_notify_scanning_cb),
|
||||
self);
|
||||
priv->supplicant.iface_notify_scanning_id = id;
|
||||
priv->supplicant.sig_ids[i++] = id;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -762,6 +701,7 @@ static void
|
|||
supplicant_interface_release (NMDeviceWifi *self)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
|
|
@ -776,45 +716,18 @@ supplicant_interface_release (NMDeviceWifi *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_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
|
||||
priv->supplicant.iface_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_scanned_ap_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scanned_ap_id);
|
||||
priv->supplicant.iface_scanned_ap_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_scan_request_result_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_request_result_id);
|
||||
priv->supplicant.iface_scan_request_result_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_scan_results_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_scan_results_id);
|
||||
priv->supplicant.iface_scan_results_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_con_state_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id);
|
||||
priv->supplicant.iface_con_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.iface_notify_scanning_id > 0) {
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_notify_scanning_id);
|
||||
priv->supplicant.iface_notify_scanning_id = 0;
|
||||
/* Clear supplicant interface signal handlers */
|
||||
for (i = 0; i < SUP_SIG_ID_LEN; i++) {
|
||||
if (priv->supplicant.sig_ids[i] > 0)
|
||||
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.sig_ids[i]);
|
||||
}
|
||||
memset (priv->supplicant.sig_ids, 0, sizeof (priv->supplicant.sig_ids));
|
||||
|
||||
if (priv->supplicant.iface) {
|
||||
/* Tell the supplicant to disconnect from the current AP */
|
||||
nm_supplicant_interface_disconnect (priv->supplicant.iface);
|
||||
|
||||
nm_supplicant_manager_release_iface (priv->supplicant.mgr, priv->supplicant.iface);
|
||||
nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface);
|
||||
priv->supplicant.iface = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1837,11 +1750,11 @@ scanning_allowed (NMDeviceWifi *self)
|
|||
}
|
||||
|
||||
/* Don't scan if the supplicant is busy */
|
||||
sup_state = nm_supplicant_interface_get_connection_state (priv->supplicant.iface);
|
||||
if ( sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE
|
||||
sup_state = nm_supplicant_interface_get_state (priv->supplicant.iface);
|
||||
if ( sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
|
||||
|| sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
|
||||
|| nm_supplicant_interface_get_scanning (priv->supplicant.iface))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -2441,253 +2354,97 @@ time_out:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
schedule_state_handler (NMDeviceWifi *self,
|
||||
GSourceFunc handler,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gboolean mgr_task)
|
||||
static void
|
||||
supplicant_iface_state_cb (NMSupplicantInterface *iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv;
|
||||
SupplicantStateTask *task;
|
||||
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (handler != NULL, FALSE);
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMDevice *device = NM_DEVICE (self);
|
||||
NMDeviceState devstate;
|
||||
gboolean scanning;
|
||||
|
||||
if (new_state == old_state)
|
||||
return TRUE;
|
||||
return;
|
||||
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
nm_log_info (LOGD_DEVICE | LOGD_WIFI,
|
||||
"(%s): supplicant interface state: %s -> %s",
|
||||
nm_device_get_iface (device),
|
||||
nm_supplicant_interface_state_to_string (old_state),
|
||||
nm_supplicant_interface_state_to_string (new_state));
|
||||
|
||||
task = g_slice_new0 (SupplicantStateTask);
|
||||
if (!task) {
|
||||
nm_log_err (LOGD_WIFI, "Not enough memory to process supplicant manager state change.");
|
||||
return FALSE;
|
||||
}
|
||||
devstate = nm_device_get_state (device);
|
||||
scanning = nm_supplicant_interface_get_scanning (iface);
|
||||
|
||||
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_iface_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (task != NULL, FALSE);
|
||||
|
||||
self = task->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
|
||||
nm_log_info (LOGD_WIFI, "(%s): supplicant interface state: %s -> %s",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
nm_supplicant_interface_state_to_string (task->old_state),
|
||||
nm_supplicant_interface_state_to_string (task->new_state));
|
||||
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
||||
switch (new_state) {
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_READY:
|
||||
priv->scan_interval = SCAN_INTERVAL_MIN;
|
||||
|
||||
/* If the interface can now be activated because the supplicant is now
|
||||
* available, transition to DISCONNECTED.
|
||||
*/
|
||||
if ( (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_UNAVAILABLE)
|
||||
&& nm_device_is_available (NM_DEVICE (self))) {
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED,
|
||||
if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE);
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_WIFI_SCAN, "(%s): supplicant ready, requesting initial scan",
|
||||
nm_device_get_iface (NM_DEVICE (self)));
|
||||
nm_log_dbg (LOGD_WIFI_SCAN,
|
||||
"(%s): supplicant ready, requesting initial scan",
|
||||
nm_device_get_iface (device));
|
||||
|
||||
/* Request a scan to get latest results */
|
||||
cancel_pending_scan (self);
|
||||
request_wireless_scan (self);
|
||||
} 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);
|
||||
}
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
supplicant_iface_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
schedule_state_handler (self,
|
||||
supplicant_iface_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_iface_connection_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self = task->self;
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
NMDevice *dev = NM_DEVICE (self);
|
||||
gboolean scanning;
|
||||
|
||||
if (!nm_device_get_act_request (dev)) {
|
||||
/* The device is not activating or already activated; do nothing. */
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_log_info (LOGD_WIFI, "(%s): supplicant connection state: %s -> %s",
|
||||
nm_device_get_iface (dev),
|
||||
nm_supplicant_interface_connection_state_to_string (task->old_state),
|
||||
nm_supplicant_interface_connection_state_to_string (task->new_state));
|
||||
|
||||
scanning = nm_supplicant_interface_get_scanning (priv->supplicant.iface);
|
||||
|
||||
if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
|
||||
remove_supplicant_interface_error_handler (self);
|
||||
remove_supplicant_timeouts (self);
|
||||
|
||||
/* If this is the initial association during device activation,
|
||||
* schedule the next activation stage.
|
||||
*/
|
||||
if (nm_device_get_state (dev) == NM_DEVICE_STATE_CONFIG) {
|
||||
if (devstate == NM_DEVICE_STATE_CONFIG) {
|
||||
NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
|
||||
const GByteArray * ssid = nm_ap_get_ssid (ap);
|
||||
const GByteArray *ssid = nm_ap_get_ssid (ap);
|
||||
|
||||
nm_log_info (LOGD_DEVICE | LOGD_WIFI,
|
||||
"Activation (%s/wireless) Stage 2 of 5 (Device Configure) "
|
||||
"successful. Connected to wireless network '%s'.",
|
||||
nm_device_get_iface (dev),
|
||||
nm_device_get_iface (device),
|
||||
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
|
||||
nm_device_activate_schedule_stage3_ip_config_start (dev);
|
||||
nm_device_activate_schedule_stage3_ip_config_start (device);
|
||||
}
|
||||
} 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)) {
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
|
||||
if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
|
||||
/* Start the link timeout so we allow some time for reauthentication,
|
||||
* use a longer timeout if we are scanning since some cards take a
|
||||
* while to scan.
|
||||
*/
|
||||
if (!priv->link_timeout_id) {
|
||||
priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15,
|
||||
link_timeout_cb, self);
|
||||
link_timeout_cb, self);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
supplicant_interface_release (self);
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Signal scanning state changes */
|
||||
if ( task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING
|
||||
|| task->old_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING)
|
||||
if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
|
||||
|| old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
|
||||
g_object_notify (G_OBJECT (self), "scanning");
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
supplicant_iface_connection_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
schedule_state_handler (self,
|
||||
supplicant_iface_connection_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
supplicant_mgr_state_cb_handler (gpointer user_data)
|
||||
{
|
||||
SupplicantStateTask *task = (SupplicantStateTask *) user_data;
|
||||
NMDeviceWifi *self;
|
||||
NMDeviceWifiPrivate *priv;
|
||||
NMDevice *dev;
|
||||
NMDeviceState dev_state;
|
||||
|
||||
g_return_val_if_fail (task != NULL, FALSE);
|
||||
|
||||
self = task->self;
|
||||
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
dev = NM_DEVICE (self);
|
||||
|
||||
nm_log_info (LOGD_WIFI, "(%s): supplicant manager state: %s -> %s",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
nm_supplicant_manager_state_to_string (task->old_state),
|
||||
nm_supplicant_manager_state_to_string (task->new_state));
|
||||
|
||||
/* If the supplicant went away, release the supplicant interface */
|
||||
if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
|
||||
if (priv->supplicant.iface) {
|
||||
cleanup_association_attempt (self, FALSE);
|
||||
supplicant_interface_release (self);
|
||||
}
|
||||
|
||||
if (nm_device_get_state (dev) > NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
|
||||
}
|
||||
} else if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
|
||||
dev_state = nm_device_get_state (dev);
|
||||
if ( priv->enabled
|
||||
&& !priv->supplicant.iface
|
||||
&& (dev_state >= NM_DEVICE_STATE_UNAVAILABLE)
|
||||
&& (nm_device_get_firmware_missing (NM_DEVICE (self)) == FALSE)) {
|
||||
/* request a supplicant interface from the supplicant manager */
|
||||
supplicant_interface_acquire (self);
|
||||
|
||||
/* if wireless is enabled and we have a supplicant interface,
|
||||
* we can transition to the DISCONNECTED state.
|
||||
*/
|
||||
if (priv->supplicant.iface) {
|
||||
nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finish_supplicant_task (task, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
supplicant_mgr_state_cb (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state,
|
||||
NMDeviceWifi *self)
|
||||
{
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
schedule_state_handler (self,
|
||||
supplicant_mgr_state_cb_handler,
|
||||
new_state,
|
||||
old_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
struct iface_con_error_cb_data {
|
||||
|
|
@ -3845,20 +3602,9 @@ 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);
|
||||
|
||||
if (priv->supplicant.mgr_state_id) {
|
||||
g_signal_handler_disconnect (priv->supplicant.mgr, priv->supplicant.mgr_state_id);
|
||||
priv->supplicant.mgr_state_id = 0;
|
||||
}
|
||||
|
||||
if (priv->supplicant.mgr) {
|
||||
g_object_unref (priv->supplicant.mgr);
|
||||
priv->supplicant.mgr = NULL;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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) 2006 - 2008 Red Hat, Inc.
|
||||
* Copyright (C) 2006 - 2010 Red Hat, Inc.
|
||||
* Copyright (C) 2007 - 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
|
|
@ -26,47 +26,26 @@
|
|||
#include <dbus/dbus.h>
|
||||
#include "nm-supplicant-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Supplicant interface states
|
||||
* The states are linear, ie INIT -> READY -> DOWN and state may only be
|
||||
* changed in one direction. If an interface reaches the DOWN state, it
|
||||
* cannot be re-initialized; it must be torn down and a new one created.
|
||||
*
|
||||
* INIT: interface has been created, but cannot be used yet; it is waiting
|
||||
* for pending requests of the supplicant to complete.
|
||||
* READY: interface is ready for use
|
||||
* DOWN: interface has been removed or has otherwise been made invalid; it
|
||||
* must be torn down.
|
||||
*
|
||||
* Note: LAST is an invalid state and only used for boundary checking.
|
||||
* A mix of wpa_supplicant interface states and internal states.
|
||||
*/
|
||||
enum {
|
||||
NM_SUPPLICANT_INTERFACE_STATE_INIT = 0,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_STARTING,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_READY,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_INACTIVE,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_SCANNING,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_COMPLETED,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_DOWN,
|
||||
NM_SUPPLICANT_INTERFACE_STATE_LAST
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Supplicant interface connection states
|
||||
* The wpa_supplicant state for the connection.
|
||||
*/
|
||||
enum {
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED = 0,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_INACTIVE,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATING,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_ASSOCIATED,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_4WAY_HANDSHAKE,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_GROUP_HANDSHAKE,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED,
|
||||
NM_SUPPLICANT_INTERFACE_CON_STATE_LAST
|
||||
};
|
||||
|
||||
#define NM_TYPE_SUPPLICANT_INTERFACE (nm_supplicant_interface_get_type ())
|
||||
#define NM_SUPPLICANT_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterface))
|
||||
#define NM_SUPPLICANT_INTERFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_INTERFACE, NMSupplicantInterfaceClass))
|
||||
|
|
@ -103,11 +82,6 @@ typedef struct {
|
|||
void (*scan_results) (NMSupplicantInterface * iface,
|
||||
guint num_bssids);
|
||||
|
||||
/* link state of the device's connection */
|
||||
void (*connection_state) (NMSupplicantInterface * iface,
|
||||
guint32 new_state,
|
||||
guint32 old_state);
|
||||
|
||||
/* an error occurred during a connection request */
|
||||
void (*connection_error) (NMSupplicantInterface * iface,
|
||||
const char * name,
|
||||
|
|
@ -119,7 +93,8 @@ GType nm_supplicant_interface_get_type (void);
|
|||
|
||||
NMSupplicantInterface * nm_supplicant_interface_new (NMSupplicantManager * smgr,
|
||||
const char *ifname,
|
||||
gboolean is_wireless);
|
||||
gboolean is_wireless,
|
||||
gboolean start_now);
|
||||
|
||||
gboolean nm_supplicant_interface_set_config (NMSupplicantInterface * iface,
|
||||
NMSupplicantConfig * cfg);
|
||||
|
|
@ -128,18 +103,16 @@ void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
|
|||
|
||||
const char * nm_supplicant_interface_get_device (NMSupplicantInterface * iface);
|
||||
|
||||
const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface);
|
||||
|
||||
gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self);
|
||||
|
||||
guint32 nm_supplicant_interface_get_state (NMSupplicantInterface * self);
|
||||
|
||||
guint32 nm_supplicant_interface_get_connection_state (NMSupplicantInterface * self);
|
||||
|
||||
const char *nm_supplicant_interface_state_to_string (guint32 state);
|
||||
|
||||
const char *nm_supplicant_interface_connection_state_to_string (guint32 state);
|
||||
|
||||
gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self);
|
||||
|
||||
G_END_DECLS
|
||||
const char *nm_supplicant_interface_get_ifname (NMSupplicantInterface *self);
|
||||
|
||||
#endif /* NM_SUPPLICANT_INTERFACE_H */
|
||||
|
|
|
|||
|
|
@ -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) 2006 - 2008 Red Hat, Inc.
|
||||
* Copyright (C) 2006 - 2010 Red Hat, Inc.
|
||||
* Copyright (C) 2007 - 2008 Novell, Inc.
|
||||
*/
|
||||
|
||||
|
|
@ -26,19 +26,7 @@
|
|||
#include "nm-supplicant-manager.h"
|
||||
#include "nm-supplicant-interface.h"
|
||||
#include "nm-dbus-manager.h"
|
||||
#include "nm-marshal.h"
|
||||
#include "nm-logging.h"
|
||||
#include "nm-glib-compat.h"
|
||||
|
||||
#define SUPPLICANT_POKE_INTERVAL 120
|
||||
|
||||
typedef struct {
|
||||
NMDBusManager * dbus_mgr;
|
||||
guint32 state;
|
||||
GSList * ifaces;
|
||||
gboolean dispose_has_run;
|
||||
guint poke_id;
|
||||
} NMSupplicantManagerPrivate;
|
||||
|
||||
#define NM_SUPPLICANT_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
||||
NM_TYPE_SUPPLICANT_MANAGER, \
|
||||
|
|
@ -46,252 +34,59 @@ typedef struct {
|
|||
|
||||
G_DEFINE_TYPE (NMSupplicantManager, nm_supplicant_manager, G_TYPE_OBJECT)
|
||||
|
||||
|
||||
static void nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr,
|
||||
const char *name,
|
||||
const char *old,
|
||||
const char *new,
|
||||
gpointer user_data);
|
||||
|
||||
static void nm_supplicant_manager_set_state (NMSupplicantManager * self,
|
||||
guint32 new_state);
|
||||
|
||||
static gboolean nm_supplicant_manager_startup (NMSupplicantManager * self);
|
||||
|
||||
|
||||
/* Signals */
|
||||
/* Properties */
|
||||
enum {
|
||||
STATE, /* change in the manager's state */
|
||||
LAST_SIGNAL
|
||||
PROP_0 = 0,
|
||||
PROP_AVAILABLE,
|
||||
LAST_PROP
|
||||
};
|
||||
static guint nm_supplicant_manager_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
typedef struct {
|
||||
NMDBusManager * dbus_mgr;
|
||||
guint name_owner_id;
|
||||
DBusGProxy * proxy;
|
||||
gboolean running;
|
||||
GHashTable * ifaces;
|
||||
guint die_count_reset_id;
|
||||
guint die_count;
|
||||
gboolean disposed;
|
||||
} NMSupplicantManagerPrivate;
|
||||
|
||||
NMSupplicantManager *
|
||||
nm_supplicant_manager_get (void)
|
||||
/********************************************************************/
|
||||
|
||||
static inline gboolean
|
||||
die_count_exceeded (guint32 count)
|
||||
{
|
||||
static NMSupplicantManager * singleton = NULL;
|
||||
|
||||
if (!singleton) {
|
||||
singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL));
|
||||
} else {
|
||||
g_object_ref (singleton);
|
||||
}
|
||||
|
||||
g_assert (singleton);
|
||||
return singleton;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
poke_supplicant_cb (gpointer user_data)
|
||||
{
|
||||
NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
DBusGConnection *g_connection;
|
||||
DBusGProxy *proxy;
|
||||
const char *tmp = "ignoreme";
|
||||
|
||||
g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr);
|
||||
proxy = dbus_g_proxy_new_for_name (g_connection,
|
||||
WPAS_DBUS_SERVICE,
|
||||
WPAS_DBUS_PATH,
|
||||
WPAS_DBUS_INTERFACE);
|
||||
if (!proxy) {
|
||||
nm_log_warn (LOGD_SUPPLICANT, "Error: could not init wpa_supplicant proxy");
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_log_info (LOGD_SUPPLICANT, "Trying to start the supplicant...");
|
||||
dbus_g_proxy_call_no_reply (proxy, "getInterface", G_TYPE_STRING, tmp, G_TYPE_INVALID);
|
||||
g_object_unref (proxy);
|
||||
|
||||
out:
|
||||
/* Reschedule the poke */
|
||||
priv->poke_id = g_timeout_add_seconds (SUPPLICANT_POKE_INTERVAL,
|
||||
poke_supplicant_cb,
|
||||
(gpointer) self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_init (NMSupplicantManager * self)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
gboolean running;
|
||||
|
||||
priv->dispose_has_run = FALSE;
|
||||
priv->state = NM_SUPPLICANT_MANAGER_STATE_DOWN;
|
||||
priv->dbus_mgr = nm_dbus_manager_get ();
|
||||
priv->poke_id = 0;
|
||||
|
||||
running = nm_supplicant_manager_startup (self);
|
||||
|
||||
g_signal_connect (priv->dbus_mgr,
|
||||
"name-owner-changed",
|
||||
G_CALLBACK (nm_supplicant_manager_name_owner_changed),
|
||||
self);
|
||||
|
||||
if (!running) {
|
||||
/* Try to activate the supplicant */
|
||||
priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_dispose (GObject *object)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object);
|
||||
|
||||
if (priv->dispose_has_run) {
|
||||
G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
|
||||
return;
|
||||
}
|
||||
|
||||
priv->dispose_has_run = TRUE;
|
||||
|
||||
if (priv->poke_id) {
|
||||
g_source_remove (priv->poke_id);
|
||||
priv->poke_id = 0;
|
||||
}
|
||||
|
||||
if (priv->dbus_mgr) {
|
||||
g_object_unref (G_OBJECT (priv->dbus_mgr));
|
||||
priv->dbus_mgr = NULL;
|
||||
}
|
||||
|
||||
/* Chain up to the parent class */
|
||||
G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass)
|
||||
{
|
||||
GObjectClass * object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate));
|
||||
|
||||
object_class->dispose = nm_supplicant_manager_dispose;
|
||||
|
||||
/* Signals */
|
||||
nm_supplicant_manager_signals[STATE] =
|
||||
g_signal_new ("state",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (NMSupplicantManagerClass, state),
|
||||
NULL, NULL,
|
||||
_nm_marshal_VOID__UINT_UINT,
|
||||
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_name_owner_changed (NMDBusManager *dbus_mgr,
|
||||
const char *name,
|
||||
const char *old_owner,
|
||||
const char *new_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSupplicantManager * self = (NMSupplicantManager *) user_data;
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
gboolean old_owner_good = (old_owner && strlen (old_owner));
|
||||
gboolean new_owner_good = (new_owner && strlen (new_owner));
|
||||
|
||||
/* Can't handle the signal if its not from the supplicant service */
|
||||
if (strcmp (WPAS_DBUS_SERVICE, name) != 0)
|
||||
return;
|
||||
|
||||
if (!old_owner_good && new_owner_good) {
|
||||
gboolean running;
|
||||
|
||||
running = nm_supplicant_manager_startup (self);
|
||||
|
||||
if (running && priv->poke_id) {
|
||||
g_source_remove (priv->poke_id);
|
||||
priv->poke_id = 0;
|
||||
}
|
||||
} else if (old_owner_good && !new_owner_good) {
|
||||
nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_DOWN);
|
||||
|
||||
if (priv->poke_id)
|
||||
g_source_remove (priv->poke_id);
|
||||
|
||||
/* Poke the supplicant so that it gets activated by dbus system bus
|
||||
* activation.
|
||||
*/
|
||||
priv->poke_id = g_idle_add (poke_supplicant_cb, (gpointer) self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
guint32
|
||||
nm_supplicant_manager_get_state (NMSupplicantManager * self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE);
|
||||
|
||||
return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->state;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_set_state (NMSupplicantManager * self, guint32 new_state)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
guint32 old_state;
|
||||
|
||||
if (new_state == priv->state)
|
||||
return;
|
||||
|
||||
old_state = priv->state;
|
||||
priv->state = new_state;
|
||||
g_signal_emit (self,
|
||||
nm_supplicant_manager_signals[STATE],
|
||||
0,
|
||||
priv->state,
|
||||
old_state);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_supplicant_manager_startup (NMSupplicantManager * self)
|
||||
{
|
||||
gboolean running;
|
||||
|
||||
/* FIXME: convert to pending call */
|
||||
running = nm_dbus_manager_name_has_owner (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->dbus_mgr,
|
||||
WPAS_DBUS_SERVICE);
|
||||
if (running)
|
||||
nm_supplicant_manager_set_state (self, NM_SUPPLICANT_MANAGER_STATE_IDLE);
|
||||
|
||||
return running;
|
||||
return count > 2;
|
||||
}
|
||||
|
||||
NMSupplicantInterface *
|
||||
nm_supplicant_manager_get_iface (NMSupplicantManager * self,
|
||||
const char *ifname,
|
||||
gboolean is_wireless)
|
||||
nm_supplicant_manager_iface_get (NMSupplicantManager * self,
|
||||
const char *ifname,
|
||||
gboolean is_wireless)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv;
|
||||
NMSupplicantInterface * iface = NULL;
|
||||
GSList * elt;
|
||||
NMSupplicantInterface *iface = NULL;
|
||||
gboolean start_now;
|
||||
|
||||
g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), NULL);
|
||||
g_return_val_if_fail (ifname != NULL, NULL);
|
||||
|
||||
priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
/* Ensure we don't already have this interface */
|
||||
for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) {
|
||||
NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data;
|
||||
|
||||
if (!strcmp (ifname, nm_supplicant_interface_get_device (if_tmp))) {
|
||||
iface = if_tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iface = g_hash_table_lookup (priv->ifaces, ifname);
|
||||
if (!iface) {
|
||||
/* If we're making the supplicant take a time out for a bit, don't
|
||||
* let the supplicant interface start immediately, just let it hang
|
||||
* around in INIT state until we're ready to talk to the supplicant
|
||||
* again.
|
||||
*/
|
||||
start_now = !die_count_exceeded (priv->die_count);
|
||||
|
||||
nm_log_dbg (LOGD_SUPPLICANT, "(%s): creating new supplicant interface", ifname);
|
||||
iface = nm_supplicant_interface_new (self, ifname, is_wireless);
|
||||
iface = nm_supplicant_interface_new (self, ifname, is_wireless, start_now);
|
||||
if (iface)
|
||||
priv->ifaces = g_slist_append (priv->ifaces, iface);
|
||||
g_hash_table_insert (priv->ifaces, g_strdup (ifname), iface);
|
||||
} else {
|
||||
nm_log_dbg (LOGD_SUPPLICANT, "(%s): returning existing supplicant interface", ifname);
|
||||
}
|
||||
|
|
@ -300,44 +95,222 @@ nm_supplicant_manager_get_iface (NMSupplicantManager * self,
|
|||
}
|
||||
|
||||
void
|
||||
nm_supplicant_manager_release_iface (NMSupplicantManager * self,
|
||||
NMSupplicantInterface * iface)
|
||||
nm_supplicant_manager_iface_release (NMSupplicantManager *self,
|
||||
NMSupplicantInterface *iface)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv;
|
||||
GSList * elt;
|
||||
const char *ifname, *op;
|
||||
|
||||
g_return_if_fail (NM_IS_SUPPLICANT_MANAGER (self));
|
||||
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (iface));
|
||||
|
||||
ifname = nm_supplicant_interface_get_ifname (iface);
|
||||
g_assert (ifname);
|
||||
|
||||
priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
for (elt = priv->ifaces; elt; elt = g_slist_next (elt)) {
|
||||
NMSupplicantInterface * if_tmp = (NMSupplicantInterface *) elt->data;
|
||||
g_return_if_fail (g_hash_table_lookup (priv->ifaces, ifname) == iface);
|
||||
|
||||
if (if_tmp == iface) {
|
||||
/* Remove the iface from the supplicant manager's list and
|
||||
* dereference to match additional reference in get_iface.
|
||||
*/
|
||||
priv->ifaces = g_slist_remove_link (priv->ifaces, elt);
|
||||
g_slist_free_1 (elt);
|
||||
g_object_unref (iface);
|
||||
break;
|
||||
/* Ask wpa_supplicant to remove this interface */
|
||||
op = nm_supplicant_interface_get_object_path (iface);
|
||||
if (priv->running && priv->proxy && op) {
|
||||
dbus_g_proxy_call_no_reply (priv->proxy, "removeInterface",
|
||||
DBUS_TYPE_G_OBJECT_PATH, op,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
g_hash_table_remove (priv->ifaces, ifname);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_supplicant_manager_available (NMSupplicantManager *self)
|
||||
{
|
||||
g_return_val_if_fail (self != NULL, FALSE);
|
||||
g_return_val_if_fail (NM_IS_SUPPLICANT_MANAGER (self), FALSE);
|
||||
|
||||
if (die_count_exceeded (NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->die_count))
|
||||
return FALSE;
|
||||
return NM_SUPPLICANT_MANAGER_GET_PRIVATE (self)->running;
|
||||
}
|
||||
|
||||
static void
|
||||
set_running (NMSupplicantManager *self, gboolean now_running)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
gboolean old_available = nm_supplicant_manager_available (self);
|
||||
|
||||
priv->running = now_running;
|
||||
if (old_available != nm_supplicant_manager_available (self))
|
||||
g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE);
|
||||
}
|
||||
|
||||
static void
|
||||
set_die_count (NMSupplicantManager *self, guint new_die_count)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
gboolean old_available = nm_supplicant_manager_available (self);
|
||||
|
||||
priv->die_count = new_die_count;
|
||||
if (old_available != nm_supplicant_manager_available (self))
|
||||
g_object_notify (G_OBJECT (self), NM_SUPPLICANT_MANAGER_AVAILABLE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wpas_die_count_reset_cb (gpointer user_data)
|
||||
{
|
||||
NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
/* Reset the die count back to zero, which allows use of the supplicant again */
|
||||
priv->die_count_reset_id = 0;
|
||||
set_die_count (self, 0);
|
||||
nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant die count reset");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
name_owner_changed (NMDBusManager *dbus_mgr,
|
||||
const char *name,
|
||||
const char *old_owner,
|
||||
const char *new_owner,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMSupplicantManager *self = NM_SUPPLICANT_MANAGER (user_data);
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
gboolean old_owner_good = (old_owner && strlen (old_owner));
|
||||
gboolean new_owner_good = (new_owner && strlen (new_owner));
|
||||
|
||||
/* We only care about the supplicant here */
|
||||
if (strcmp (WPAS_DBUS_SERVICE, name) != 0)
|
||||
return;
|
||||
|
||||
if (!old_owner_good && new_owner_good) {
|
||||
nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant started");
|
||||
set_running (self, TRUE);
|
||||
} else if (old_owner_good && !new_owner_good) {
|
||||
nm_log_info (LOGD_SUPPLICANT, "wpa_supplicant stopped");
|
||||
|
||||
/* Reschedule the die count reset timeout. Every time the supplicant
|
||||
* dies we wait 10 seconds before resetting the counter. If the
|
||||
* supplicant died more than twice before the timer is reset, then
|
||||
* we don't try to talk to the supplicant for a while.
|
||||
*/
|
||||
if (priv->die_count_reset_id)
|
||||
g_source_remove (priv->die_count_reset_id);
|
||||
priv->die_count_reset_id = g_timeout_add_seconds (10, wpas_die_count_reset_cb, self);
|
||||
set_die_count (self, priv->die_count + 1);
|
||||
|
||||
if (die_count_exceeded (priv->die_count)) {
|
||||
nm_log_info (LOGD_SUPPLICANT,
|
||||
"wpa_supplicant die count %d; ignoring for 10 seconds",
|
||||
priv->die_count);
|
||||
}
|
||||
|
||||
set_running (self, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
nm_supplicant_manager_state_to_string (guint32 state)
|
||||
/*******************************************************************/
|
||||
|
||||
NMSupplicantManager *
|
||||
nm_supplicant_manager_get (void)
|
||||
{
|
||||
switch (state) {
|
||||
case NM_SUPPLICANT_MANAGER_STATE_DOWN:
|
||||
return "down";
|
||||
case NM_SUPPLICANT_MANAGER_STATE_IDLE:
|
||||
return "idle";
|
||||
static NMSupplicantManager *singleton = NULL;
|
||||
|
||||
if (!singleton)
|
||||
singleton = NM_SUPPLICANT_MANAGER (g_object_new (NM_TYPE_SUPPLICANT_MANAGER, NULL));
|
||||
else
|
||||
g_object_ref (singleton);
|
||||
|
||||
g_assert (singleton);
|
||||
return singleton;
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_init (NMSupplicantManager * self)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (self);
|
||||
DBusGConnection *bus;
|
||||
|
||||
priv->dbus_mgr = nm_dbus_manager_get ();
|
||||
priv->name_owner_id = g_signal_connect (priv->dbus_mgr,
|
||||
"name-owner-changed",
|
||||
G_CALLBACK (name_owner_changed),
|
||||
self);
|
||||
priv->running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, WPAS_DBUS_SERVICE);
|
||||
|
||||
bus = nm_dbus_manager_get_connection (priv->dbus_mgr);
|
||||
priv->proxy = dbus_g_proxy_new_for_name (bus,
|
||||
WPAS_DBUS_SERVICE,
|
||||
WPAS_DBUS_PATH,
|
||||
WPAS_DBUS_INTERFACE);
|
||||
|
||||
priv->ifaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id) {
|
||||
case PROP_AVAILABLE:
|
||||
g_value_set_boolean (value, nm_supplicant_manager_available (NM_SUPPLICANT_MANAGER (object)));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMSupplicantManagerPrivate *priv = NM_SUPPLICANT_MANAGER_GET_PRIVATE (object);
|
||||
|
||||
if (priv->disposed)
|
||||
goto out;
|
||||
priv->disposed = TRUE;
|
||||
|
||||
if (priv->die_count_reset_id)
|
||||
g_source_remove (priv->die_count_reset_id);
|
||||
|
||||
if (priv->dbus_mgr) {
|
||||
if (priv->name_owner_id)
|
||||
g_signal_handler_disconnect (priv->dbus_mgr, priv->name_owner_id);
|
||||
g_object_unref (G_OBJECT (priv->dbus_mgr));
|
||||
}
|
||||
|
||||
g_hash_table_destroy (priv->ifaces);
|
||||
|
||||
if (priv->proxy)
|
||||
g_object_unref (priv->proxy);
|
||||
|
||||
out:
|
||||
/* Chain up to the parent class */
|
||||
G_OBJECT_CLASS (nm_supplicant_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_supplicant_manager_class_init (NMSupplicantManagerClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMSupplicantManagerPrivate));
|
||||
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
object_class->dispose = dispose;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_AVAILABLE,
|
||||
g_param_spec_boolean (NM_SUPPLICANT_MANAGER_AVAILABLE,
|
||||
"Available",
|
||||
"Available",
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,23 +33,6 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* Supplicant manager states
|
||||
* Either state may transition to the other state at any time.
|
||||
*
|
||||
* DOWN: supplicant manager has been created, but cannot be used; the supplicant
|
||||
* is either not running or has not yet been fully initialized.
|
||||
* IDLE: supplicant manager is ready for use
|
||||
*
|
||||
* Note: LAST is an invalid state and only used for boundary checking.
|
||||
*/
|
||||
enum {
|
||||
NM_SUPPLICANT_MANAGER_STATE_DOWN = 0,
|
||||
NM_SUPPLICANT_MANAGER_STATE_IDLE,
|
||||
NM_SUPPLICANT_MANAGER_STATE_LAST
|
||||
};
|
||||
|
||||
|
||||
#define NM_TYPE_SUPPLICANT_MANAGER (nm_supplicant_manager_get_type ())
|
||||
#define NM_SUPPLICANT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManager))
|
||||
#define NM_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass))
|
||||
|
|
@ -57,6 +40,8 @@ enum {
|
|||
#define NM_IS_SUPPLICANT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SUPPLICANT_MANAGER))
|
||||
#define NM_SUPPLICANT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT_MANAGER, NMSupplicantManagerClass))
|
||||
|
||||
#define NM_SUPPLICANT_MANAGER_AVAILABLE "available"
|
||||
|
||||
struct _NMSupplicantManager
|
||||
{
|
||||
GObject parent;
|
||||
|
|
@ -65,24 +50,19 @@ struct _NMSupplicantManager
|
|||
typedef struct
|
||||
{
|
||||
GObjectClass parent;
|
||||
|
||||
/* class members */
|
||||
void (* state) (NMSupplicantManager * mgr, guint32 new_state, guint32 old_state);
|
||||
} NMSupplicantManagerClass;
|
||||
|
||||
GType nm_supplicant_manager_get_type (void);
|
||||
|
||||
NMSupplicantManager * nm_supplicant_manager_get (void);
|
||||
NMSupplicantManager *nm_supplicant_manager_get (void);
|
||||
|
||||
guint32 nm_supplicant_manager_get_state (NMSupplicantManager * mgr);
|
||||
NMSupplicantInterface *nm_supplicant_manager_iface_get (NMSupplicantManager *mgr,
|
||||
const char *ifname,
|
||||
gboolean is_wireless);
|
||||
|
||||
NMSupplicantInterface * nm_supplicant_manager_get_iface (NMSupplicantManager * mgr,
|
||||
const char *ifname,
|
||||
gboolean is_wireless);
|
||||
void nm_supplicant_manager_iface_release (NMSupplicantManager *mgr,
|
||||
NMSupplicantInterface *iface);
|
||||
|
||||
void nm_supplicant_manager_release_iface (NMSupplicantManager * mgr,
|
||||
NMSupplicantInterface * iface);
|
||||
|
||||
const char *nm_supplicant_manager_state_to_string (guint32 state);
|
||||
gboolean nm_supplicant_manager_available (NMSupplicantManager *mgr);
|
||||
|
||||
#endif /* NM_SUPPLICANT_MANAGER_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue