NetworkManager r3238 - in branches/NETWORKMANAGER_0_6_0_RELEASE: . src
- From: tambeti svn gnome org
- To: svn-commits-list gnome org
- Subject: NetworkManager r3238 - in branches/NETWORKMANAGER_0_6_0_RELEASE: . src
- Date: Wed, 16 Jan 2008 16:51:06 +0000 (GMT)
Author: tambeti
Date: Wed Jan 16 16:51:06 2008
New Revision: 3238
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3238&view=rev
Log:
2008-01-16 Tambet Ingo <tambet gmail com>
Shuffle the code a bit in preparation for wired 802.1X
authentication.
* src/nm-device-802-11-wireless.c: Remove the supplicant driving
* code and use
NMSuppicant instead.
* src/nm-supplicant.[ch]: New files. The wpa_supplicant driving
* code is moved
here from nm-device-802-11-wireless.c and refactored a bit so it
can be shared
by wired cards as well.
Added:
branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.c
branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.h
Modified:
branches/NETWORKMANAGER_0_6_0_RELEASE/ChangeLog
branches/NETWORKMANAGER_0_6_0_RELEASE/src/Makefile.am
branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-device-802-11-wireless.c
Modified: branches/NETWORKMANAGER_0_6_0_RELEASE/src/Makefile.am
==============================================================================
--- branches/NETWORKMANAGER_0_6_0_RELEASE/src/Makefile.am (original)
+++ branches/NETWORKMANAGER_0_6_0_RELEASE/src/Makefile.am Wed Jan 16 16:51:06 2008
@@ -64,6 +64,8 @@
nm-ap-security-wpa-psk.h \
nm-ap-security-leap.c \
nm-ap-security-leap.h \
+ nm-supplicant.h \
+ nm-supplicant.c \
nm-marshal-main.c \
kernel-types.h \
wpa.c \
Modified: branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-device-802-11-wireless.c
==============================================================================
--- branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-device-802-11-wireless.c (original)
+++ branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-device-802-11-wireless.c Wed Jan 16 16:51:06 2008
@@ -1,3 +1,5 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw redhat com>
@@ -35,6 +37,7 @@
#include "nm-device-private.h"
#include "NetworkManagerAPList.h"
#include "NetworkManagerDbus.h"
+#include "nm-supplicant.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
#include "NetworkManagerPolicy.h"
@@ -47,15 +50,6 @@
#define NM_DEVICE_802_11_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_802_11_WIRELESS, NMDevice80211WirelessPrivate))
-struct _Supplicant
-{
- GPid pid;
- GSource * watch;
- GSource * status;
- struct wpa_ctrl * ctrl;
- GSource * timeout;
-};
-
struct _NMDevice80211WirelessPrivate
{
gboolean dispose_has_run;
@@ -77,7 +71,7 @@
GSource * scan_timeout;
GSource * pending_scan;
- struct _Supplicant supplicant;
+ NMSupplicant *supplicant;
guint32 failed_link_count;
GSource * link_timeout;
@@ -127,8 +121,6 @@
NMAccessPoint *ap,
gboolean default_link);
-static void supplicant_cleanup (NMDevice80211Wireless *self);
-
static void remove_link_timeout (NMDevice80211Wireless *self);
static void nm_device_802_11_wireless_set_wep_enc_key (NMDevice80211Wireless *self,
@@ -380,8 +372,6 @@
self->priv = NM_DEVICE_802_11_WIRELESS_GET_PRIVATE (self);
self->priv->dispose_has_run = FALSE;
self->priv->is_initialized = FALSE;
-
- self->priv->supplicant.pid = -1;
}
@@ -621,7 +611,7 @@
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev);
/* If the supplicant isn't running, we can't possibly have a link */
- if (!self->priv->supplicant.pid)
+ if (!self->priv->supplicant)
nm_device_set_active_link (NM_DEVICE (self), FALSE);
}
@@ -681,7 +671,11 @@
{
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev);
- supplicant_cleanup (self);
+ if (self->priv->supplicant) {
+ g_object_unref (self->priv->supplicant);
+ self->priv->supplicant = NULL;
+ }
+
remove_link_timeout (self);
}
@@ -2155,11 +2149,11 @@
* the scan request rather than doing it ourselves.
*/
iface = nm_device_get_iface (NM_DEVICE (self));
- if (self->priv->supplicant.ctrl)
+ if (self->priv->supplicant)
{
- if (nm_utils_supplicant_request_with_check (self->priv->supplicant.ctrl,
- "OK", __func__, NULL, "SCAN"))
- success = TRUE;
+ if (nm_utils_supplicant_request_with_check (nm_supplicant_get_ctrl (self->priv->supplicant),
+ "OK", __func__, NULL, "SCAN"))
+ success = TRUE;
}
else
{
@@ -2409,442 +2403,7 @@
return auth_required;
}
-
/****************************************************************************/
-/* WPA Supplicant control stuff
- *
- * Originally from:
- *
- * wpa_supplicant wrapper
- *
- * Copyright (C) 2005 Kay Sievers <kay sievers vrfy org>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation version 2 of the License.
- */
-
-#define WPA_SUPPLICANT_GLOBAL_SOCKET LOCALSTATEDIR"/run/wpa_supplicant-global"
-#define WPA_SUPPLICANT_CONTROL_SOCKET LOCALSTATEDIR"/run/wpa_supplicant"
-#define WPA_SUPPLICANT_NUM_RETRIES 20
-#define WPA_SUPPLICANT_RETRY_TIME_US 100*1000
-
-
-static void
-remove_link_timeout (NMDevice80211Wireless *self)
-{
- g_return_if_fail (self != NULL);
-
- if (self->priv->link_timeout != NULL)
- {
- g_source_destroy (self->priv->link_timeout);
- self->priv->link_timeout = NULL;
- }
-}
-
-static void
-supplicant_remove_timeout (NMDevice80211Wireless *self)
-{
- g_return_if_fail (self != NULL);
-
- /* Remove any pending timeouts on the request */
- if (self->priv->supplicant.timeout != NULL)
- {
- g_source_destroy (self->priv->supplicant.timeout);
- self->priv->supplicant.timeout = NULL;
- }
-}
-
-static char *
-supplicant_get_device_socket_path (NMDevice80211Wireless *self)
-{
- const char *iface;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- iface = nm_device_get_iface (NM_DEVICE (self));
- return g_strdup_printf (WPA_SUPPLICANT_CONTROL_SOCKET "/%s", iface);
-}
-
-static void
-supplicant_cleanup (NMDevice80211Wireless *self)
-{
- char * sock_path;
-
- g_return_if_fail (self != NULL);
-
- if (self->priv->supplicant.pid > 0)
- {
- kill (self->priv->supplicant.pid, SIGTERM);
- self->priv->supplicant.pid = -1;
- }
- if (self->priv->supplicant.watch)
- {
- g_source_destroy (self->priv->supplicant.watch);
- self->priv->supplicant.watch = NULL;
- }
- if (self->priv->supplicant.status)
- {
- g_source_destroy (self->priv->supplicant.status);
- self->priv->supplicant.status = NULL;
- }
- if (self->priv->supplicant.ctrl)
- {
- wpa_ctrl_close (self->priv->supplicant.ctrl);
- self->priv->supplicant.ctrl = NULL;
- }
-
- supplicant_remove_timeout (self);
- remove_link_timeout (self);
-
- /* HACK: should be fixed in wpa_supplicant. Will likely
- * require accomodations for selinux.
- */
- unlink (WPA_SUPPLICANT_GLOBAL_SOCKET);
- sock_path = supplicant_get_device_socket_path (self);
- unlink (sock_path);
- g_free (sock_path);
-}
-
-static void
-supplicant_watch_done (gpointer user_data)
-{
- NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
-
- device->priv->supplicant.watch = NULL;
-}
-
-static void
-supplicant_watch_cb (GPid pid,
- gint status,
- gpointer user_data)
-{
- NMDevice * dev = NM_DEVICE (user_data);
- NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
-
- g_assert (self);
-
- if (WIFEXITED (status))
- nm_warning ("wpa_supplicant exited with error code %d", WEXITSTATUS (status));
- else if (WIFSTOPPED (status))
- nm_warning ("wpa_supplicant stopped unexpectedly with signal %d", WSTOPSIG (status));
- else if (WIFSIGNALED (status))
- nm_warning ("wpa_supplicant died with signal %d", WTERMSIG (status));
- else
- nm_warning ("wpa_supplicant died from an unknown cause");
-
- supplicant_cleanup (self);
-
- nm_device_set_active_link (dev, FALSE);
-}
-
-
-static void
-link_timeout_done (gpointer user_data)
-{
- NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
-
- device->priv->link_timeout = NULL;
-}
-
-
-/*
- * link_timeout_cb
- *
- * Called when the link to the access point has been down for a specified
- * period of time.
- */
-static gboolean
-link_timeout_cb (gpointer user_data)
-{
- NMDevice * dev = NM_DEVICE (user_data);
- NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
- NMActRequest * req = nm_device_get_act_request (dev);
- NMAccessPoint * ap = nm_act_request_get_ap (req);
- NMData * data = nm_device_get_app_data (dev);
- gboolean has_key;
-
- g_assert (dev);
-
- /* Disconnect event during initial authentication and credentials
- * ARE checked - we are likely to have wrong key. Ask the user for
- * another one.
- */
- if ( (nm_act_request_get_stage (req) == NM_ACT_STAGE_DEVICE_CONFIG)
- && (ap_is_auth_required (ap, &has_key) && has_key))
- {
- /* Association/authentication failed, we must have bad encryption key */
- nm_info ("Activation (%s/wireless): disconnected during association,"
- " asking for new key.", nm_device_get_iface (dev));
- supplicant_remove_timeout(self);
- nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
- }
- else
- {
- nm_info ("%s: link timed out.", nm_device_get_iface (dev));
- nm_device_set_active_link (dev, FALSE);
- }
-
- return FALSE;
-}
-
-
-static void
-supplicant_status_done (gpointer user_data)
-{
- NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
-
- device->priv->supplicant.status = NULL;
-}
-
-
-#define MESSAGE_LEN 2048
-
-static gboolean
-supplicant_status_cb (GIOChannel *source,
- GIOCondition condition,
- gpointer user_data)
-{
- NMDevice * dev = NM_DEVICE (user_data);
- NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
- char * message;
- size_t len;
- struct wpa_ctrl * ctrl;
- NMActRequest * req;
-
- g_assert (self);
-
- /* Do nothing if we're supposed to be canceling activation.
- * We'll get cleaned up by the cancellation handlers later.
- */
- if (nm_device_activation_should_cancel (dev))
- return TRUE;
-
- ctrl = self->priv->supplicant.ctrl;
- g_return_val_if_fail (ctrl != NULL, FALSE);
-
- req = nm_device_get_act_request (NM_DEVICE (self));
-
- message = g_malloc (MESSAGE_LEN);
- len = MESSAGE_LEN;
- wpa_ctrl_recv (ctrl, message, &len);
- message[len] = '\0';
-
- if (strstr (message, WPA_EVENT_CONNECTED) != NULL)
- {
- remove_link_timeout (self);
- nm_device_set_active_link (dev, TRUE);
-
- /* If this is the initial association during device activation,
- * schedule the next activation stage.
- */
- if (req && (nm_act_request_get_stage (req) == NM_ACT_STAGE_DEVICE_CONFIG))
- {
- NMAccessPoint *ap = nm_act_request_get_ap (req);
-
- nm_info ("Activation (%s/wireless) Stage 2 of 5 (Device Configure) "
- "successful. Connected to access point '%s'.",
- nm_device_get_iface (NM_DEVICE (self)),
- nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)");
- supplicant_remove_timeout (self);
- nm_device_activate_schedule_stage3_ip_config_start (req);
- }
- }
- else if (strstr (message, WPA_EVENT_DISCONNECTED) != NULL)
- {
- if (nm_device_is_activated (dev) || nm_device_is_activating (dev))
- {
- /* Start the link timeout so we allow some time for reauthentication */
- if ((self->priv->link_timeout == NULL) && !self->priv->scanning)
- {
- GMainContext * context = nm_device_get_main_context (dev);
- self->priv->link_timeout = g_timeout_source_new (8000);
- g_source_set_callback (self->priv->link_timeout,
- link_timeout_cb,
- self,
- link_timeout_done);
- g_source_attach (self->priv->link_timeout, context);
- g_source_unref (self->priv->link_timeout);
- }
- }
- else
- {
- nm_device_set_active_link (dev, FALSE);
- }
- }
-
- g_free (message);
-
- return TRUE;
-}
-
-
-#define NM_SUPPLICANT_TIMEOUT 20 /* how long we wait for wpa_supplicant to associate (in seconds) */
-
-static unsigned int
-get_supplicant_timeout (NMDevice80211Wireless *self)
-{
- if (self->priv->num_freqs > 14)
- return NM_SUPPLICANT_TIMEOUT * 2;
- return NM_SUPPLICANT_TIMEOUT;
-}
-
-
-static void
-supplicant_timeout_done (gpointer user_data)
-{
- NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
-
- device->priv->supplicant.timeout = NULL;
-}
-
-
-/*
- * supplicant_timeout_cb
- *
- * Called when the supplicant has been unable to connect to an access point
- * within a specified period of time.
- */
-static gboolean
-supplicant_timeout_cb (gpointer user_data)
-{
- NMDevice * dev = NM_DEVICE (user_data);
- NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
- NMActRequest * req = nm_device_get_act_request (dev);
- NMAccessPoint * ap = nm_act_request_get_ap (req);
- NMData * data = nm_device_get_app_data (dev);
- gboolean has_key;
-
- g_assert (self);
-
- /* Timed out waiting for authentication success; if the security method
- * in use does not require access point side authentication (Open System
- * WEP, for example) then we are likely using the wrong authentication
- * algorithm or key. Request new one from the user.
- */
- if (!ap_is_auth_required (ap, &has_key) && has_key)
- {
- /* Activation failed, we must have bad encryption key */
- nm_info ("Activation (%s/wireless): association took too long (>%us), asking for new key.",
- nm_device_get_iface (dev), get_supplicant_timeout (self));
- nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
- }
- else
- {
- nm_info ("Activation (%s/wireless): association took too long (>%us), failing activation.",
- nm_device_get_iface (dev), get_supplicant_timeout (self));
- if (nm_device_is_activating (dev))
- nm_policy_schedule_activation_failed (nm_device_get_act_request (dev));
- }
-
- return FALSE;
-}
-
-/*
- * supplicant_child_setup
- *
- * Set the process group ID of the newly forked process
- *
- */
-static void
-supplicant_child_setup (gpointer user_data G_GNUC_UNUSED)
-{
- /* We are in the child process at this point */
- pid_t pid = getpid ();
- setpgid (pid, pid);
-}
-
-static gboolean
-supplicant_exec (NMDevice80211Wireless *self)
-{
- gboolean success = FALSE;
- char * argv[4];
- GError * error = NULL;
- GPid pid = -1;
-
- argv[0] = WPA_SUPPLICANT_BIN;
- argv[1] = "-g";
- argv[2] = WPA_SUPPLICANT_GLOBAL_SOCKET;
- argv[3] = NULL;
-
- success = g_spawn_async ("/", argv, NULL, 0, &supplicant_child_setup, NULL,
- &pid, &error);
- if (!success)
- {
- if (error)
- {
- nm_warning ("Couldn't start wpa_supplicant. Error: (%d) %s",
- error->code, error->message);
- g_error_free (error);
- }
- else
- nm_warning ("Couldn't start wpa_supplicant due to an unknown error.");
- }
- else
- {
- /* Monitor the child process so we know when it stops */
- self->priv->supplicant.pid = pid;
- if (self->priv->supplicant.watch)
- g_source_destroy (self->priv->supplicant.watch);
- self->priv->supplicant.watch = g_child_watch_source_new (pid);
- g_source_set_callback (self->priv->supplicant.watch,
- (GSourceFunc) supplicant_watch_cb,
- self,
- supplicant_watch_done);
- g_source_attach (self->priv->supplicant.watch, nm_device_get_main_context (NM_DEVICE (self)));
- g_source_unref (self->priv->supplicant.watch);
- }
-
- return success;
-}
-
-
-static gboolean
-supplicant_interface_init (NMDevice80211Wireless *self)
-{
- struct wpa_ctrl * ctrl = NULL;
- char * socket_path;
- const char * iface = nm_device_get_iface (NM_DEVICE (self));
- gboolean success = FALSE;
- int tries = 0;
-
- /* Try to open wpa_supplicant's global control socket */
- for (tries = 0; tries < WPA_SUPPLICANT_NUM_RETRIES && !ctrl; tries++)
- {
- ctrl = wpa_ctrl_open (WPA_SUPPLICANT_GLOBAL_SOCKET, NM_RUN_DIR);
- g_usleep (WPA_SUPPLICANT_RETRY_TIME_US);
- }
-
- if (!ctrl)
- {
- nm_info ("Error opening supplicant global control interface.");
- goto exit;
- }
-
- /* wpa_cli -g/var/run/wpa_supplicant-global interface_add eth1 "" wext /var/run/wpa_supplicant */
- if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
- "INTERFACE_ADD %s\t\twext\t" WPA_SUPPLICANT_CONTROL_SOCKET "\t", iface))
- goto exit;
- wpa_ctrl_close (ctrl);
-
- /* Get a control socket to wpa_supplicant for this interface.
- * Try a couple times to work around naive socket naming
- * in wpa_ctrl that sometimes collides with stale ones.
- */
- socket_path = supplicant_get_device_socket_path (self);
- while (!self->priv->supplicant.ctrl && (tries++ < 10))
- self->priv->supplicant.ctrl = wpa_ctrl_open (socket_path, NM_RUN_DIR);
- g_free (socket_path);
- if (!self->priv->supplicant.ctrl)
- {
- nm_info ("Error opening control interface to supplicant.");
- goto exit;
- }
- success = TRUE;
-
-exit:
- return success;
-}
static guint32
find_supported_frequency (NMDevice80211Wireless *self, guint32 *freqs)
@@ -2862,7 +2421,6 @@
return 0;
}
-
static gboolean
supplicant_send_network_config (NMDevice80211Wireless *self,
NMActRequest *req)
@@ -2879,13 +2437,10 @@
guint32 caps;
gboolean supports_wpa;
- g_return_val_if_fail (self != NULL, FALSE);
- g_return_val_if_fail (req != NULL, FALSE);
-
ap = nm_act_request_get_ap (req);
g_assert (ap);
- ctrl = self->priv->supplicant.ctrl;
+ ctrl = nm_supplicant_get_ctrl (self->priv->supplicant);
g_assert (ctrl);
/* Assume that drivers that don't support WPA pretty much suck,
@@ -2985,52 +2540,157 @@
return success;
}
+#define NM_SUPPLICANT_TIMEOUT 20 /* how long we wait for wpa_supplicant to associate (in seconds) */
+
+static unsigned int
+get_supplicant_timeout (NMDevice80211Wireless *self)
+{
+ if (self->priv->num_freqs > 14)
+ return NM_SUPPLICANT_TIMEOUT * 2;
+ return NM_SUPPLICANT_TIMEOUT;
+}
static gboolean
-supplicant_monitor_start (NMDevice80211Wireless *self)
+supplicant_timed_out (gpointer user_data)
{
- gboolean success = FALSE;
- int fd = -1;
- GIOChannel * channel;
- GMainContext * context;
+ NMDevice *dev = NM_DEVICE (user_data);
+ NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (user_data);
+ NMActRequest *req = nm_device_get_act_request (dev);
+ NMAccessPoint *ap = nm_act_request_get_ap (req);
+ NMData *data = nm_device_get_app_data (dev);
+ gboolean has_key;
- g_return_val_if_fail (self != NULL, FALSE);
+ /* Timed out waiting for authentication success; if the security method
+ * in use does not require access point side authentication (Open System
+ * WEP, for example) then we are likely using the wrong authentication
+ * algorithm or key. Request new one from the user.
+ */
+ if (!ap_is_auth_required (ap, &has_key) && has_key) {
+ /* Activation failed, we must have bad encryption key */
+ nm_info ("Activation (%s/wireless): association took too long (>%us), asking for new key.",
+ nm_device_get_iface (dev), get_supplicant_timeout (self));
+ nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
+ } else {
+ nm_info ("Activation (%s/wireless): association took too long (>%us), failing activation.",
+ nm_device_get_iface (dev), get_supplicant_timeout (self));
+ if (nm_device_is_activating (dev))
+ nm_policy_schedule_activation_failed (nm_device_get_act_request (dev));
+ }
- /* register network event monitor */
- if (wpa_ctrl_attach (self->priv->supplicant.ctrl) != 0)
- goto out;
+ return FALSE;
+}
- if ((fd = wpa_ctrl_get_fd (self->priv->supplicant.ctrl)) < 0)
- goto out;
+static void
+remove_link_timeout (NMDevice80211Wireless *self)
+{
+ g_return_if_fail (self != NULL);
- context = nm_device_get_main_context (NM_DEVICE (self));
- channel = g_io_channel_unix_new (fd);
- self->priv->supplicant.status = g_io_create_watch (channel, G_IO_IN);
- g_io_channel_unref (channel);
- g_source_set_callback (self->priv->supplicant.status,
- (GSourceFunc) supplicant_status_cb,
- self,
- supplicant_status_done);
- g_source_attach (self->priv->supplicant.status, context);
- g_source_unref (self->priv->supplicant.status);
-
- /* Set up a timeout on the association to kill it after get_supplicant_time() seconds */
- self->priv->supplicant.timeout = g_timeout_source_new (get_supplicant_timeout (self) * 1000);
- g_source_set_callback (self->priv->supplicant.timeout,
- supplicant_timeout_cb,
- self,
- supplicant_timeout_done);
- g_source_attach (self->priv->supplicant.timeout, context);
- g_source_unref (self->priv->supplicant.timeout);
+ if (self->priv->link_timeout != NULL)
+ {
+ g_source_destroy (self->priv->link_timeout);
+ self->priv->link_timeout = NULL;
+ }
+}
- success = TRUE;
+static void
+link_timeout_done (gpointer user_data)
+{
+ NMDevice80211Wireless *device = NM_DEVICE_802_11_WIRELESS (user_data);
-out:
- return success;
+ device->priv->link_timeout = NULL;
+}
+
+/*
+ * link_timeout_cb
+ *
+ * Called when the link to the access point has been down for a specified
+ * period of time.
+ */
+static gboolean
+link_timeout_cb (gpointer user_data)
+{
+ NMDevice * dev = NM_DEVICE (user_data);
+ NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (user_data);
+ NMActRequest * req = nm_device_get_act_request (dev);
+ NMAccessPoint * ap = nm_act_request_get_ap (req);
+ NMData * data = nm_device_get_app_data (dev);
+ gboolean has_key;
+
+ g_assert (dev);
+
+ /* Disconnect event during initial authentication and credentials
+ * ARE checked - we are likely to have wrong key. Ask the user for
+ * another one.
+ */
+ if ( (nm_act_request_get_stage (req) == NM_ACT_STAGE_DEVICE_CONFIG)
+ && (ap_is_auth_required (ap, &has_key) && has_key))
+ {
+ /* Association/authentication failed, we must have bad encryption key */
+ nm_info ("Activation (%s/wireless): disconnected during association,"
+ " asking for new key.", nm_device_get_iface (dev));
+ nm_supplicant_remove_timeout (self->priv->supplicant);
+ nm_dbus_get_user_key_for_network (data->dbus_connection, req, TRUE);
+ }
+ else
+ {
+ nm_info ("%s: link timed out.", nm_device_get_iface (dev));
+ nm_device_set_active_link (dev, FALSE);
+ }
+
+ return FALSE;
}
+static void
+supplicant_state_changed (NMSupplicant *supplicant,
+ gboolean connected,
+ gpointer user_data)
+{
+ NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (user_data);
+ NMDevice *dev = NM_DEVICE (self);
+ NMActRequest *req = nm_device_get_act_request (NM_DEVICE (self));
+
+ if (connected) {
+ remove_link_timeout (self);
+ nm_device_set_active_link (dev, TRUE);
+
+ /* If this is the initial association during device activation,
+ * schedule the next activation stage.
+ */
+ if (req && (nm_act_request_get_stage (req) == NM_ACT_STAGE_DEVICE_CONFIG)) {
+ NMAccessPoint *ap = nm_act_request_get_ap (req);
+
+ nm_info ("Activation (%s/wireless) Stage 2 of 5 (Device Configure) "
+ "successful. Connected to access point '%s'.",
+ nm_device_get_iface (dev),
+ nm_ap_get_essid (ap) ? nm_ap_get_essid (ap) : "(none)");
+ nm_supplicant_remove_timeout (self->priv->supplicant);
+ nm_device_activate_schedule_stage3_ip_config_start (req);
+ }
+ } else {
+ if (nm_device_is_activated (dev) || nm_device_is_activating (dev)) {
+ /* Start the link timeout so we allow some time for reauthentication */
+ if ((self->priv->link_timeout == NULL) && !self->priv->scanning) {
+ self->priv->link_timeout = g_timeout_source_new (8000);
+ g_source_set_callback (self->priv->link_timeout,
+ link_timeout_cb,
+ self,
+ link_timeout_done);
+ g_source_attach (self->priv->link_timeout, nm_device_get_main_context (dev));
+ g_source_unref (self->priv->link_timeout);
+ }
+ } else
+ nm_device_set_active_link (dev, FALSE);
+ }
+}
+static void
+supplicant_down (NMSupplicant *supplicant,
+ gpointer user_data)
+{
+ NMDevice80211Wireless *self = NM_DEVICE_802_11_WIRELESS (user_data);
+ remove_link_timeout (self);
+}
/****************************************************************************/
@@ -3040,15 +2700,13 @@
{
NMDevice80211Wireless * self = NM_DEVICE_802_11_WIRELESS (dev);
NMAccessPoint * ap = nm_act_request_get_ap (req);
- NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
NMData * data = nm_act_request_get_data (req);
const char * iface;
gboolean ask_user = FALSE;
+ GMainContext *ctx;
g_assert (ap);
- supplicant_cleanup (self);
-
/* If we need an encryption key, get one */
if (ap_need_key (self, ap, &ask_user))
{
@@ -3060,22 +2718,32 @@
sleep (1);
iface = nm_device_get_iface (dev);
- if (!supplicant_exec (self))
+ ctx = nm_device_get_main_context (dev);
+
+ self->priv->supplicant = nm_supplicant_new ();
+ g_signal_connect (self->priv->supplicant, "state-changed",
+ G_CALLBACK (supplicant_state_changed),
+ self);
+
+ g_signal_connect (self->priv->supplicant, "down",
+ G_CALLBACK (supplicant_down),
+ self);
+
+ if (!nm_supplicant_exec (self->priv->supplicant, ctx))
{
- nm_warning ("Activation (%s/wireless): couldn't start the supplicant.",
- iface);
+ nm_warning ("Activation (%s/wireless): couldn't start the supplicant.", iface);
goto out;
}
- if (!supplicant_interface_init (self))
+ if (!nm_supplicant_interface_init (self->priv->supplicant, iface, "wext"))
{
- nm_warning ("Activation (%s/wireless): couldn't connect to the supplicant.",
- iface);
+ nm_warning ("Activation (%s/wireless): couldn't connect to the supplicant.", iface);
goto out;
}
- if (!supplicant_monitor_start (self))
+ if (!nm_supplicant_monitor_start (self->priv->supplicant, ctx,
+ get_supplicant_timeout (self),
+ supplicant_timed_out, self))
{
- nm_warning ("Activation (%s/wireless): couldn't monitor the supplicant.",
- iface);
+ nm_warning ("Activation (%s/wireless): couldn't monitor the supplicant.", iface);
goto out;
}
if (!supplicant_send_network_config (self, req))
@@ -3086,10 +2754,13 @@
}
/* We'll get stage3 started when the supplicant connects */
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
+ return NM_ACT_STAGE_RETURN_POSTPONE;
out:
- return ret;
+ g_object_unref (self->priv->supplicant);
+ self->priv->supplicant = NULL;
+
+ return NM_ACT_STAGE_RETURN_FAILURE;
}
Added: branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.c
==============================================================================
--- (empty file)
+++ branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.c Wed Jan 16 16:51:06 2008
@@ -0,0 +1,419 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#include <signal.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "nm-supplicant.h"
+#include "NetworkManagerUtils.h"
+#include "nm-utils.h"
+#include "wpa_ctrl.h"
+
+
+/****************************************************************************/
+/* WPA Supplicant control stuff
+ *
+ * Originally from:
+ *
+ * wpa_supplicant wrapper
+ *
+ * Copyright (C) 2005 Kay Sievers <kay sievers vrfy org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 of the License.
+ */
+
+#define WPA_SUPPLICANT_GLOBAL_SOCKET LOCALSTATEDIR"/run/wpa_supplicant-global"
+#define WPA_SUPPLICANT_CONTROL_SOCKET LOCALSTATEDIR"/run/wpa_supplicant"
+#define WPA_SUPPLICANT_NUM_RETRIES 20
+#define WPA_SUPPLICANT_RETRY_TIME_US 100*1000
+
+G_DEFINE_TYPE (NMSupplicant, nm_supplicant, G_TYPE_OBJECT)
+
+#define NM_SUPPLICANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SUPPLICANT, NMSupplicantPrivate))
+
+typedef struct {
+ GPid pid;
+ GSource *watch;
+ GSource *status;
+ GSource *timeout;
+ struct wpa_ctrl *ctrl;
+
+ char *socket_path;
+ char *message;
+} NMSupplicantPrivate;
+
+enum {
+ STATE_CHANGED,
+ DOWN,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+NMSupplicant *
+nm_supplicant_new (void)
+{
+ return (NMSupplicant *) g_object_new (NM_TYPE_SUPPLICANT, NULL);
+}
+
+void
+nm_supplicant_remove_timeout (NMSupplicant *self)
+{
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (self);
+
+ /* Remove any pending timeouts on the request */
+ if (priv->timeout != NULL) {
+ g_source_destroy (priv->timeout);
+ priv->timeout = NULL;
+ }
+}
+
+void
+nm_supplicant_down (NMSupplicant *self)
+{
+ NMSupplicantPrivate *priv;
+
+ g_return_if_fail (NM_IS_SUPPLICANT (self));
+
+ priv = NM_SUPPLICANT_GET_PRIVATE (self);
+
+ if (priv->pid > 0) {
+ kill (priv->pid, SIGTERM);
+ priv->pid = -1;
+ }
+
+ if (priv->watch) {
+ g_source_destroy (priv->watch);
+ priv->watch = NULL;
+ }
+
+ if (priv->status) {
+ g_source_destroy (priv->status);
+ priv->status = NULL;
+ }
+
+ if (priv->ctrl) {
+ wpa_ctrl_close (priv->ctrl);
+ priv->ctrl = NULL;
+ }
+
+ nm_supplicant_remove_timeout (self);
+
+ /* HACK: should be fixed in wpa_supplicant. Will likely
+ * require accomodations for selinux.
+ */
+ unlink (WPA_SUPPLICANT_GLOBAL_SOCKET);
+ unlink (priv->socket_path);
+
+ g_signal_emit (self, signals[DOWN], 0);
+}
+
+static void
+supplicant_watch_done (gpointer user_data)
+{
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (user_data);
+
+ priv->watch = NULL;
+}
+
+static void
+supplicant_watch_cb (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ NMSupplicant *self = NM_SUPPLICANT (user_data);
+
+ if (WIFEXITED (status))
+ nm_warning ("wpa_supplicant exited with error code %d", WEXITSTATUS (status));
+ else if (WIFSTOPPED (status))
+ nm_warning ("wpa_supplicant stopped unexpectedly with signal %d", WSTOPSIG (status));
+ else if (WIFSIGNALED (status))
+ nm_warning ("wpa_supplicant died with signal %d", WTERMSIG (status));
+ else
+ nm_warning ("wpa_supplicant died from an unknown cause");
+
+ nm_supplicant_down (self);
+}
+
+/*
+ * supplicant_child_setup
+ *
+ * Set the process group ID of the newly forked process
+ *
+ */
+static void
+supplicant_child_setup (gpointer user_data G_GNUC_UNUSED)
+{
+ /* We are in the child process at this point */
+ pid_t pid = getpid ();
+ setpgid (pid, pid);
+}
+
+gboolean
+nm_supplicant_exec (NMSupplicant *self,
+ GMainContext *ctx)
+{
+ gboolean success;
+ char *argv[4];
+ GPid pid;
+ GError *err = NULL;
+
+ g_return_val_if_fail (NM_IS_SUPPLICANT (self), FALSE);
+
+ argv[0] = WPA_SUPPLICANT_BIN;
+ argv[1] = "-g";
+ argv[2] = WPA_SUPPLICANT_GLOBAL_SOCKET;
+ argv[3] = NULL;
+
+ success = g_spawn_async ("/", argv, NULL, 0, &supplicant_child_setup, NULL, &pid, &err);
+ if (!success) {
+ if (err) {
+ nm_warning ("Couldn't start wpa_supplicant. Error: (%d) %s", err->code, err->message);
+ g_error_free (err);
+ } else
+ nm_warning ("Couldn't start wpa_supplicant due to an unknown error.");
+ } else {
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (self);
+
+ /* Monitor the child process so we know when it stops */
+ priv->pid = pid;
+ if (priv->watch)
+ g_source_destroy (priv->watch);
+
+ priv->watch = g_child_watch_source_new (pid);
+ g_source_set_callback (priv->watch,
+ (GSourceFunc) supplicant_watch_cb,
+ self,
+ supplicant_watch_done);
+ g_source_attach (priv->watch, ctx);
+ g_source_unref (priv->watch);
+ }
+
+ return success;
+}
+
+gboolean
+nm_supplicant_interface_init (NMSupplicant *self,
+ const char *iface,
+ const char *supplicant_driver)
+{
+ NMSupplicantPrivate *priv;
+ struct wpa_ctrl *ctrl = NULL;
+ int tries;
+
+ g_return_val_if_fail (NM_IS_SUPPLICANT (self), FALSE);
+ g_return_val_if_fail (iface != NULL, FALSE);
+
+ /* Try to open wpa_supplicant's global control socket */
+ for (tries = 0; tries < WPA_SUPPLICANT_NUM_RETRIES && !ctrl; tries++) {
+ ctrl = wpa_ctrl_open (WPA_SUPPLICANT_GLOBAL_SOCKET, NM_RUN_DIR);
+ g_usleep (WPA_SUPPLICANT_RETRY_TIME_US);
+ }
+
+ if (!ctrl) {
+ nm_info ("Error opening supplicant global control interface.");
+ return FALSE;
+ }
+
+ /* wpa_cli -g/var/run/wpa_supplicant-global interface_add eth1 "" wext /var/run/wpa_supplicant */
+ if (!nm_utils_supplicant_request_with_check (ctrl, "OK", __func__, NULL,
+ "INTERFACE_ADD %s\t\t%s\t" WPA_SUPPLICANT_CONTROL_SOCKET "\t",
+ iface, supplicant_driver)) {
+ wpa_ctrl_close (ctrl);
+ return FALSE;
+ }
+
+ wpa_ctrl_close (ctrl);
+
+ priv = NM_SUPPLICANT_GET_PRIVATE (self);
+
+ /* Get a control socket to wpa_supplicant for this interface.
+ * Try a couple times to work around naive socket naming
+ * in wpa_ctrl that sometimes collides with stale ones.
+ */
+ priv->socket_path = g_strdup_printf (WPA_SUPPLICANT_CONTROL_SOCKET "/%s", iface);
+
+ while (!priv->ctrl && (tries++ < 10))
+ priv->ctrl = wpa_ctrl_open (priv->socket_path, NM_RUN_DIR);
+
+ if (!priv->ctrl)
+ nm_info ("Error opening control interface to supplicant.");
+
+ return priv->ctrl != NULL;
+}
+
+static void
+supplicant_status_done (gpointer user_data)
+{
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (user_data);
+
+ priv->status = NULL;
+}
+
+static void
+supplicant_state_changed (NMSupplicant *self, gboolean up)
+{
+ g_signal_emit (self, signals[STATE_CHANGED], 0, up);
+}
+
+#define MESSAGE_LEN 2048
+
+static gboolean
+supplicant_status_cb (GIOChannel *source,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ NMSupplicant *self = NM_SUPPLICANT (user_data);
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (self);
+ size_t len = MESSAGE_LEN;
+
+ wpa_ctrl_recv (priv->ctrl, priv->message, &len);
+ priv->message[len] = '\0';
+
+ if (strstr (priv->message, WPA_EVENT_CONNECTED) != NULL)
+ supplicant_state_changed (self, TRUE);
+ else if (strstr (priv->message, WPA_EVENT_DISCONNECTED) != NULL)
+ supplicant_state_changed (self, FALSE);
+
+ return TRUE;
+}
+
+typedef struct {
+ NMSupplicant *supplicant;
+ GSourceFunc callback;
+ gpointer user_data;
+} TimeoutInfo;
+
+static void
+supplicant_timeout_done (gpointer user_data)
+{
+ TimeoutInfo *info = (TimeoutInfo *) user_data;
+
+ NM_SUPPLICANT_GET_PRIVATE (info->supplicant)->timeout = NULL;
+
+ g_free (info);
+}
+
+static void
+supplicant_timeout_cb (gpointer user_data)
+{
+ TimeoutInfo *info = (TimeoutInfo *) user_data;
+
+ info->callback (info->user_data);
+}
+
+gboolean
+nm_supplicant_monitor_start (NMSupplicant *self,
+ GMainContext *context,
+ guint32 timeout,
+ GSourceFunc timeout_cb,
+ gpointer user_data)
+{
+ NMSupplicantPrivate *priv;
+ int fd;
+ GIOChannel *channel;
+
+ g_return_val_if_fail (NM_IS_SUPPLICANT (self), FALSE);
+
+ priv = NM_SUPPLICANT_GET_PRIVATE (self);
+
+ /* register network event monitor */
+ if (wpa_ctrl_attach (priv->ctrl) != 0)
+ return FALSE;
+
+ if ((fd = wpa_ctrl_get_fd (priv->ctrl)) < 0)
+ return FALSE;
+
+ channel = g_io_channel_unix_new (fd);
+ priv->status = g_io_create_watch (channel, G_IO_IN);
+ g_io_channel_unref (channel);
+ g_source_set_callback (priv->status,
+ (GSourceFunc) supplicant_status_cb,
+ self,
+ supplicant_status_done);
+ g_source_attach (priv->status, context);
+ g_source_unref (priv->status);
+
+ if (timeout_cb) {
+ TimeoutInfo *info;
+
+ info = g_new (TimeoutInfo, 1);
+ info->supplicant = self;
+ info->callback = timeout_cb;
+ info->user_data = user_data;
+
+ priv->timeout = g_timeout_source_new (timeout * 1000);
+ g_source_set_callback (priv->timeout,
+ (GSourceFunc) supplicant_timeout_cb,
+ info,
+ supplicant_timeout_done);
+ g_source_attach (priv->timeout, context);
+ g_source_unref (priv->timeout);
+ }
+
+ return TRUE;
+}
+
+struct wpa_ctrl *
+nm_supplicant_get_ctrl (NMSupplicant *self)
+{
+ g_return_val_if_fail (NM_IS_SUPPLICANT (self), NULL);
+
+ return NM_SUPPLICANT_GET_PRIVATE (self)->ctrl;
+}
+
+/*****************************************************************************/
+
+static void
+nm_supplicant_init (NMSupplicant *supplicant)
+{
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (supplicant);
+
+ priv->message = g_malloc (MESSAGE_LEN);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSupplicantPrivate *priv = NM_SUPPLICANT_GET_PRIVATE (object);
+
+ nm_supplicant_down (NM_SUPPLICANT (object));
+
+ g_free (priv->socket_path);
+ g_free (priv->message);
+
+ G_OBJECT_CLASS (nm_supplicant_parent_class)->finalize (object);
+}
+
+static void
+nm_supplicant_class_init (NMSupplicantClass *supplicant_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (supplicant_class);
+
+ g_type_class_add_private (supplicant_class, sizeof (NMSupplicantPrivate));
+
+ object_class->finalize = finalize;
+
+ /* signals */
+ signals[STATE_CHANGED] =
+ g_signal_new ("state-changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMSupplicantClass, state_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1,
+ G_TYPE_BOOLEAN);
+
+ signals[DOWN] =
+ g_signal_new ("down",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMSupplicantClass, down),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
Added: branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.h
==============================================================================
--- (empty file)
+++ branches/NETWORKMANAGER_0_6_0_RELEASE/src/nm-supplicant.h Wed Jan 16 16:51:06 2008
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+
+#ifndef NM_SUPPLICANT_H
+#define NM_SUPPLICANT_H 1
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+
+#define NM_TYPE_SUPPLICANT (nm_supplicant_get_type ())
+#define NM_SUPPLICANT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUPPLICANT, NMSupplicant))
+#define NM_SUPPLICANT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUPPLICANT, NMSupplicantClass))
+#define NM_IS_SUPPLICANT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUPPLICANT))
+#define NM_IS_SUPPLICANT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SUPPLICANT))
+#define NM_SUPPLICANT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUPPLICANT, NMSupplicantClass))
+
+typedef struct {
+ GObject parent;
+} NMSupplicant;
+
+typedef struct {
+ GObjectClass parent;
+
+ /* Signals */
+ void (*state_changed) (NMSupplicant *supplicant,
+ gboolean connected);
+
+ void (*down) (NMSupplicant *supplicant);
+} NMSupplicantClass;
+
+GType nm_supplicant_get_type (void);
+
+NMSupplicant *nm_supplicant_new (void);
+gboolean nm_supplicant_exec (NMSupplicant *self,
+ GMainContext *ctx);
+
+gboolean nm_supplicant_interface_init (NMSupplicant *self,
+ const char *iface,
+ const char *supplicant_driver);
+
+gboolean nm_supplicant_monitor_start (NMSupplicant *self,
+ GMainContext *context,
+ guint32 timeout,
+ GSourceFunc timeout_cb,
+ gpointer user_data);
+
+void nm_supplicant_remove_timeout (NMSupplicant *self);
+
+void nm_supplicant_down (NMSupplicant *self);
+
+struct wpa_ctrl *nm_supplicant_get_ctrl (NMSupplicant *self);
+
+
+#endif /* NM_SUPPLICANT_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]