1    	/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2    	/* NetworkManager -- Network link manager
3    	 *
4    	 * This program is free software; you can redistribute it and/or modify
5    	 * it under the terms of the GNU General Public License as published by
6    	 * the Free Software Foundation; either version 2 of the License, or
7    	 * (at your option) any later version.
8    	 *
9    	 * This program is distributed in the hope that it will be useful,
10   	 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   	 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   	 * GNU General Public License for more details.
13   	 *
14   	 * You should have received a copy of the GNU General Public License along
15   	 * with this program; if not, write to the Free Software Foundation, Inc.,
16   	 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17   	 *
18   	 * Copyright (C) 2005 - 2012 Red Hat, Inc.
19   	 * Copyright (C) 2006 - 2008 Novell, Inc.
20   	 */
21   	
22   	#include <glib.h>
23   	#include <glib/gi18n.h>
24   	#include <dbus/dbus.h>
25   	#include <netinet/in.h>
26   	#include <string.h>
27   	#include <net/ethernet.h>
28   	#include <sys/stat.h>
29   	#include <sys/wait.h>
30   	#include <signal.h>
31   	#include <unistd.h>
32   	#include <linux/sockios.h>
33   	#include <linux/ethtool.h>
34   	#include <sys/ioctl.h>
35   	#include <netinet/ether.h>
36   	#include <errno.h>
37   	
38   	#include "nm-glib-compat.h"
39   	#include "nm-dbus-manager.h"
40   	#include "nm-device.h"
41   	#include "nm-device-wifi.h"
42   	#include "nm-device-private.h"
43   	#include "nm-utils.h"
44   	#include "nm-logging.h"
45   	#include "NetworkManagerUtils.h"
46   	#include "nm-activation-request.h"
47   	#include "nm-supplicant-manager.h"
48   	#include "nm-supplicant-interface.h"
49   	#include "nm-supplicant-config.h"
50   	#include "nm-setting-connection.h"
51   	#include "nm-setting-wireless.h"
52   	#include "nm-setting-wireless-security.h"
53   	#include "nm-setting-8021x.h"
54   	#include "nm-setting-ip4-config.h"
55   	#include "nm-setting-ip6-config.h"
56   	#include "nm-platform.h"
57   	#include "nm-manager-auth.h"
58   	#include "nm-settings-connection.h"
59   	#include "nm-enum-types.h"
60   	#include "wifi-utils.h"
61   	
62   	static gboolean impl_device_get_access_points (NMDeviceWifi *device,
63   	                                               GPtrArray **aps,
64   	                                               GError **err);
65   	
66   	static void impl_device_request_scan (NMDeviceWifi *device,
67   	                                      GHashTable *options,
68   	                                      DBusGMethodInvocation *context);
69   	
70   	#include "nm-device-wifi-glue.h"
71   	
72   	
73   	/* All of these are in seconds */
74   	#define SCAN_INTERVAL_MIN 3
75   	#define SCAN_INTERVAL_STEP 20
76   	#define SCAN_INTERVAL_MAX 120
77   	
78   	#define WIRELESS_SECRETS_TRIES "wireless-secrets-tries"
79   	
80   	G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
81   	
82   	#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate))
83   	
84   	
85   	enum {
86   		PROP_0,
87   		PROP_PERM_HW_ADDRESS,
88   		PROP_MODE,
89   		PROP_BITRATE,
90   		PROP_ACTIVE_ACCESS_POINT,
91   		PROP_CAPABILITIES,
92   		PROP_SCANNING,
93   		PROP_IPW_RFKILL_STATE,
94   	
95   		LAST_PROP
96   	};
97   	
98   	enum {
99   		ACCESS_POINT_ADDED,
100  		ACCESS_POINT_REMOVED,
101  		HIDDEN_AP_FOUND,
102  		SCANNING_ALLOWED,
103  	
104  		LAST_SIGNAL
105  	};
106  	
107  	static guint signals[LAST_SIGNAL] = { 0 };
108  	
109  	typedef struct Supplicant {
110  		NMSupplicantManager *mgr;
111  		NMSupplicantInterface *iface;
112  	
113  		guint iface_error_id;
114  	
115  		/* Timeouts and idles */
116  		guint iface_con_error_cb_id;
117  		guint con_timeout_id;
118  	} Supplicant;
119  	
120  	struct _NMDeviceWifiPrivate {
121  		gboolean          disposed;
122  	
123  		guint8            perm_hw_addr[ETH_ALEN];    /* Permanent MAC address */
124  		guint8            initial_hw_addr[ETH_ALEN]; /* Initial MAC address (as seen when NM starts) */
125  	
126  		/* Legacy rfkill for ipw2x00; will be fixed with 2.6.33 kernel */
127  		char *            ipw_rfkill_path;
128  		guint             ipw_rfkill_id;
129  		RfKillState       ipw_rfkill_state;
130  	
131  		gint8             invalid_strength_counter;
132  	
133  		GSList *          ap_list;
134  		NMAccessPoint *   current_ap;
135  		guint32           rate;
136  		gboolean          enabled; /* rfkilled or not */
137  		
138  		time_t            scheduled_scan_time;
139  		guint8            scan_interval; /* seconds */
140  		guint             pending_scan_id;
141  		guint             scanlist_cull_id;
142  		gboolean          requested_scan;
143  	
144  		Supplicant        supplicant;
145  		WifiData *        wifi_data;
146  		gboolean          ssid_found;
147  		NM80211Mode       mode;
148  	
149  		guint32           failed_link_count;
150  		guint             periodic_source_id;
151  		guint             link_timeout_id;
152  	
153  		NMDeviceWifiCapabilities capabilities;
154  	};
155  	
156  	static gboolean check_scanning_allowed (NMDeviceWifi *self);
157  	
158  	static void schedule_scan (NMDeviceWifi *self, gboolean backoff);
159  	
160  	static void cancel_pending_scan (NMDeviceWifi *self);
161  	
162  	static void cleanup_association_attempt (NMDeviceWifi * self,
163  	                                         gboolean disconnect);
164  	
165  	static void remove_supplicant_timeouts (NMDeviceWifi *self);
166  	
167  	static void supplicant_iface_state_cb (NMSupplicantInterface *iface,
168  	                                       guint32 new_state,
169  	                                       guint32 old_state,
170  	                                       int disconnect_reason,
171  	                                       gpointer user_data);
172  	
173  	static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface,
174  	                                         const char *object_path,
175  	                                         GHashTable *properties,
176  	                                         NMDeviceWifi * self);
177  	
178  	static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
179  	                                             const char *object_path,
180  	                                             GHashTable *properties,
181  	                                             NMDeviceWifi *self);
182  	
183  	static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
184  	                                             const char *object_path,
185  	                                             NMDeviceWifi *self);
186  	
187  	static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface,
188  	                                           gboolean success,
189  	                                           NMDeviceWifi * self);
190  	
191  	static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface,
192  	                                                 GParamSpec * pspec,
193  	                                                 NMDeviceWifi * self);
194  	
195  	static void schedule_scanlist_cull (NMDeviceWifi *self);
196  	
197  	static gboolean request_wireless_scan (gpointer user_data);
198  	
199  	/*****************************************************************/
200  	
201  	#define NM_WIFI_ERROR (nm_wifi_error_quark ())
202  	
203  	static GQuark
204  	nm_wifi_error_quark (void)
205  	{
206  		static GQuark quark = 0;
207  		if (!quark)
208  			quark = g_quark_from_static_string ("nm-wifi-error");
209  		return quark;
210  	}
211  	
212  	/*****************************************************************/
213  	
214  	/* IPW rfkill handling (until 2.6.33) */
215  	RfKillState
216  	nm_device_wifi_get_ipw_rfkill_state (NMDeviceWifi *self)
217  	{
218  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
219  		char *contents = NULL;
220  		RfKillState state = RFKILL_UNBLOCKED;
221  		const char *str_state = NULL;
222  	
223  		if (   priv->ipw_rfkill_path
224  		    && g_file_get_contents (priv->ipw_rfkill_path, &contents, NULL, NULL)) {
225  			contents = g_strstrip (contents);
226  	
227  			/* 0 - RF kill not enabled
228  			 * 1 - SW based RF kill active (sysfs)
229  			 * 2 - HW based RF kill active
230  			 * 3 - Both HW and SW baed RF kill active
231  			 */
232  			switch (contents[0]) {
233  			case '1':
234  				state = RFKILL_SOFT_BLOCKED;
235  				str_state = "soft-blocked";
236  				break;
237  			case '2':
238  			case '3':
239  				state = RFKILL_HARD_BLOCKED;
240  				str_state = "hard-blocked";
241  				break;
242  			case '0':
243  				str_state = "unblocked";
244  			default:
245  				break;
246  			}
247  			g_free (contents);
248  	
249  			nm_log_dbg (LOGD_RFKILL, "(%s): ipw rfkill state '%s'",
250  			            nm_device_get_iface (NM_DEVICE (self)),
251  			            str_state ? str_state : "(unknown)");
252  		}
253  	
254  		return state;
255  	}
256  	
257  	static gboolean
258  	ipw_rfkill_state_work (gpointer user_data)
259  	{
260  		NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
261  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
262  		RfKillState old_state;
263  	
264  		old_state = priv->ipw_rfkill_state;
265  		priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self);
266  		if (priv->ipw_rfkill_state != old_state)
267  			g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_IPW_RFKILL_STATE);
268  	
269  		return TRUE;
270  	}
271  	
272  	/*****************************************************************/
273  	
274  	static GObject*
275  	constructor (GType type,
276  	             guint n_construct_params,
277  	             GObjectConstructParam *construct_params)
278  	{
279  		GObject *object;
280  		GObjectClass *klass;
281  		NMDeviceWifi *self;
282  		NMDeviceWifiPrivate *priv;
283  	
284  		klass = G_OBJECT_CLASS (nm_device_wifi_parent_class);
285  		object = klass->constructor (type, n_construct_params, construct_params);
286  		if (!object)
287  			return NULL;
288  	
289  		self = NM_DEVICE_WIFI (object);
290  		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
291  	
292  		nm_log_dbg (LOGD_HW | LOGD_WIFI, "(%s): kernel ifindex %d",
293  		            nm_device_get_iface (NM_DEVICE (self)),
294  		            nm_device_get_ifindex (NM_DEVICE (self)));
295  	
296  		priv->wifi_data = wifi_utils_init (nm_device_get_iface (NM_DEVICE (self)),
297  		                                   nm_device_get_ifindex (NM_DEVICE (self)),
298  		                                   TRUE);
299  		if (priv->wifi_data == NULL) {
300  			nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s): failed to initialize WiFi driver",
301  			             nm_device_get_iface (NM_DEVICE (self)));
302  			g_object_unref (object);
303  			return NULL;
304  		}
305  		priv->capabilities = wifi_utils_get_caps (priv->wifi_data);
306  	
307  		if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) {
308  			nm_log_info (LOGD_HW | LOGD_WIFI, "(%s): driver supports Access Point (AP) mode",
309  			             nm_device_get_iface (NM_DEVICE (self)));
310  		}
311  	
312  		/* Connect to the supplicant manager */
313  		priv->supplicant.mgr = nm_supplicant_manager_get ();
314  		g_assert (priv->supplicant.mgr);
315  	
316  		/* The ipw2x00 drivers don't integrate with the kernel rfkill subsystem until
317  		 * 2.6.33.  Thus all our nice libgudev magic is useless.  So we get to poll.
318  		 *
319  		 * FIXME: when 2.6.33 comes lands, we can do some sysfs parkour to figure out
320  		 * if we need to poll or not by matching /sys/class/net/ethX/device to one
321  		 * of the /sys/class/rfkill/rfkillX/device links.  If there's a match, we
322  		 * don't have to poll.
323  		 */
324  		priv->ipw_rfkill_path = g_strdup_printf ("/sys/class/net/%s/device/rf_kill",
325  		                                         nm_device_get_iface (NM_DEVICE (self)));
326  		if (!g_file_test (priv->ipw_rfkill_path, G_FILE_TEST_IS_REGULAR)) {
327  			g_free (priv->ipw_rfkill_path);
328  			priv->ipw_rfkill_path = NULL;
329  		}
330  		priv->ipw_rfkill_state = nm_device_wifi_get_ipw_rfkill_state (self);
331  	
332  		return object;
333  	}
334  	
335  	static gboolean
336  	supplicant_interface_acquire (NMDeviceWifi *self)
337  	{
338  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
339  	
340  		g_return_val_if_fail (self != NULL, FALSE);
341  		/* interface already acquired? */
342  		g_return_val_if_fail (priv->supplicant.iface == NULL, TRUE);
343  	
344  		priv->supplicant.iface = nm_supplicant_manager_iface_get (priv->supplicant.mgr,
345  		                                                          nm_device_get_iface (NM_DEVICE (self)),
346  		                                                          TRUE);
347  		if (priv->supplicant.iface == NULL) {
348  			nm_log_err (LOGD_WIFI, "Couldn't initialize supplicant interface for %s.",
349  			            nm_device_get_iface (NM_DEVICE (self)));
350  			return FALSE;
351  		}
352  	
353  		if (nm_supplicant_interface_get_state (priv->supplicant.iface) < NM_SUPPLICANT_INTERFACE_STATE_READY)
354  			nm_device_add_pending_action (NM_DEVICE (self), "waiting for supplicant");
355  	
356  		g_signal_connect (priv->supplicant.iface,
357  		                  NM_SUPPLICANT_INTERFACE_STATE,
358  		                  G_CALLBACK (supplicant_iface_state_cb),
359  		                  self);
360  		g_signal_connect (priv->supplicant.iface,
361  		                  NM_SUPPLICANT_INTERFACE_NEW_BSS,
362  		                  G_CALLBACK (supplicant_iface_new_bss_cb),
363  		                  self);
364  		g_signal_connect (priv->supplicant.iface,
365  		                  NM_SUPPLICANT_INTERFACE_BSS_UPDATED,
366  		                  G_CALLBACK (supplicant_iface_bss_updated_cb),
367  		                  self);
368  		g_signal_connect (priv->supplicant.iface,
369  		                  NM_SUPPLICANT_INTERFACE_BSS_REMOVED,
370  		                  G_CALLBACK (supplicant_iface_bss_removed_cb),
371  		                  self);
372  		g_signal_connect (priv->supplicant.iface,
373  		                  NM_SUPPLICANT_INTERFACE_SCAN_DONE,
374  		                  G_CALLBACK (supplicant_iface_scan_done_cb),
375  		                  self);
376  		g_signal_connect (priv->supplicant.iface,
377  		                  "notify::scanning",
378  		                  G_CALLBACK (supplicant_iface_notify_scanning_cb),
379  		                  self);
380  	
381  		return TRUE;
382  	}
383  	
384  	static void
385  	remove_supplicant_interface_error_handler (NMDeviceWifi *self)
386  	{
387  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
388  	
389  		if (!priv->supplicant.iface)
390  			return;
391  	
392  		if (priv->supplicant.iface_error_id > 0) {
393  			g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
394  			priv->supplicant.iface_error_id = 0;
395  		}
396  	
397  		if (priv->supplicant.iface_con_error_cb_id > 0) {
398  			g_source_remove (priv->supplicant.iface_con_error_cb_id);
399  			priv->supplicant.iface_con_error_cb_id = 0;
400  		}
401  	}
402  	
403  	static void
404  	supplicant_interface_release (NMDeviceWifi *self)
405  	{
406  		NMDeviceWifiPrivate *priv;
407  	
408  		g_return_if_fail (self != NULL);
409  	
410  		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
411  	
412  		cancel_pending_scan (self);
413  	
414  		/* Reset the scan interval to be pretty frequent when disconnected */
415  		priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
416  		nm_log_dbg (LOGD_WIFI_SCAN, "(%s): reset scanning interval to %d seconds",
417  		            nm_device_get_iface (NM_DEVICE (self)),
418  		            priv->scan_interval);
419  	
420  		remove_supplicant_interface_error_handler (self);
421  	
422  		if (priv->scanlist_cull_id) {
423  			g_source_remove (priv->scanlist_cull_id);
424  			priv->scanlist_cull_id = 0;
425  		}
426  	
427  		if (priv->supplicant.iface) {
428  			/* Clear supplicant interface signal handlers */
429  			g_signal_handlers_disconnect_matched (priv->supplicant.iface, G_SIGNAL_MATCH_DATA,
430  			                                      0, 0, NULL, NULL, self);
431  	
432  			/* Tell the supplicant to disconnect from the current AP */
433  			nm_supplicant_interface_disconnect (priv->supplicant.iface);
434  	
435  			nm_supplicant_manager_iface_release (priv->supplicant.mgr, priv->supplicant.iface);
436  			priv->supplicant.iface = NULL;
437  		}
438  	}
439  	
440  	static NMAccessPoint *
441  	get_ap_by_path (NMDeviceWifi *self, const char *path)
442  	{
443  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
444  		GSList *iter;
445  	
446  		for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
447  			if (g_strcmp0 (path, nm_ap_get_dbus_path (NM_AP (iter->data))) == 0)
448  				return NM_AP (iter->data);
449  		}
450  		return NULL;
451  	}
452  	
453  	static NMAccessPoint *
454  	get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path)
455  	{
456  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
457  		GSList *iter;
458  	
459  		for (iter = priv->ap_list; iter && path; iter = g_slist_next (iter)) {
460  			if (g_strcmp0 (path, nm_ap_get_supplicant_path (NM_AP (iter->data))) == 0)
461  				return NM_AP (iter->data);
462  		}
463  		return NULL;
464  	}
465  	
466  	static NMAccessPoint *
467  	get_active_ap (NMDeviceWifi *self,
468  	               NMAccessPoint *ignore_ap,
469  	               gboolean match_hidden)
470  	{
471  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
472  		const char *iface = nm_device_get_iface (NM_DEVICE (self));
473  		struct ether_addr bssid;
474  		GByteArray *ssid;
475  		GSList *iter;
476  		int i = 0;
477  		NMAccessPoint *match_nofreq = NULL, *active_ap = NULL;
478  		gboolean found_a_band = FALSE;
479  		gboolean found_bg_band = FALSE;
480  		NM80211Mode devmode;
481  		guint32 devfreq;
482  	
483  		wifi_utils_get_bssid (priv->wifi_data, &bssid);
484  		nm_log_dbg (LOGD_WIFI, "(%s): active BSSID: %02x:%02x:%02x:%02x:%02x:%02x",
485  		            iface,
486  		            bssid.ether_addr_octet[0], bssid.ether_addr_octet[1],
487  		            bssid.ether_addr_octet[2], bssid.ether_addr_octet[3],
488  		            bssid.ether_addr_octet[4], bssid.ether_addr_octet[5]);
489  	
490  		if (!nm_ethernet_address_is_valid (&bssid))
491  			return NULL;
492  	
493  		ssid = wifi_utils_get_ssid (priv->wifi_data);
494  		nm_log_dbg (LOGD_WIFI, "(%s): active SSID: %s%s%s",
495  		            iface,
496  		            ssid ? "'" : "",
497  		            ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
498  		            ssid ? "'" : "");
499  	
500  		devmode = wifi_utils_get_mode (priv->wifi_data);
501  		devfreq = wifi_utils_get_freq (priv->wifi_data);
502  	
503  		/* When matching hidden APs, do a second pass that ignores the SSID check,
504  		 * because NM might not yet know the SSID of the hidden AP in the scan list
505  		 * and therefore it won't get matched the first time around.
506  		 */
507  		while (i++ < (match_hidden ? 2 : 1)) {
508  			nm_log_dbg (LOGD_WIFI, "  Pass #%d %s", i, i > 1 ? "(ignoring SSID)" : "");
509  	
510  			/* Find this SSID + BSSID in the device's AP list */
511  			for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
512  				NMAccessPoint *ap = NM_AP (iter->data);
513  				const struct ether_addr	*ap_bssid = nm_ap_get_address (ap);
514  				const GByteArray *ap_ssid = nm_ap_get_ssid (ap);
515  				NM80211Mode apmode;
516  				guint32 apfreq;
517  	
518  				nm_log_dbg (LOGD_WIFI, "    AP: %s%s%s  %02x:%02x:%02x:%02x:%02x:%02x",
519  				            ap_ssid ? "'" : "",
520  				            ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)",
521  				            ap_ssid ? "'" : "",
522  				            ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1],
523  				            ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3],
524  				            ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]);
525  	
526  				if (ignore_ap && (ap == ignore_ap)) {
527  					nm_log_dbg (LOGD_WIFI, "      ignored");
528  					continue;
529  				}
530  	
531  				if (memcmp (bssid.ether_addr_octet, ap_bssid->ether_addr_octet, ETH_ALEN)) {
532  					nm_log_dbg (LOGD_WIFI, "      BSSID mismatch");
533  					continue;
534  				}
535  	
536  				if ((i == 0) && !nm_utils_same_ssid (ssid, ap_ssid, TRUE)) {
537  					nm_log_dbg (LOGD_WIFI, "      SSID mismatch");
538  					continue;
539  				}
540  	
541  				apmode = nm_ap_get_mode (ap);
542  				if (devmode != apmode) {
543  					nm_log_dbg (LOGD_WIFI, "      mode mismatch (device %d, ap %d)",
544  					            devmode, apmode);
545  					continue;
546  				}
547  	
548  				apfreq = nm_ap_get_freq (ap);
549  				if (devfreq != apfreq) {
550  					nm_log_dbg (LOGD_WIFI, "      frequency mismatch (device %u, ap %u)",
551  					            devfreq, apfreq);
552  	
553  					if (match_nofreq == NULL)
554  						match_nofreq = ap;
555  	
556  					if (apfreq > 4000)
557  						found_a_band = TRUE;
558  					else if (apfreq > 2000)
559  						found_bg_band = TRUE;
560  					continue;
561  				}
562  	
563  				// FIXME: handle security settings here too
564  				nm_log_dbg (LOGD_WIFI, "      matched");
565  				active_ap = ap;
566  				goto done;
567  			}
568  		}
569  	
570  		/* Some proprietary drivers (wl.o) report tuned frequency (like when
571  		 * scanning) instead of the associated AP's frequency.  This is a great
572  		 * example of how WEXT is underspecified.  We use frequency to find the
573  		 * active AP in the scan list because some configurations use the same
574  		 * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to
575  		 * make sure we get the right AP in the right band.  This configuration
576  		 * is uncommon though, and the frequency check penalizes closed drivers we
577  		 * can't fix.  Because we're not total dicks, ignore the frequency condition
578  		 * if the associated BSSID/SSID exists only in one band since that's most
579  		 * likely the AP we want.  Sometimes wl.o returns a frequency of 0, so if
580  		 * we can't match the AP based on frequency at all, just give up.
581  		 */
582  		if (match_nofreq && ((found_a_band != found_bg_band) || (devfreq == 0))) {
583  			const struct ether_addr	*ap_bssid = nm_ap_get_address (match_nofreq);
584  			const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq);
585  	
586  			nm_log_dbg (LOGD_WIFI, "    matched %s%s%s  %02x:%02x:%02x:%02x:%02x:%02x",
587  			            ap_ssid ? "'" : "",
588  			            ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)",
589  			            ap_ssid ? "'" : "",
590  			            ap_bssid->ether_addr_octet[0], ap_bssid->ether_addr_octet[1],
591  			            ap_bssid->ether_addr_octet[2], ap_bssid->ether_addr_octet[3],
592  			            ap_bssid->ether_addr_octet[4], ap_bssid->ether_addr_octet[5]);
593  	
594  			active_ap = match_nofreq;
595  		}
596  	
597  		nm_log_dbg (LOGD_WIFI, "  No matching AP found.");
598  	
599  	done:
600  		if (ssid)
601  			g_byte_array_free (ssid, TRUE);
602  		return active_ap;
603  	}
604  	
605  	static void
606  	update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap)
607  	{
608  		NMActRequest *req;
609  		NMConnection *connection;
610  	
611  		g_return_if_fail (NM_IS_DEVICE_WIFI (self));
612  		
613  		if (ap == NULL)
614  			return;
615  	
616  		/* Don't cache the BSSID for Ad-Hoc APs */
617  		if (nm_ap_get_mode (ap) != NM_802_11_MODE_INFRA)
618  			return;
619  	
620  		if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) {
621  			req = nm_device_get_act_request (NM_DEVICE (self));
622  			if (req) {
623  				connection = nm_act_request_get_connection (req);
624  				nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection),
625  				                                       nm_ap_get_address (ap));
626  			}
627  		}
628  	}
629  	
630  	static void
631  	set_active_ap (NMDeviceWifi *self, NMAccessPoint *new_ap)
632  	{
633  		NMDeviceWifiPrivate *priv;
634  		char *old_path = NULL;
635  		NMAccessPoint *old_ap;
636  	
637  		g_return_if_fail (NM_IS_DEVICE_WIFI (self));
638  	
639  		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
640  		old_ap = priv->current_ap;
641  	
642  		if (old_ap) {
643  			old_path = g_strdup (nm_ap_get_dbus_path (old_ap));
644  			priv->current_ap = NULL;
645  		}
646  	
647  		if (new_ap) {
648  			priv->current_ap = g_object_ref (new_ap);
649  	
650  			/* Move the current AP to the front of the scan list.  Since we
651  			 * do a lot of searches looking for the current AP, it saves
652  			 * time to have it in front.
653  			 */
654  			priv->ap_list = g_slist_remove (priv->ap_list, new_ap);
655  			priv->ap_list = g_slist_prepend (priv->ap_list, new_ap);
656  	
657  			/* Update seen BSSIDs cache */
658  			update_seen_bssids_cache (self, priv->current_ap);
659  		}
660  	
661  		/* Unref old AP here to ensure object lives if new_ap == old_ap */
662  		if (old_ap)
663  			g_object_unref (old_ap);
664  	
665  		/* Only notify if it's really changed */
666  		if (   (!old_path && new_ap)
667  		    || (old_path && !new_ap)
668  		    || (old_path && new_ap && strcmp (old_path, nm_ap_get_dbus_path (new_ap))))
669  			g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
670  	
671  		g_free (old_path);
672  	}
673  	
674  	/* Called both as a GSourceFunc and standalone */
675  	static gboolean
676  	periodic_update (gpointer user_data)
677  	{
678  		NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
679  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
680  		NMAccessPoint *new_ap;
681  		guint32 new_rate, percent;
682  		NMDeviceState state;
683  		guint32 supplicant_state;
684  	
685  		/* BSSID and signal strength have meaningful values only if the device
686  		 * is activated and not scanning.
687  		 */
688  		state = nm_device_get_state (NM_DEVICE (self));
689  		if (state != NM_DEVICE_STATE_ACTIVATED)
690  			return TRUE;
691  	
692  		/* Only update current AP if we're actually talking to something, otherwise
693  		 * assume the old one (if any) is still valid until we're told otherwise or
694  		 * the connection fails.
695  		 */
696  		supplicant_state = nm_supplicant_interface_get_state (priv->supplicant.iface);
697  		if (   supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING
698  		    || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED
699  		    || nm_supplicant_interface_get_scanning (priv->supplicant.iface))
700  			return TRUE;
701  	
702  		/* In AP mode we currently have nothing to do. */
703  		if (priv->mode == NM_802_11_MODE_AP)
704  			return TRUE;
705  	
706  		/* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where
707  		 * multiple IBSS stations using the same SSID will eventually switch to
708  		 * using the same BSSID to avoid network segmentation.  When this happens,
709  		 * the card's reported BSSID will change, but the new BSS may not
710  		 * be in the scan list, since scanning isn't done in ad-hoc mode for
711  		 * various reasons.  So pull the BSSID from the card and update the
712  		 * current AP with it, if the current AP is adhoc.
713  		 */
714  		if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) {
715  			struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
716  	
717  			wifi_utils_get_bssid (priv->wifi_data, &bssid);
718  			/* 0x02 means "locally administered" and should be OR-ed into
719  			 * the first byte of IBSS BSSIDs.
720  			 */
721  			if (   (bssid.ether_addr_octet[0] & 0x02)
722  			    && nm_ethernet_address_is_valid (&bssid))
723  				nm_ap_set_address (priv->current_ap, &bssid);
724  		}
725  	
726  		new_ap = get_active_ap (self, NULL, FALSE);
727  		if (new_ap) {
728  			/* Try to smooth out the strength.  Atmel cards, for example, will give no strength
729  			 * one second and normal strength the next.
730  			 */
731  			percent = wifi_utils_get_qual (priv->wifi_data);
(1) Event unsigned_compare: This greater-than-or-equal-to-zero comparison of an unsigned value is always true. "percent >= 0U".
732  			if (percent >= 0 || ++priv->invalid_strength_counter > 3) {
733  				nm_ap_set_strength (new_ap, (gint8) percent);
734  				priv->invalid_strength_counter = 0;
735  			}
736  		}
737  	
738  		if ((new_ap || priv->current_ap) && (new_ap != priv->current_ap)) {
739  			const struct ether_addr *new_bssid = NULL;
740  			const GByteArray *new_ssid = NULL;
741  			const struct ether_addr *old_bssid = NULL;
742  			const GByteArray *old_ssid = NULL;
743  			char *old_addr = NULL, *new_addr = NULL;
744  	
745  			if (new_ap) {
746  				new_bssid = nm_ap_get_address (new_ap);
747  				new_addr = nm_utils_hwaddr_ntoa (new_bssid, ARPHRD_ETHER);
748  				new_ssid = nm_ap_get_ssid (new_ap);
749  			}
750  	
751  			if (priv->current_ap) {
752  				old_bssid = nm_ap_get_address (priv->current_ap);
753  				old_addr = nm_utils_hwaddr_ntoa (old_bssid, ARPHRD_ETHER);
754  				old_ssid = nm_ap_get_ssid (priv->current_ap);
755  			}
756  	
757  			nm_log_info (LOGD_WIFI, "(%s): roamed from BSSID %s (%s) to %s (%s)",
758  			             nm_device_get_iface (NM_DEVICE (self)),
759  			             old_addr ? old_addr : "(none)",
760  			             old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)",
761  			             new_addr ? new_addr : "(none)",
762  			             new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)");
763  			g_free (old_addr);
764  			g_free (new_addr);
765  	
766  			set_active_ap (self, new_ap);
767  		}
768  	
769  		new_rate = wifi_utils_get_rate (priv->wifi_data);
770  		if (new_rate != priv->rate) {
771  			priv->rate = new_rate;
772  			g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_BITRATE);
773  		}
774  	
775  		return TRUE;
776  	}
777  	
778  	static gboolean
779  	bring_up (NMDevice *device, gboolean *no_firmware)
780  	{
781  		if (!NM_DEVICE_WIFI_GET_PRIVATE (device)->enabled)
782  			return FALSE;
783  	
784  		return NM_DEVICE_CLASS (nm_device_wifi_parent_class)->bring_up (device, no_firmware);
785  	}
786  	
787  	static void
788  	remove_access_point (NMDeviceWifi *device,
789  	                     NMAccessPoint *ap,
790  	                     gboolean recheck_available_connections)
791  	{
792  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
793  	
794  		g_signal_emit (device, signals[ACCESS_POINT_REMOVED], 0, ap);
795  		priv->ap_list = g_slist_remove (priv->ap_list, ap);
796  		g_object_unref (ap);
797  	
798  		if (recheck_available_connections)
799  			nm_device_recheck_available_connections (NM_DEVICE (device));
800  	}
801  	
802  	static void
803  	remove_all_aps (NMDeviceWifi *self)
804  	{
805  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
806  	
807  		/* Remove outdated APs */
808  		while (g_slist_length (priv->ap_list)) {
809  			NMAccessPoint *ap = NM_AP (priv->ap_list->data);
810  			remove_access_point (self, ap, FALSE);
811  		}
812  		g_slist_free (priv->ap_list);
813  		priv->ap_list = NULL;
814  	
815  		nm_device_recheck_available_connections (NM_DEVICE (self));
816  	}
817  	
818  	static void
819  	deactivate (NMDevice *dev)
820  	{
821  		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
822  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
823  		NMAccessPoint *orig_ap = nm_device_wifi_get_activation_ap (self);
824  		NMActRequest *req;
825  		NMConnection *connection;
826  		NM80211Mode old_mode = priv->mode;
827  	
828  		req = nm_device_get_act_request (dev);
829  		if (req) {
830  			connection = nm_act_request_get_connection (req);
831  			/* Clear wireless secrets tries when deactivating */
832  			g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
833  		}
834  	
835  		if (priv->periodic_source_id) {
836  			g_source_remove (priv->periodic_source_id);
837  			priv->periodic_source_id = 0;
838  		}
839  	
840  		cleanup_association_attempt (self, TRUE);
841  	
842  		set_active_ap (self, NULL);
843  		priv->rate = 0;
844  	
845  		/* If the AP is 'fake', i.e. it wasn't actually found from
846  		 * a scan but the user tried to connect to it manually (maybe it
847  		 * was non-broadcasting or something) get rid of it, because 'fake'
848  		 * APs should only live for as long as we're connected to them.  Fixes
849  		 * a bug where user-created Ad-Hoc APs are never removed from the scan
850  		 * list, because scanning is disabled while in Ad-Hoc mode (for stability),
851  		 * and thus the AP culling never happens. (bgo #569241)
852  		 */
853  		if (orig_ap && nm_ap_get_fake (orig_ap))
854  		    remove_access_point (self, orig_ap, TRUE);
855  	
856  		/* Reset MAC address back to initial address */
857  		nm_device_set_hw_addr (dev, priv->initial_hw_addr, "reset", LOGD_WIFI);
858  	
859  		/* Ensure we're in infrastructure mode after deactivation; some devices
860  		 * (usually older ones) don't scan well in adhoc mode.
861  		 */
862  		if (wifi_utils_get_mode (priv->wifi_data) != NM_802_11_MODE_INFRA) {
863  			nm_device_take_down (NM_DEVICE (self), TRUE);
864  			wifi_utils_set_mode (priv->wifi_data, NM_802_11_MODE_INFRA);
865  			nm_device_bring_up (NM_DEVICE (self), TRUE, NULL);
866  		}
867  	
868  		if (priv->mode != NM_802_11_MODE_INFRA) {
869  			priv->mode = NM_802_11_MODE_INFRA;
870  			g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
871  		}
872  	
873  		/* Ensure we trigger a scan after deactivating a Hotspot */
874  		if (old_mode == NM_802_11_MODE_AP) {
875  			cancel_pending_scan (self);
876  			request_wireless_scan (self);
877  		}
878  	}
879  	
880  	static gboolean
881  	is_adhoc_wpa (NMConnection *connection)
882  	{
883  		NMSettingWireless *s_wifi;
884  		NMSettingWirelessSecurity *s_wsec;
885  		const char *mode, *key_mgmt;
886  	
887  		/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
888  		 * and turns them into open networks.  It's been this way since at least
889  		 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
890  		 */
891  	
892  		s_wifi = nm_connection_get_setting_wireless (connection);
893  		g_return_val_if_fail (s_wifi != NULL, FALSE);
894  	
895  		mode = nm_setting_wireless_get_mode (s_wifi);
896  		if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) != 0)
897  			return FALSE;
898  	
899  		s_wsec = nm_connection_get_setting_wireless_security (connection);
900  		if (!s_wsec)
901  			return FALSE;
902  	
903  		key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
904  		if (g_strcmp0 (key_mgmt, "wpa-none") != 0)
905  			return FALSE;
906  	
907  		return TRUE;
908  	}
909  	
910  	static gboolean
911  	check_connection_compatible (NMDevice *device,
912  	                             NMConnection *connection,
913  	                             GError **error)
914  	{
915  		NMDeviceWifi *self = NM_DEVICE_WIFI (device);
916  		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
917  		NMSettingConnection *s_con;
918  		NMSettingWireless *s_wireless;
919  		const GByteArray *mac;
920  		const GSList *mac_blacklist, *mac_blacklist_iter;
921  		const char *mode;
922  	
923  		if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->check_connection_compatible (device, connection, error))
924  			return FALSE;
925  	
926  		s_con = nm_connection_get_setting_connection (connection);
927  		g_assert (s_con);
928  	
929  		if (strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_WIRELESS_SETTING_NAME)) {
930  			g_set_error (error,
931  			             NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_NOT_WIRELESS,
932  			             "The connection was not a WiFi connection.");
933  			return FALSE;
934  		}
935  	
936  		s_wireless = nm_connection_get_setting_wireless (connection);
937  		if (!s_wireless) {
938  			g_set_error (error,
939  			             NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INVALID,
940  			             "The connection was not a valid WiFi connection.");
941  			return FALSE;
942  		}
943  	
944  	
945  		mac = nm_setting_wireless_get_mac_address (s_wireless);
946  		if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) {
947  			g_set_error (error,
948  			             NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE,
949  			             "The connection's MAC address did not match this device.");
950  			return FALSE;
951  		}
952  	
953  		/* Check for MAC address blacklist */
954  		mac_blacklist = nm_setting_wireless_get_mac_address_blacklist (s_wireless);
955  		for (mac_blacklist_iter = mac_blacklist; mac_blacklist_iter;
956  		     mac_blacklist_iter = g_slist_next (mac_blacklist_iter)) {
957  			struct ether_addr addr;
958  	
959  			if (!ether_aton_r (mac_blacklist_iter->data, &addr)) {
960  				g_warn_if_reached ();
961  				continue;
962  			}
963  			if (memcmp (&addr, &priv->perm_hw_addr, ETH_ALEN) == 0) {
964  				g_set_error (error,
965  				             NM_WIFI_ERROR, NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE,
966  				             "The connection's MAC address (%s) is blacklisted in %s.",
967  				             (char *) mac_blacklist_iter->data, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
968  				return FALSE;
969  			}
970  		}
971  	
972  		if (is_adhoc_wpa (connection)) {
973  			g_set_error_literal (error,
974  			                     NM_WIFI_ERROR,
975  			                     NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE,
976  			                     "WPA Ad-Hoc disabled due to kernel bugs");
977  			return FALSE;
978  		}
979  	
980  		/* Early exit if supplicant or device doesn't support requested mode */
981  		mode = nm_setting_wireless_get_mode (s_wireless);
982  		if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) {
983  			if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) {
984  				g_set_error_literal (error,
985  				                     NM_WIFI_ERROR,
986  				                     NM_WIFI_ERROR_ADHOC_MODE_UNSUPPORTED,
987  				                     "Ad-Hoc mode is not supported by this device.");
988  				return FALSE;
989  			}
990  		} else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) {
991  			if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) {
992  				g_set_error_literal (error,
993  				                     NM_WIFI_ERROR,
994  				                     NM_WIFI_ERROR_AP_MODE_UNSUPPORTED,
995  				                     "Access Point (AP) mode is not supported by this device.");
996  				return FALSE;
997  			}
998  	
999  			if (priv->supplicant.iface) {
1000 				switch (nm_supplicant_interface_get_ap_support (priv->supplicant.iface)) {
1001 				case AP_SUPPORT_NO:
1002 					g_set_error_literal (error,
1003 					                     NM_WIFI_ERROR,
1004 					                     NM_WIFI_ERROR_AP_MODE_UNSUPPORTED,
1005 					                     "Access Point (AP) mode is not supported by the supplicant.");
1006 					return FALSE;
1007 				case AP_SUPPORT_YES:
1008 				case AP_SUPPORT_UNKNOWN:
1009 				default:
1010 					break;
1011 				}
1012 			}
1013 		}
1014 	
1015 		// FIXME: check channel/freq/band against bands the hardware supports
1016 		// FIXME: check encryption against device capabilities
1017 		// FIXME: check bitrate against device capabilities
1018 	
1019 		return TRUE;
1020 	}
1021 	
1022 	
1023 	static gboolean
1024 	check_connection_available (NMDevice *device, NMConnection *connection)
1025 	{
1026 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
1027 		NMSettingWireless *s_wifi;
1028 		const char *mode;
1029 		GSList *ap_iter = NULL;
1030 	
1031 		s_wifi = nm_connection_get_setting_wireless (connection);
1032 	
1033 		/* Ad-Hoc and AP connections are always available because they may be
1034 		 * started at any time.
1035 		 */
1036 		mode = nm_setting_wireless_get_mode (s_wifi);
1037 		if (   g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0
1038 		    || g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0)
1039 			return TRUE;
1040 	
1041 		/* Hidden SSIDs obviously don't always appear in the scan list either */
1042 		if (nm_setting_wireless_get_hidden (s_wifi))
1043 			return TRUE;
1044 	
1045 		/* check if its visible */
1046 		for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) {
1047 			if (nm_ap_check_compatible (NM_AP (ap_iter->data), connection))
1048 				return TRUE;
1049 		}
1050 	
1051 		return FALSE;
1052 	}
1053 	
1054 	/*
1055 	 * List of manufacturer default SSIDs that are often unchanged by users.
1056 	 *
1057 	 * NOTE: this list should *not* contain networks that you would like to
1058 	 * automatically roam to like "Starbucks" or "AT&T" or "T-Mobile HotSpot".
1059 	 */
1060 	static const char *
1061 	manf_defaults[] = {
1062 		"linksys",
1063 		"linksys-a",
1064 		"linksys-g",
1065 		"default",
1066 		"belkin54g",
1067 		"NETGEAR",
1068 		"o2DSL",
1069 		"WLAN",
1070 		"ALICE-WLAN",
1071 		"Speedport W 501V",
1072 	};
1073 	
1074 	#define ARRAY_SIZE(a)  (sizeof (a) / sizeof (a[0]))
1075 	
1076 	static gboolean
1077 	is_manf_default_ssid (const GByteArray *ssid)
1078 	{
1079 		int i;
1080 	
1081 		for (i = 0; i < ARRAY_SIZE (manf_defaults); i++) {
1082 			if (ssid->len == strlen (manf_defaults[i])) {
1083 				if (memcmp (manf_defaults[i], ssid->data, ssid->len) == 0)
1084 					return TRUE;
1085 			}
1086 		}
1087 		return FALSE;
1088 	}
1089 	
1090 	static gboolean
1091 	complete_connection (NMDevice *device,
1092 	                     NMConnection *connection,
1093 	                     const char *specific_object,
1094 	                     const GSList *existing_connections,
1095 	                     GError **error)
1096 	{
1097 		NMDeviceWifi *self = NM_DEVICE_WIFI (device);
1098 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1099 		NMSettingWireless *s_wifi;
1100 		NMSettingWirelessSecurity *s_wsec;
1101 		NMSetting8021x *s_8021x;
1102 		const GByteArray *setting_mac;
1103 		char *format, *str_ssid = NULL;
1104 		NMAccessPoint *ap = NULL;
1105 		const GByteArray *ssid = NULL;
1106 		GSList *iter;
1107 	
1108 		s_wifi = nm_connection_get_setting_wireless (connection);
1109 		s_wsec = nm_connection_get_setting_wireless_security (connection);
1110 		s_8021x = nm_connection_get_setting_802_1x (connection);
1111 	
1112 		if (!specific_object) {
1113 			/* If not given a specific object, we need at minimum an SSID */
1114 			if (!s_wifi) {
1115 				g_set_error_literal (error,
1116 				                     NM_WIFI_ERROR,
1117 				                     NM_WIFI_ERROR_CONNECTION_INVALID,
1118 				                     "A 'wireless' setting is required if no AP path was given.");
1119 				return FALSE;
1120 			}
1121 	
1122 			ssid = nm_setting_wireless_get_ssid (s_wifi);
1123 			if (!ssid || !ssid->len) {
1124 				g_set_error_literal (error,
1125 				                     NM_WIFI_ERROR,
1126 				                     NM_WIFI_ERROR_CONNECTION_INVALID,
1127 				                     "A 'wireless' setting with a valid SSID is required if no AP path was given.");
1128 				return FALSE;
1129 			}
1130 	
1131 			/* Find a compatible AP in the scan list */
1132 			for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
1133 				if (nm_ap_check_compatible (NM_AP (iter->data), connection)) {
1134 					ap = NM_AP (iter->data);
1135 					break;
1136 				}
1137 			}
1138 	
1139 			/* If we still don't have an AP, then the WiFI settings needs to be
1140 			 * fully specified by the client.  Might not be able to find an AP
1141 			 * if the network isn't broadcasting the SSID for example.
1142 			 */
1143 			if (!ap) {
1144 				GSList *settings = NULL;
1145 				gboolean valid;
1146 	
1147 				settings = g_slist_prepend (settings, s_wifi);
1148 				if (s_wsec)
1149 					settings = g_slist_prepend (settings, s_wsec);
1150 				if (s_8021x)
1151 					settings = g_slist_prepend (settings, s_8021x);
1152 				valid = nm_setting_verify (NM_SETTING (s_wifi), settings, error);
1153 				g_slist_free (settings);
1154 				if (!valid)
1155 					return FALSE;
1156 			}
1157 		} else {
1158 			ap = get_ap_by_path (self, specific_object);
1159 			if (!ap) {
1160 				g_set_error (error,
1161 				             NM_WIFI_ERROR,
1162 				             NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND,
1163 				             "The access point %s was not in the scan list.",
1164 				             specific_object);
1165 				return FALSE;
1166 			}
1167 		}
1168 	
1169 		/* Add a wifi setting if one doesn't exist yet */
1170 		if (!s_wifi) {
1171 			s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
1172 			nm_connection_add_setting (connection, NM_SETTING (s_wifi));
1173 		}
1174 	
1175 		if (ap) {
1176 			ssid = nm_ap_get_ssid (ap);
1177 	
1178 			if (ssid == NULL) {
1179 				/* The AP must be hidden.  Connecting to a WiFi AP requires the SSID
1180 				 * as part of the initial handshake, so check the connection details
1181 				 * for the SSID.  The AP object will still be used for encryption
1182 				 * settings and such.
1183 				 */
1184 				ssid = nm_setting_wireless_get_ssid (s_wifi);
1185 			}
1186 	
1187 			if (ssid == NULL) {
1188 				/* If there's no SSID on the AP itself, and no SSID in the
1189 				 * connection data, then we cannot connect at all.  Return an error.
1190 				 */
1191 				g_set_error_literal (error,
1192 				                     NM_WIFI_ERROR,
1193 				                     NM_WIFI_ERROR_CONNECTION_INVALID,
1194 				                     "A 'wireless' setting with a valid SSID is required for hidden access points.");
1195 				return FALSE;
1196 			}
1197 	
1198 			/* If the SSID is a well-known SSID, lock the connection to the AP's
1199 			 * specific BSSID so NM doesn't autoconnect to some random wifi net.
1200 			 */
1201 			if (!nm_ap_complete_connection (ap,
1202 			                                connection,
1203 			                                is_manf_default_ssid (ssid),
1204 			                                error))
1205 				return FALSE;
1206 		}
1207 	
1208 		/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
1209 		 * and turns them into open networks.  It's been this way since at least
1210 		 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
1211 		 */
1212 		if (is_adhoc_wpa (connection)) {
1213 			g_set_error_literal (error,
1214 			                     NM_SETTING_WIRELESS_ERROR,
1215 			                     NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
1216 			                     "WPA Ad-Hoc disabled due to kernel bugs");
1217 			return FALSE;
1218 		}
1219 	
1220 		g_assert (ssid);
1221 		str_ssid = nm_utils_ssid_to_utf8 (ssid);
1222 		format = g_strdup_printf ("%s %%d", str_ssid);
1223 	
1224 		nm_utils_complete_generic (connection,
1225 		                           NM_SETTING_WIRELESS_SETTING_NAME,
1226 		                           existing_connections,
1227 		                           format,
1228 		                           str_ssid,
1229 		                           TRUE);
1230 		g_free (str_ssid);
1231 		g_free (format);
1232 	
1233 		setting_mac = nm_setting_wireless_get_mac_address (s_wifi);
1234 		if (setting_mac) {
1235 			/* Make sure the setting MAC (if any) matches the device's permanent MAC */
1236 			if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) {
1237 				g_set_error (error,
1238 				             NM_SETTING_WIRELESS_ERROR,
1239 				             NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY,
1240 				             NM_SETTING_WIRELESS_MAC_ADDRESS);
1241 				return FALSE;
1242 			}
1243 		} else {
1244 			GByteArray *mac;
1245 			const guint8 null_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
1246 	
1247 			/* Lock the connection to this device by default if it uses a
1248 			 * permanent MAC address (ie not a 'locally administered' one)
1249 			 */
1250 			if (   !(priv->perm_hw_addr[0] & 0x02)
1251 			    && memcmp (priv->perm_hw_addr, null_mac, ETH_ALEN)) {
1252 				mac = g_byte_array_sized_new (ETH_ALEN);
1253 				g_byte_array_append (mac, priv->perm_hw_addr, ETH_ALEN);
1254 				g_object_set (G_OBJECT (s_wifi), NM_SETTING_WIRELESS_MAC_ADDRESS, mac, NULL);
1255 				g_byte_array_free (mac, TRUE);
1256 			}
1257 		}
1258 	
1259 		return TRUE;
1260 	}
1261 	
1262 	static gboolean
1263 	is_available (NMDevice *dev)
1264 	{
1265 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
1266 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1267 		NMSupplicantInterface *sup_iface;
1268 		guint32 state;
1269 	
1270 		if (!priv->enabled) {
1271 			nm_log_dbg (LOGD_WIFI, "(%s): not available because not enabled",
1272 			            nm_device_get_iface (dev));
1273 			return FALSE;
1274 		}
1275 	
1276 		sup_iface = priv->supplicant.iface;
1277 		if (!sup_iface) {
1278 			nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant not running",
1279 			            nm_device_get_iface (dev));
1280 			return FALSE;
1281 		}
1282 	
1283 		state = nm_supplicant_interface_get_state (sup_iface);
1284 		if (   state < NM_SUPPLICANT_INTERFACE_STATE_READY
1285 		    || state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) {
1286 			nm_log_dbg (LOGD_WIFI, "(%s): not available because supplicant interface not ready",
1287 			            nm_device_get_iface (dev));
1288 			return FALSE;
1289 		}
1290 	
1291 		return TRUE;
1292 	}
1293 	
1294 	static gboolean
1295 	can_auto_connect (NMDevice *dev,
1296 	                  NMConnection *connection,
1297 	                  char **specific_object)
1298 	{
1299 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
1300 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1301 		GSList *ap_iter;
1302 		const char *method = NULL;
1303 		guint64 timestamp = 0;
1304 	
1305 		if (!NM_DEVICE_CLASS (nm_device_wifi_parent_class)->can_auto_connect (dev, connection, specific_object))
1306 			return FALSE;
1307 	
1308 		/* Don't autoconnect to networks that have been tried at least once
1309 		 * but haven't been successful, since these are often accidental choices
1310 		 * from the menu and the user may not know the password.
1311 		 */
1312 		if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), &timestamp)) {
1313 			if (timestamp == 0)
1314 				return FALSE;
1315 		}
1316 	
1317 		/* Use the connection if it's a shared connection */
1318 		method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
1319 		if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
1320 			return TRUE;
1321 	
1322 		for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) {
1323 			NMAccessPoint *ap = NM_AP (ap_iter->data);
1324 	
1325 			if (nm_ap_check_compatible (ap, connection)) {
1326 				/* All good; connection is usable */
1327 				*specific_object = (char *) nm_ap_get_dbus_path (ap);
1328 				return TRUE;
1329 			}
1330 		}
1331 	
1332 		return FALSE;
1333 	}
1334 	
1335 	static void
1336 	ap_list_dump (NMDeviceWifi *self)
1337 	{
1338 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1339 		GSList * elt;
1340 		int i = 0;
1341 	
1342 		g_return_if_fail (NM_IS_DEVICE_WIFI (self));
1343 	
1344 		nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list:");
1345 		for (elt = priv->ap_list; elt; elt = g_slist_next (elt), i++) {
1346 			NMAccessPoint * ap = NM_AP (elt->data);
1347 			nm_ap_dump (ap, "List AP: ");
1348 		}
1349 		nm_log_dbg (LOGD_WIFI_SCAN, "Current AP list: done");
1350 	}
1351 	
1352 	static gboolean
1353 	impl_device_get_access_points (NMDeviceWifi *self,
1354 	                               GPtrArray **aps,
1355 	                               GError **err)
1356 	{
1357 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1358 		GSList *elt;
1359 	
1360 		*aps = g_ptr_array_new ();
1361 	
1362 		for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) {
1363 			NMAccessPoint * ap = NM_AP (elt->data);
1364 	
1365 			if (nm_ap_get_ssid (ap))
1366 				g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (ap)));
1367 		}
1368 		return TRUE;
1369 	}
1370 	
1371 	static void
1372 	request_scan_cb (NMDevice *device,
1373 	                 DBusGMethodInvocation *context,
1374 	                 GError *error,
1375 	                 gpointer user_data)
1376 	{
1377 		NMDeviceWifi *self = NM_DEVICE_WIFI (device);
1378 	
1379 		if (error) {
1380 			dbus_g_method_return_error (context, error);
1381 			g_clear_error (&error);
1382 		} else if (!check_scanning_allowed (self)) {
1383 			error = g_error_new_literal (NM_WIFI_ERROR,
1384 			                             NM_WIFI_ERROR_SCAN_NOT_ALLOWED,
1385 			                             "Scanning not allowed at this time");
1386 			dbus_g_method_return_error (context, error);
1387 			g_error_free (error);
1388 		} else {
1389 			cancel_pending_scan (self);
1390 			request_wireless_scan (self);
1391 			dbus_g_method_return (context);
1392 		}
1393 	}
1394 	
1395 	static void
1396 	impl_device_request_scan (NMDeviceWifi *self,
1397 	                          GHashTable *options,
1398 	                          DBusGMethodInvocation *context)
1399 	{
1400 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1401 		NMDevice *device = NM_DEVICE (self);
1402 		time_t last_scan;
1403 		GError *error;
1404 	
1405 		if (   !priv->enabled
1406 		    || !priv->supplicant.iface
1407 		    || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED
1408 		    || nm_device_is_activating (device)) {
1409 			error = g_error_new_literal (NM_WIFI_ERROR,
1410 			                             NM_WIFI_ERROR_SCAN_NOT_ALLOWED,
1411 			                             "Scanning not allowed while unavailable or activating");
1412 			goto error;
1413 		}
1414 	
1415 		if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) {
1416 			error = g_error_new_literal (NM_WIFI_ERROR,
1417 			                             NM_WIFI_ERROR_SCAN_NOT_ALLOWED,
1418 			                             "Scanning not allowed while already scanning");
1419 			goto error;
1420 		}
1421 	
1422 		last_scan = nm_supplicant_interface_get_last_scan_time (priv->supplicant.iface);
1423 		if ((time (NULL) - last_scan) < 10) {
1424 			error = g_error_new_literal (NM_WIFI_ERROR,
1425 			                             NM_WIFI_ERROR_SCAN_NOT_ALLOWED,
1426 			                             "Scanning not allowed immediately following previous scan");
1427 			goto error;
1428 		}
1429 	
1430 		/* Ask the manager to authenticate this request for us */
1431 		g_signal_emit_by_name (device,
1432 		                       NM_DEVICE_AUTH_REQUEST,
1433 		                       context,
1434 		                       NM_AUTH_PERMISSION_NETWORK_CONTROL,
1435 		                       TRUE,
1436 		                       request_scan_cb,
1437 		                       NULL);
1438 		return;
1439 	
1440 	error:
1441 		dbus_g_method_return_error (context, error);
1442 		g_error_free (error);
1443 	}
1444 	
1445 	static gboolean
1446 	scanning_allowed (NMDeviceWifi *self)
1447 	{
1448 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1449 		guint32 sup_state;
1450 		NMActRequest *req;
1451 	
1452 		g_return_val_if_fail (priv->supplicant.iface != NULL, FALSE);
1453 	
1454 		/* Scanning not done in AP mode */
1455 		if (priv->mode == NM_802_11_MODE_AP)
1456 			return FALSE;
1457 	
1458 		switch (nm_device_get_state (NM_DEVICE (self))) {
1459 		case NM_DEVICE_STATE_UNKNOWN:
1460 		case NM_DEVICE_STATE_UNMANAGED:
1461 		case NM_DEVICE_STATE_UNAVAILABLE:
1462 		case NM_DEVICE_STATE_PREPARE:
1463 		case NM_DEVICE_STATE_CONFIG:
1464 		case NM_DEVICE_STATE_NEED_AUTH:
1465 		case NM_DEVICE_STATE_IP_CONFIG:
1466 		case NM_DEVICE_STATE_IP_CHECK:
1467 		case NM_DEVICE_STATE_SECONDARIES:
1468 		case NM_DEVICE_STATE_DEACTIVATING:
1469 			/* Don't scan when unusable or activating */
1470 			return FALSE;
1471 		case NM_DEVICE_STATE_DISCONNECTED:
1472 		case NM_DEVICE_STATE_FAILED:
1473 			/* Can always scan when disconnected */
1474 			return TRUE;
1475 		case NM_DEVICE_STATE_ACTIVATED:
1476 			/* Need to do further checks when activated */
1477 			break;
1478 		}
1479 	
1480 		/* Don't scan if the supplicant is busy */
1481 		sup_state = nm_supplicant_interface_get_state (priv->supplicant.iface);
1482 		if (   sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
1483 		    || sup_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
1484 		    || sup_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
1485 		    || sup_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
1486 		    || nm_supplicant_interface_get_scanning (priv->supplicant.iface))
1487 			return FALSE;
1488 	
1489 		req = nm_device_get_act_request (NM_DEVICE (self));
1490 		if (req) {
1491 			NMConnection *connection;
1492 			NMSettingWireless *s_wifi;
1493 			const char *ip4_method = NULL;
1494 			const GByteArray *bssid;
1495 	
1496 			/* Don't scan when a shared connection is active; it makes drivers mad */
1497 			connection = nm_act_request_get_connection (req);
1498 			ip4_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
1499 	
1500 			if (!strcmp (ip4_method, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
1501 				return FALSE;
1502 	
1503 			/* Don't scan when the connection is locked to a specifc AP, since
1504 			 * intra-ESS roaming (which requires periodic scanning) isn't being
1505 			 * used due to the specific AP lock. (bgo #513820)
1506 			 */
1507 			s_wifi = nm_connection_get_setting_wireless (connection);
1508 			g_assert (s_wifi);
1509 			bssid = nm_setting_wireless_get_bssid (s_wifi);
1510 			if (bssid && bssid->len == ETH_ALEN)
1511 				return FALSE;
1512 		}
1513 	
1514 		return TRUE;
1515 	}
1516 	
1517 	static gboolean
1518 	scanning_allowed_accumulator (GSignalInvocationHint *ihint,
1519 	                              GValue *return_accu,
1520 	                              const GValue *handler_return,
1521 	                              gpointer data)
1522 	{
1523 		if (!g_value_get_boolean (handler_return))
1524 			g_value_set_boolean (return_accu, FALSE);
1525 		return TRUE;
1526 	}
1527 	
1528 	static gboolean
1529 	check_scanning_allowed (NMDeviceWifi *self)
1530 	{
1531 		GValue instance = G_VALUE_INIT;
1532 		GValue retval = G_VALUE_INIT;
1533 	
1534 		g_value_init (&instance, G_TYPE_OBJECT);
1535 		g_value_take_object (&instance, self);
1536 	
1537 		g_value_init (&retval, G_TYPE_BOOLEAN);
1538 		g_value_set_boolean (&retval, TRUE);
1539 	
1540 		/* Use g_signal_emitv() rather than g_signal_emit() to avoid the return
1541 		 * value being changed if no handlers are connected */
1542 		g_signal_emitv (&instance, signals[SCANNING_ALLOWED], 0, &retval);
1543 	
1544 		return g_value_get_boolean (&retval);
1545 	}
1546 	
1547 	static gboolean
1548 	hidden_filter_func (NMConnectionProvider *provider,
1549 	                    NMConnection *connection,
1550 	                    gpointer user_data)
1551 	{
1552 		NMSettingWireless *s_wifi;
1553 	
1554 		s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection);
1555 		return s_wifi ? nm_setting_wireless_get_hidden (s_wifi) : FALSE;
1556 	}
1557 	
1558 	static GPtrArray *
1559 	build_hidden_probe_list (NMDeviceWifi *self)
1560 	{
1561 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1562 		guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->supplicant.iface);
1563 		NMConnectionProvider *provider = nm_device_get_connection_provider (NM_DEVICE (self));
1564 		GSList *connections, *iter;
1565 		GPtrArray *ssids = NULL;
1566 		static GByteArray *nullssid = NULL;
1567 	
1568 		/* Need at least two: wildcard SSID and one or more hidden SSIDs */
1569 		if (max_scan_ssids < 2)
1570 			return NULL;
1571 	
1572 		/* Static wildcard SSID used for every scan */
1573 		if (G_UNLIKELY (nullssid == NULL))
1574 			nullssid = g_byte_array_new ();
1575 	
1576 		connections = nm_connection_provider_get_best_connections (provider,
1577 		                                                           max_scan_ssids - 1,
1578 		                                                           NM_SETTING_WIRELESS_SETTING_NAME,
1579 		                                                           NULL,
1580 		                                                           hidden_filter_func,
1581 		                                                           NULL);
1582 		if (connections && connections->data) {
1583 			ssids = g_ptr_array_sized_new (max_scan_ssids - 1);
1584 			g_ptr_array_add (ssids, nullssid);  /* Add wildcard SSID */
1585 		}
1586 	
1587 		for (iter = connections; iter; iter = g_slist_next (iter)) {
1588 			NMConnection *connection = iter->data;
1589 			NMSettingWireless *s_wifi;
1590 			const GByteArray *ssid;
1591 	
1592 			s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection);
1593 			g_assert (s_wifi);
1594 			ssid = nm_setting_wireless_get_ssid (s_wifi);
1595 			g_assert (ssid);
1596 			g_ptr_array_add (ssids, (gpointer) ssid);
1597 		}
1598 		g_slist_free (connections);
1599 	
1600 		return ssids;
1601 	}
1602 	
1603 	static gboolean
1604 	request_wireless_scan (gpointer user_data)
1605 	{
1606 		NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
1607 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1608 		gboolean backoff = FALSE;
1609 		GPtrArray *ssids = NULL;
1610 	
1611 		if (priv->requested_scan) {
1612 			/* There's already a scan in progress */
1613 			return FALSE;
1614 		}
1615 	
1616 		if (check_scanning_allowed (self)) {
1617 			nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scanning requested",
1618 			            nm_device_get_iface (NM_DEVICE (self)));
1619 	
1620 			ssids = build_hidden_probe_list (self);
1621 	
1622 			if (nm_logging_level_enabled (LOGL_DEBUG)) {
1623 				if (ssids) {
1624 					guint i;
1625 					char *foo;
1626 	
1627 					for (i = 0; i < ssids->len; i++) {
1628 						foo = nm_utils_ssid_to_utf8 (g_ptr_array_index (ssids, i));
1629 						nm_log_dbg (LOGD_WIFI_SCAN, "(%s): (%d) probe scanning SSID '%s'",
1630 						            nm_device_get_iface (NM_DEVICE (self)),
1631 						            i, foo ? foo : "<hidden>");
1632 						g_free (foo);
1633 					}
1634 				} else {
1635 					nm_log_dbg (LOGD_WIFI_SCAN, "(%s): no SSIDs to probe scan",
1636 					            nm_device_get_iface (NM_DEVICE (self)));
1637 				}
1638 			}
1639 	
1640 			if (nm_supplicant_interface_request_scan (priv->supplicant.iface, ssids)) {
1641 				/* success */
1642 				backoff = TRUE;
1643 				priv->requested_scan = TRUE;
1644 				nm_device_add_pending_action (NM_DEVICE (self), "scan");
1645 			}
1646 	
1647 			if (ssids) {
1648 				/* Elements owned by the connections, so we don't free them here */
1649 				g_ptr_array_free (ssids, TRUE);
1650 			}
1651 		} else {
1652 			nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan requested but not allowed at this time",
1653 			            nm_device_get_iface (NM_DEVICE (self)));
1654 		}
1655 	
1656 		priv->pending_scan_id = 0;
1657 		schedule_scan (self, backoff);
1658 		return FALSE;
1659 	}
1660 	
1661 	
1662 	/*
1663 	 * schedule_scan
1664 	 *
1665 	 * Schedule a wireless scan.
1666 	 *
1667 	 */
1668 	static void
1669 	schedule_scan (NMDeviceWifi *self, gboolean backoff)
1670 	{
1671 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1672 		time_t now = time (NULL);
1673 	
1674 		/* Cancel the pending scan if it would happen later than (now + the scan_interval) */
1675 		if (priv->pending_scan_id) {
1676 			if (now + priv->scan_interval < priv->scheduled_scan_time)
1677 				cancel_pending_scan (self);
1678 		}
1679 	
1680 		if (!priv->pending_scan_id) {
1681 			guint factor = 2, next_scan = priv->scan_interval;
1682 	
1683 			if (    nm_device_is_activating (NM_DEVICE (self))
1684 			    || (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED))
1685 				factor = 1;
1686 	
1687 			priv->pending_scan_id = g_timeout_add_seconds (next_scan,
1688 			                                               request_wireless_scan,
1689 			                                               self);
1690 	
1691 			priv->scheduled_scan_time = now + priv->scan_interval;
1692 			if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) {
1693 					priv->scan_interval += (SCAN_INTERVAL_STEP / factor);
1694 					/* Ensure the scan interval will never be less than 20s... */
1695 					priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP);
1696 					/* ... or more than 120s */
1697 					priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX);
1698 			} else if (!backoff && (priv->scan_interval == 0)) {
1699 				/* Invalid combination; would cause continual rescheduling of
1700 				 * the scan and hog CPU.  Reset to something minimally sane.
1701 				 */
1702 				priv->scan_interval = 5;
1703 			}
1704 	
1705 			nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scheduled scan in %d seconds (interval now %d seconds)",
1706 			            nm_device_get_iface (NM_DEVICE (self)),
1707 			            next_scan,
1708 			            priv->scan_interval);
1709 	
1710 		}
1711 	}
1712 	
1713 	
1714 	static void
1715 	cancel_pending_scan (NMDeviceWifi *self)
1716 	{
1717 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1718 	
1719 		if (priv->pending_scan_id) {
1720 			g_source_remove (priv->pending_scan_id);
1721 			priv->pending_scan_id = 0;
1722 		}
1723 	}
1724 	
1725 	static void
1726 	supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
1727 	                               gboolean success,
1728 	                               NMDeviceWifi *self)
1729 	{
1730 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1731 	
1732 		nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan %s",
1733 		            nm_device_get_iface (NM_DEVICE (self)),
1734 		            success ? "successful" : "failed");
1735 	
1736 		schedule_scan (self, success);
1737 	
1738 		/* Ensure that old APs get removed, which otherwise only
1739 		 * happens when there are new BSSes.
1740 		 */
1741 		schedule_scanlist_cull (self);
1742 	
1743 		if (priv->requested_scan) {
1744 			priv->requested_scan = FALSE;
1745 			nm_device_remove_pending_action (NM_DEVICE (self), "scan");
1746 		}
1747 	}
1748 	
1749 	
1750 	/****************************************************************************
1751 	 * WPA Supplicant control stuff
1752 	 *
1753 	 */
1754 	
1755 	#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
1756 	#define MAC_ARG(x) ((guint8*)(x))[0],((guint8*)(x))[1],((guint8*)(x))[2],((guint8*)(x))[3],((guint8*)(x))[4],((guint8*)(x))[5]
1757 	
1758 	/*
1759 	 * merge_scanned_ap
1760 	 *
1761 	 * If there is already an entry that matches the BSSID and ESSID of the
1762 	 * AP to merge, replace that entry with the scanned AP.  Otherwise, add
1763 	 * the scanned AP to the list.
1764 	 *
1765 	 * TODO: possibly need to differentiate entries based on security too; i.e. if
1766 	 * there are two scan results with the same BSSID and SSID but different
1767 	 * security options?
1768 	 *
1769 	 */
1770 	static void
1771 	merge_scanned_ap (NMDeviceWifi *self,
1772 	                  NMAccessPoint *merge_ap)
1773 	{
1774 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1775 		NMAccessPoint *found_ap = NULL;
1776 		const GByteArray *ssid;
1777 		const struct ether_addr *bssid;
1778 		gboolean strict_match = TRUE;
1779 		NMAccessPoint *current_ap = NULL;
1780 	
1781 		/* Let the manager try to fill in the SSID from seen-bssids lists */
1782 		bssid = nm_ap_get_address (merge_ap);
1783 		ssid = nm_ap_get_ssid (merge_ap);
1784 		if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) {
1785 			/* Let the manager try to fill the AP's SSID from the database */
1786 			g_signal_emit (self, signals[HIDDEN_AP_FOUND], 0, merge_ap);
1787 	
1788 			ssid = nm_ap_get_ssid (merge_ap);
1789 			if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
1790 				/* Yay, matched it, no longer treat as hidden */
1791 				nm_log_dbg (LOGD_WIFI_SCAN, "(%s): matched hidden AP " MAC_FMT " => '%s'",
1792 				            nm_device_get_iface (NM_DEVICE (self)),
1793 				            MAC_ARG (bssid->ether_addr_octet),
1794 				            nm_utils_escape_ssid (ssid->data, ssid->len));
1795 				nm_ap_set_broadcast (merge_ap, FALSE);
1796 			} else {
1797 				/* Didn't have an entry for this AP in the database */
1798 				nm_log_dbg (LOGD_WIFI_SCAN, "(%s): failed to match hidden AP " MAC_FMT,
1799 				            nm_device_get_iface (NM_DEVICE (self)),
1800 				            MAC_ARG (bssid->ether_addr_octet));
1801 			}
1802 		}
1803 	
1804 		/* If the incoming scan result matches the hidden AP that NM is currently
1805 		 * connected to but hasn't been seen in the scan list yet, don't use
1806 		 * strict matching.  Because the capabilities of the fake AP have to be
1807 		 * constructed from the NMConnection of the activation request, they won't
1808 		 * always be the same as the capabilities of the real AP from the scan.
1809 		 */
1810 		current_ap = nm_device_wifi_get_activation_ap (self);
1811 		if (current_ap && nm_ap_get_fake (current_ap))
1812 			strict_match = FALSE;
1813 	
1814 		found_ap = get_ap_by_supplicant_path (self, nm_ap_get_supplicant_path (merge_ap));
1815 		if (!found_ap)
1816 			found_ap = nm_ap_match_in_list (merge_ap, priv->ap_list, strict_match);
1817 		if (found_ap) {
1818 			nm_log_dbg (LOGD_WIFI_SCAN, "(%s): merging AP '%s' " MAC_FMT " (%p) with existing (%p)",
1819 			            nm_device_get_iface (NM_DEVICE (self)),
1820 			            ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
1821 			            MAC_ARG (bssid->ether_addr_octet),
1822 			            merge_ap,
1823 			            found_ap);
1824 	
1825 			nm_ap_set_supplicant_path (found_ap, nm_ap_get_supplicant_path (merge_ap));
1826 			nm_ap_set_flags (found_ap, nm_ap_get_flags (merge_ap));
1827 			nm_ap_set_wpa_flags (found_ap, nm_ap_get_wpa_flags (merge_ap));
1828 			nm_ap_set_rsn_flags (found_ap, nm_ap_get_rsn_flags (merge_ap));
1829 			nm_ap_set_strength (found_ap, nm_ap_get_strength (merge_ap));
1830 			nm_ap_set_last_seen (found_ap, nm_ap_get_last_seen (merge_ap));
1831 			nm_ap_set_broadcast (found_ap, nm_ap_get_broadcast (merge_ap));
1832 			nm_ap_set_freq (found_ap, nm_ap_get_freq (merge_ap));
1833 			nm_ap_set_max_bitrate (found_ap, nm_ap_get_max_bitrate (merge_ap));
1834 	
1835 			/* If the AP is noticed in a scan, it's automatically no longer
1836 			 * fake, since it clearly exists somewhere.
1837 			 */
1838 			nm_ap_set_fake (found_ap, FALSE);
1839 		} else {
1840 			/* New entry in the list */
1841 			nm_log_dbg (LOGD_WIFI_SCAN, "(%s): adding new AP '%s' " MAC_FMT " (%p)",
1842 			            nm_device_get_iface (NM_DEVICE (self)),
1843 			            ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
1844 			            MAC_ARG (bssid->ether_addr_octet),
1845 			            merge_ap);
1846 	
1847 			g_object_ref (merge_ap);
1848 			priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap);
1849 			nm_ap_export_to_dbus (merge_ap);
1850 			g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, merge_ap);
1851 			nm_device_recheck_available_connections (NM_DEVICE (self));
1852 		}
1853 	}
1854 	
1855 	#define WPAS_REMOVED_TAG "supplicant-removed"
1856 	
1857 	static gboolean
1858 	cull_scan_list (NMDeviceWifi *self)
1859 	{
1860 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1861 		time_t now = time (NULL);
1862 		GSList *outdated_list = NULL;
1863 		GSList *elt;
1864 		guint32 removed = 0, total = 0;
1865 	
1866 		priv->scanlist_cull_id = 0;
1867 	
1868 		nm_log_dbg (LOGD_WIFI_SCAN, "(%s): checking scan list for outdated APs",
1869 		            nm_device_get_iface (NM_DEVICE (self)));
1870 	
1871 		/* Walk the access point list and remove any access points older than
1872 		 * three times the inactive scan interval.
1873 		 */
1874 		for (elt = priv->ap_list; elt; elt = g_slist_next (elt), total++) {
1875 			NMAccessPoint *ap = elt->data;
1876 			const guint prune_interval_s = SCAN_INTERVAL_MAX * 3;
1877 	
1878 			/* Don't cull the associated AP or manually created APs */
1879 			if (ap == priv->current_ap || nm_ap_get_fake (ap))
1880 				continue;
1881 	
1882 			/* Don't cull APs still known to the supplicant.  Since the supplicant
1883 			 * doesn't yet emit property updates for "last seen" we have to rely
1884 			 * on changing signal strength for updating "last seen".  But if the
1885 			 * AP's strength doesn't change we won't get any updates for the AP,
1886 			 * and we'll end up here even if the AP was still found by the
1887 			 * supplicant in the last scan.
1888 			 */
1889 			if (   nm_ap_get_supplicant_path (ap)
1890 			    && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL)
1891 				continue;
1892 	
1893 			if (nm_ap_get_last_seen (ap) + prune_interval_s < now)
1894 				outdated_list = g_slist_append (outdated_list, ap);
1895 		}
1896 	
1897 		/* Remove outdated APs */
1898 		for (elt = outdated_list; elt; elt = g_slist_next (elt)) {
1899 			NMAccessPoint *outdated_ap = NM_AP (elt->data);
1900 			const struct ether_addr *bssid;
1901 			const GByteArray *ssid;
1902 	
1903 			bssid = nm_ap_get_address (outdated_ap);
1904 			ssid = nm_ap_get_ssid (outdated_ap);
1905 			nm_log_dbg (LOGD_WIFI_SCAN,
1906 			            "   removing %02x:%02x:%02x:%02x:%02x:%02x (%s%s%s)",
1907 			            bssid->ether_addr_octet[0], bssid->ether_addr_octet[1],
1908 			            bssid->ether_addr_octet[2], bssid->ether_addr_octet[3],
1909 			            bssid->ether_addr_octet[4], bssid->ether_addr_octet[5],
1910 			            ssid ? "'" : "",
1911 			            ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)",
1912 			            ssid ? "'" : "");
1913 	
1914 			remove_access_point (self, outdated_ap, TRUE);
1915 			removed++;
1916 		}
1917 		g_slist_free (outdated_list);
1918 	
1919 		nm_log_dbg (LOGD_WIFI_SCAN, "(%s): removed %d APs (of %d)",
1920 		            nm_device_get_iface (NM_DEVICE (self)),
1921 		            removed, total);
1922 	
1923 		ap_list_dump (self);
1924 	
1925 		if(removed > 0)
1926 		    nm_device_recheck_available_connections (NM_DEVICE (self));
1927 	
1928 		return FALSE;
1929 	}
1930 	
1931 	static void
1932 	schedule_scanlist_cull (NMDeviceWifi *self)
1933 	{
1934 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
1935 	
1936 		/* Cull the scan list after the last request for it has come in */
1937 		if (priv->scanlist_cull_id)
1938 			g_source_remove (priv->scanlist_cull_id);
1939 		priv->scanlist_cull_id = g_timeout_add_seconds (4, (GSourceFunc) cull_scan_list, self);
1940 	}
1941 	
1942 	static void
1943 	supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
1944 	                             const char *object_path,
1945 	                             GHashTable *properties,
1946 	                             NMDeviceWifi *self)
1947 	{
1948 		NMDeviceState state;
1949 		NMAccessPoint *ap;
1950 	
1951 		g_return_if_fail (self != NULL);
1952 		g_return_if_fail (properties != NULL);
1953 		g_return_if_fail (iface != NULL);
1954 	
1955 		/* Ignore new APs when unavailable, unmanaged, or in AP mode */
1956 		state = nm_device_get_state (NM_DEVICE (self));
1957 		if (state <= NM_DEVICE_STATE_UNAVAILABLE)
1958 			return;
1959 		if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP)
1960 			return;
1961 	
1962 		ap = nm_ap_new_from_properties (object_path, properties);
1963 		if (ap) {
1964 			nm_ap_dump (ap, "New AP: ");
1965 	
1966 			/* Add the AP to the device's AP list */
1967 			merge_scanned_ap (self, ap);
1968 			g_object_unref (ap);
1969 		} else {
1970 			nm_log_warn (LOGD_WIFI_SCAN, "(%s): invalid AP properties received",
1971 			             nm_device_get_iface (NM_DEVICE (self)));
1972 		}
1973 	
1974 		/* Remove outdated access points */
1975 		schedule_scanlist_cull (self);
1976 	}
1977 	
1978 	static void
1979 	supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
1980 	                                 const char *object_path,
1981 	                                 GHashTable *properties,
1982 	                                 NMDeviceWifi *self)
1983 	{
1984 		NMDeviceState state;
1985 		NMAccessPoint *ap;
1986 	
1987 		g_return_if_fail (self != NULL);
1988 		g_return_if_fail (object_path != NULL);
1989 		g_return_if_fail (properties != NULL);
1990 	
1991 		/* Ignore new APs when unavailable or unamnaged */
1992 		state = nm_device_get_state (NM_DEVICE (self));
1993 		if (state <= NM_DEVICE_STATE_UNAVAILABLE)
1994 			return;
1995 	
1996 		/* Update the AP's last-seen property */
1997 		ap = get_ap_by_supplicant_path (self, object_path);
1998 		if (ap)
1999 			nm_ap_set_last_seen (ap, (guint32) time (NULL));
2000 	
2001 		/* Remove outdated access points */
2002 		schedule_scanlist_cull (self);
2003 	}
2004 	
2005 	static void
2006 	supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
2007 	                                 const char *object_path,
2008 	                                 NMDeviceWifi *self)
2009 	{
2010 		NMAccessPoint *ap;
2011 	
2012 		g_return_if_fail (self != NULL);
2013 		g_return_if_fail (object_path != NULL);
2014 	
2015 		ap = get_ap_by_supplicant_path (self, object_path);
2016 		if (ap)
2017 			g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE));
2018 	}
2019 	
2020 	
2021 	static void
2022 	cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
2023 	{
2024 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2025 	
2026 		remove_supplicant_interface_error_handler (self);
2027 		remove_supplicant_timeouts (self);
2028 		if (disconnect && priv->supplicant.iface)
2029 			nm_supplicant_interface_disconnect (priv->supplicant.iface);
2030 	}
2031 	
2032 	static void
2033 	wifi_secrets_cb (NMActRequest *req,
2034 	                 guint32 call_id,
2035 	                 NMConnection *connection,
2036 	                 GError *error,
2037 	                 gpointer user_data)
2038 	{
2039 		NMDevice *dev = NM_DEVICE (user_data);
2040 	
2041 		g_return_if_fail (req == nm_device_get_act_request (dev));
2042 		g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH);
2043 		g_return_if_fail (nm_act_request_get_connection (req) == connection);
2044 	
2045 		if (error) {
2046 			nm_log_warn (LOGD_WIFI, "%s", error->message);
2047 			nm_device_state_changed (dev,
2048 			                         NM_DEVICE_STATE_FAILED,
2049 			                         NM_DEVICE_STATE_REASON_NO_SECRETS);
2050 		} else
2051 			nm_device_activate_schedule_stage1_device_prepare (dev);
2052 	}
2053 	
2054 	static void
2055 	remove_link_timeout (NMDeviceWifi *self)
2056 	{
2057 		NMDeviceWifiPrivate *priv;
2058 	
2059 		g_return_if_fail (self != NULL);
2060 		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2061 	
2062 		if (priv->link_timeout_id) {
2063 			g_source_remove (priv->link_timeout_id);
2064 			priv->link_timeout_id = 0;
2065 		}
2066 	}
2067 	
2068 	
2069 	/*
2070 	 * link_timeout_cb
2071 	 *
2072 	 * Called when the link to the access point has been down for a specified
2073 	 * period of time.
2074 	 */
2075 	static gboolean
2076 	link_timeout_cb (gpointer user_data)
2077 	{
2078 		NMDevice *dev = NM_DEVICE (user_data);
2079 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
2080 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2081 		NMAccessPoint *ap;
2082 	
2083 		nm_log_warn (LOGD_WIFI, "(%s): link timed out.", nm_device_get_iface (dev));
2084 	
2085 		priv->link_timeout_id = 0;
2086 	
2087 		/* Disconnect event while activated; the supplicant hasn't been able
2088 		 * to reassociate within the timeout period, so the connection must
2089 		 * fail.
2090 		 */
2091 		if (nm_device_get_state (dev) != NM_DEVICE_STATE_ACTIVATED)
2092 			return FALSE;
2093 	
2094 		/* If the access point failed, and wasn't found by the supplicant when it
2095 		 * attempted to reconnect, then it's probably out of range or turned off.
2096 		 * Remove it from the list and if it's actually still present, it'll be
2097 		 * found in the next scan.
2098 		 */
2099 		if (priv->ssid_found == FALSE) {
2100 			if (priv->current_ap) {
2101 				ap = priv->current_ap;
2102 				priv->current_ap = NULL;
2103 			} else
2104 				ap = nm_device_wifi_get_activation_ap (self);
2105 	
2106 			if (ap)
2107 				remove_access_point (self, ap, TRUE);
2108 		}
2109 	
2110 		nm_device_state_changed (dev,
2111 		                         NM_DEVICE_STATE_FAILED,
2112 		                         priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT :
2113 		                                            NM_DEVICE_STATE_REASON_SSID_NOT_FOUND);
2114 		return FALSE;
2115 	}
2116 	
2117 	static gboolean
2118 	need_new_8021x_secrets (NMDeviceWifi *self,
2119 	                        guint32 old_state,
2120 	                        const char **setting_name)
2121 	{
2122 		NMSetting8021x *s_8021x;
2123 		NMSettingWirelessSecurity *s_wsec;
2124 		NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
2125 		NMConnection *connection;
2126 	
2127 		g_assert (setting_name != NULL);
2128 	
2129 		connection = nm_device_get_connection (NM_DEVICE (self));
2130 		g_return_val_if_fail (connection != NULL, FALSE);
2131 	
2132 		/* 802.1x stuff only happens in the supplicant's ASSOCIATED state when it's
2133 		 * attempting to authenticate with the AP.
2134 		 */
2135 		if (old_state != NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED)
2136 			return FALSE;
2137 	
2138 		/* If it's an 802.1x or LEAP connection with "always ask"/unsaved secrets
2139 		 * then we need to ask again because it might be an OTP token and the PIN
2140 		 * may have changed.
2141 		 */
2142 	
2143 		s_8021x = nm_connection_get_setting_802_1x (connection);
2144 		if (s_8021x) {
2145 			nm_setting_get_secret_flags (NM_SETTING (s_8021x),
2146 			                             NM_SETTING_802_1X_PASSWORD,
2147 			                             &secret_flags,
2148 			                             NULL);
2149 			if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
2150 				*setting_name = NM_SETTING_802_1X_SETTING_NAME;
2151 			return *setting_name ? TRUE : FALSE;
2152 		}
2153 	
2154 		s_wsec = nm_connection_get_setting_wireless_security (connection);
2155 		if (s_wsec) {
2156 			nm_setting_get_secret_flags (NM_SETTING (s_wsec),
2157 			                             NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
2158 			                             &secret_flags,
2159 			                             NULL);
2160 			if (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED)
2161 				*setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
2162 			return *setting_name ? TRUE : FALSE;
2163 		}
2164 	
2165 		/* Not a LEAP or 802.1x connection */
2166 		return FALSE;
2167 	}
2168 	
2169 	static gboolean
2170 	need_new_wpa_psk (NMDeviceWifi *self,
2171 	                  guint32 old_state,
2172 	                  const char **setting_name)
2173 	{
2174 		NMSettingWirelessSecurity *s_wsec;
2175 		NMConnection *connection;
2176 		const char *key_mgmt = NULL;
2177 	
2178 		g_assert (setting_name != NULL);
2179 	
2180 		connection = nm_device_get_connection (NM_DEVICE (self));
2181 		g_return_val_if_fail (connection != NULL, FALSE);
2182 	
2183 		/* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */
2184 		if (old_state != NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE)
2185 			return FALSE;
2186 	
2187 		s_wsec = nm_connection_get_setting_wireless_security (connection);
2188 		if (s_wsec)
2189 			key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
2190 	
2191 		if (g_strcmp0 (key_mgmt, "wpa-psk") == 0) {
2192 			*setting_name = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
2193 			return TRUE;
2194 		}
2195 	
2196 		/* Not a WPA-PSK connection */
2197 		return FALSE;
2198 	}
2199 	
2200 	static gboolean
2201 	handle_8021x_or_psk_auth_fail (NMDeviceWifi *self,
2202 	                               guint32 new_state,
2203 	                               guint32 old_state,
2204 	                               int disconnect_reason)
2205 	{
2206 		NMDevice *device = NM_DEVICE (self);
2207 		NMActRequest *req;
2208 		NMConnection *connection;
2209 		const char *setting_name = NULL;
2210 		gboolean handled = FALSE;
2211 	
2212 		g_return_val_if_fail (new_state == NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, FALSE);
2213 	
2214 		req = nm_device_get_act_request (NM_DEVICE (self));
2215 		g_return_val_if_fail (req != NULL, FALSE);
2216 	
2217 		connection = nm_act_request_get_connection (req);
2218 		g_assert (connection);
2219 	
2220 		if (   need_new_8021x_secrets (self, old_state, &setting_name)
2221 		    || need_new_wpa_psk (self, old_state, &setting_name)) {
2222 	
2223 			nm_connection_clear_secrets (connection);
2224 	
2225 			nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2226 			             "Activation (%s/wireless): disconnected during association,"
2227 			             " asking for new key.", nm_device_get_iface (device));
2228 	
2229 			cleanup_association_attempt (self, TRUE);
2230 			nm_device_state_changed (device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
2231 			nm_act_request_get_secrets (req,
2232 			                            setting_name,
2233 			                            NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION
2234 			                              | NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW,
2235 			                            NULL,
2236 			                            wifi_secrets_cb,
2237 			                            self);
2238 			handled = TRUE;
2239 		}
2240 	
2241 		return handled;
2242 	}
2243 	
2244 	static void
2245 	supplicant_iface_state_cb (NMSupplicantInterface *iface,
2246 	                           guint32 new_state,
2247 	                           guint32 old_state,
2248 	                           int disconnect_reason,
2249 	                           gpointer user_data)
2250 	{
2251 		NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
2252 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2253 		NMDevice *device = NM_DEVICE (self);
2254 		NMDeviceState devstate;
2255 		gboolean scanning;
2256 	
2257 		if (new_state == old_state)
2258 			return;
2259 	
2260 		nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2261 		             "(%s): supplicant interface state: %s -> %s",
2262 		             nm_device_get_iface (device),
2263 		             nm_supplicant_interface_state_to_string (old_state),
2264 		             nm_supplicant_interface_state_to_string (new_state));
2265 	
2266 		devstate = nm_device_get_state (device);
2267 		scanning = nm_supplicant_interface_get_scanning (iface);
2268 	
2269 		/* In these states we know the supplicant is actually talking to something */
2270 		if (   new_state >= NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
2271 		    && new_state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
2272 			priv->ssid_found = TRUE;
2273 	
2274 		switch (new_state) {
2275 		case NM_SUPPLICANT_INTERFACE_STATE_READY:
2276 			priv->scan_interval = SCAN_INTERVAL_MIN;
2277 	
2278 			/* If the interface can now be activated because the supplicant is now
2279 			 * available, transition to DISCONNECTED.
2280 			 */
2281 			if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
2282 				nm_device_state_changed (device,
2283 				                         NM_DEVICE_STATE_DISCONNECTED,
2284 				                         NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE);
2285 			}
2286 	
2287 			nm_log_dbg (LOGD_WIFI_SCAN,
2288 			            "(%s): supplicant ready, requesting initial scan",
2289 			            nm_device_get_iface (device));
2290 	
2291 			/* Request a scan to get latest results */
2292 			cancel_pending_scan (self);
2293 			request_wireless_scan (self);
2294 	
2295 			if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY)
2296 				nm_device_remove_pending_action (device, "waiting for supplicant");
2297 			break;
2298 		case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
2299 			remove_supplicant_interface_error_handler (self);
2300 			remove_supplicant_timeouts (self);
2301 	
2302 			/* If this is the initial association during device activation,
2303 			 * schedule the next activation stage.
2304 			 */
2305 			if (devstate == NM_DEVICE_STATE_CONFIG) {
2306 				NMAccessPoint *ap = nm_device_wifi_get_activation_ap (self);
2307 				const GByteArray *ssid = nm_ap_get_ssid (ap);
2308 	
2309 				nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2310 				             "Activation (%s/wireless) Stage 2 of 5 (Device Configure) "
2311 				             "successful.  %s '%s'.",
2312 				             nm_device_get_iface (device),
2313 				             priv->mode == NM_802_11_MODE_AP ? "Started Wi-Fi Hotspot" :
2314 				                 "Connected to wireless network",
2315 				             ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
2316 				nm_device_activate_schedule_stage3_ip_config_start (device);
2317 			} else if (devstate == NM_DEVICE_STATE_ACTIVATED)
2318 				periodic_update (self);
2319 			break;
2320 		case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED:
2321 			if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) {
2322 				/* Disconnect of an 802.1x/LEAP connection during authentication,
2323 				 * or disconnect of a WPA-PSK connection during the 4-way handshake,
2324 				 * often means secrets are wrong. Not always the case, but until we
2325 				 * have more information from wpa_supplicant about why the
2326 				 * disconnect happened this is the best we can do.
2327 				 */
2328 				if (handle_8021x_or_psk_auth_fail (self, new_state, old_state, disconnect_reason))
2329 					break;
2330 			}
2331 	
2332 			/* Otherwise it might be a stupid driver or some transient error, so
2333 			 * let the supplicant try to reconnect a few more times.  Give it more
2334 			 * time if a scan is in progress since the link might be dropped during
2335 			 * the scan but will be re-established when the scan is done.
2336 			 */
2337 			if (devstate == NM_DEVICE_STATE_ACTIVATED) {
2338 				if (priv->link_timeout_id == 0) {
2339 					priv->link_timeout_id = g_timeout_add_seconds (scanning ? 30 : 15, link_timeout_cb, self);
2340 					priv->ssid_found = FALSE;
2341 				}
2342 			}
2343 			break;
2344 		case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
2345 			cleanup_association_attempt (self, FALSE);
2346 	
2347 			/* If the device is already in UNAVAILABLE state then the state change
2348 			 * is a NOP and the interface won't be re-acquired in the device state
2349 			 * change handler.  So ensure we have a new one here so that we're
2350 			 * ready if the supplicant comes back.
2351 			 */
2352 			supplicant_interface_release (self);
2353 			supplicant_interface_acquire (self);
2354 	
2355 			nm_device_state_changed (device,
2356 			                         NM_DEVICE_STATE_UNAVAILABLE,
2357 			                         NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
2358 			break;
2359 		default:
2360 			break;
2361 		}
2362 	
2363 		/* Signal scanning state changes */
2364 		if (   new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
2365 		    || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
2366 			g_object_notify (G_OBJECT (self), "scanning");
2367 	}
2368 	
2369 	struct iface_con_error_cb_data {
2370 		NMDeviceWifi *self;
2371 		char *name;
2372 		char *message;
2373 	};
2374 	
2375 	static gboolean
2376 	supplicant_iface_connection_error_cb_handler (gpointer user_data)
2377 	{
2378 		NMDeviceWifi *self;
2379 		NMDeviceWifiPrivate *priv;
2380 		struct iface_con_error_cb_data * cb_data = (struct iface_con_error_cb_data *) user_data;
2381 	
2382 		g_return_val_if_fail (cb_data != NULL, FALSE);
2383 	
2384 		self = cb_data->self;
2385 		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2386 	
2387 		if (!nm_device_is_activating (NM_DEVICE (self)))
2388 			goto out;
2389 	
2390 		nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2391 		             "Activation (%s/wireless): association request to the supplicant "
2392 		             "failed: %s - %s",
2393 		             nm_device_get_iface (NM_DEVICE (self)),
2394 		             cb_data->name,
2395 		             cb_data->message);
2396 	
2397 		cleanup_association_attempt (self, TRUE);
2398 		nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
2399 	
2400 	out:
2401 		priv->supplicant.iface_con_error_cb_id = 0;
2402 		g_free (cb_data->name);
2403 		g_free (cb_data->message);
2404 		g_slice_free (struct iface_con_error_cb_data, cb_data);
2405 		return FALSE;
2406 	}
2407 	
2408 	
2409 	static void
2410 	supplicant_iface_connection_error_cb (NMSupplicantInterface * iface,
2411 	                                      const char * name,
2412 	                                      const char * message,
2413 	                                      NMDeviceWifi * self)
2414 	{
2415 		NMDeviceWifiPrivate *priv;
2416 		struct iface_con_error_cb_data *cb_data;
2417 		guint id;
2418 	
2419 		g_return_if_fail (self != NULL);
2420 		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2421 	
2422 		cb_data = g_slice_new0 (struct iface_con_error_cb_data);
2423 		cb_data->self = self;
2424 		cb_data->name = g_strdup (name);
2425 		cb_data->message = g_strdup (message);
2426 	
2427 		if (priv->supplicant.iface_con_error_cb_id)
2428 			g_source_remove (priv->supplicant.iface_con_error_cb_id);
2429 	
2430 		id = g_idle_add (supplicant_iface_connection_error_cb_handler, cb_data);
2431 		priv->supplicant.iface_con_error_cb_id = id;
2432 	}
2433 	
2434 	static void
2435 	supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
2436 	                                     GParamSpec *pspec,
2437 	                                     NMDeviceWifi *self)
2438 	{
2439 		NMDeviceState state;
2440 		gboolean scanning;
2441 	
2442 		scanning = nm_supplicant_interface_get_scanning (iface);
2443 		nm_log_dbg (LOGD_WIFI_SCAN, "(%s): now %s",
2444 		            nm_device_get_iface (NM_DEVICE (self)),
2445 		            scanning ? "scanning" : "idle");
2446 	
2447 		g_object_notify (G_OBJECT (self), "scanning");
2448 	
2449 		/* Run a quick update of current AP when coming out of a scan */
2450 		state = nm_device_get_state (NM_DEVICE (self));
2451 		if (!scanning && state == NM_DEVICE_STATE_ACTIVATED)
2452 			periodic_update (self);
2453 	}
2454 	
2455 	static void
2456 	remove_supplicant_connection_timeout (NMDeviceWifi *self)
2457 	{
2458 		NMDeviceWifiPrivate *priv;
2459 	
2460 		g_return_if_fail (self != NULL);
2461 		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2462 	
2463 		/* Remove any pending timeouts on the request */
2464 		if (priv->supplicant.con_timeout_id) {
2465 			g_source_remove (priv->supplicant.con_timeout_id);
2466 			priv->supplicant.con_timeout_id = 0;
2467 		}
2468 	}
2469 	
2470 	static NMActStageReturn
2471 	handle_auth_or_fail (NMDeviceWifi *self,
2472 	                     NMActRequest *req,
2473 	                     gboolean new_secrets)
2474 	{
2475 		const char *setting_name;
2476 		guint32 tries;
2477 		NMConnection *connection;
2478 		NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
2479 	
2480 		g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE);
2481 	
2482 		if (!req) {
2483 			req = nm_device_get_act_request (NM_DEVICE (self));
2484 			g_assert (req);
2485 		}
2486 	
2487 		connection = nm_act_request_get_connection (req);
2488 		g_assert (connection);
2489 	
2490 		tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES));
2491 		if (tries > 3)
2492 			return NM_ACT_STAGE_RETURN_FAILURE;
2493 	
2494 		nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE);
2495 	
2496 		nm_connection_clear_secrets (connection);
2497 		setting_name = nm_connection_need_secrets (connection, NULL);
2498 		if (setting_name) {
2499 			NMSettingsGetSecretsFlags flags = NM_SETTINGS_GET_SECRETS_FLAG_ALLOW_INTERACTION;
2500 	
2501 			if (new_secrets)
2502 				flags |= NM_SETTINGS_GET_SECRETS_FLAG_REQUEST_NEW;
2503 			nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self);
2504 	
2505 			g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries));
2506 			ret = NM_ACT_STAGE_RETURN_POSTPONE;
2507 		} else
2508 			nm_log_warn (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets.");
2509 	
2510 		return ret;
2511 	}
2512 	
2513 	static gboolean
2514 	is_encrypted (NMAccessPoint *ap, NMConnection *connection)
2515 	{
2516 		NM80211ApFlags flags;
2517 		NM80211ApSecurityFlags wpa_flags, rsn_flags;
2518 	
2519 		g_return_val_if_fail (ap != NULL, FALSE);
2520 		g_return_val_if_fail (connection != NULL, FALSE);
2521 	
2522 		flags = nm_ap_get_flags (ap);
2523 		wpa_flags = nm_ap_get_wpa_flags (ap);
2524 		rsn_flags = nm_ap_get_rsn_flags (ap);
2525 	
2526 		if (flags & NM_802_11_AP_FLAGS_PRIVACY)
2527 			return TRUE;
2528 		if (wpa_flags & (NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X))
2529 			return TRUE;
2530 		if (rsn_flags & (NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X))
2531 			return TRUE;
2532 	
2533 		return FALSE;
2534 	}
2535 	
2536 	/*
2537 	 * supplicant_connection_timeout_cb
2538 	 *
2539 	 * Called when the supplicant has been unable to connect to an access point
2540 	 * within a specified period of time.
2541 	 */
2542 	static gboolean
2543 	supplicant_connection_timeout_cb (gpointer user_data)
2544 	{
2545 		NMDevice *dev = NM_DEVICE (user_data);
2546 		NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
2547 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2548 		NMAccessPoint *ap;
2549 		NMActRequest *req;
2550 		NMConnection *connection;
2551 	
2552 		cleanup_association_attempt (self, TRUE);
2553 	
2554 		if (!nm_device_is_activating (dev))
2555 			return FALSE;
2556 	
2557 		/* Timed out waiting for a successful connection to the AP; if the AP's
2558 		 * security requires network-side authentication (like WPA or 802.1x)
2559 		 * and the connection attempt timed out then it's likely the authentication
2560 		 * information (passwords, pin codes, etc) are wrong.
2561 		 */
2562 	
2563 		req = nm_device_get_act_request (dev);
2564 		g_assert (req);
2565 	
2566 		connection = nm_act_request_get_connection (req);
2567 		g_assert (connection);
2568 	
2569 		if (   priv->mode == NM_802_11_MODE_ADHOC
2570 		    || priv->mode == NM_802_11_MODE_AP) {
2571 			/* In Ad-Hoc and AP modes there's nothing to check the encryption key
2572 			 * (if any), so supplicant timeouts here are almost certainly the wifi
2573 			 * driver being really stupid.
2574 			 */
2575 			nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
2576 			             "Activation (%s/wireless): %s network creation took "
2577 			             "too long, failing activation.",
2578 			             nm_device_get_iface (dev),
2579 			             priv->mode == NM_802_11_MODE_ADHOC ? "Ad-Hoc" : "Hotspot");
2580 			nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED,
2581 			                         NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT);
2582 			return FALSE;
2583 		}
2584 	
2585 		g_assert (priv->mode == NM_802_11_MODE_INFRA);
2586 		ap = nm_device_wifi_get_activation_ap (self);
2587 		g_assert (ap);
2588 	
2589 		if (priv->ssid_found && is_encrypted (ap, connection)) {
2590 			guint64 timestamp = 0;
2591 			gboolean new_secrets = TRUE;
2592 	
2593 			/* Connection failed; either driver problems, the encryption key is
2594 			 * wrong, or the passwords or certificates were wrong.
2595 			 */
2596 			nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
2597 			             "Activation (%s/wireless): association took too long.",
2598 			             nm_device_get_iface (dev));
2599 	
2600 			/* Ask for new secrets only if we've never activated this connection
2601 			 * before.  If we've connected before, don't bother the user with
2602 			 * dialogs, just retry or fail, and if we never connect the user can
2603 			 * fix the password somewhere else.
2604 			 */
2605 			if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), &timestamp))
2606 				new_secrets = !timestamp;
2607 	
2608 			if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) {
2609 				nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
2610 				             "Activation (%s/wireless): asking for new secrets",
2611 				             nm_device_get_iface (dev));
2612 			} else {
2613 				nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED,
2614 				                         NM_DEVICE_STATE_REASON_NO_SECRETS);
2615 			}
2616 		} else {
2617 			nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
2618 			             "Activation (%s/wireless): association took too long, "
2619 			             "failing activation.",
2620 			             nm_device_get_iface (dev));
2621 			nm_device_state_changed (dev, NM_DEVICE_STATE_FAILED,
2622 			                         priv->ssid_found ? NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT :
2623 			                                            NM_DEVICE_STATE_REASON_SSID_NOT_FOUND);
2624 		}
2625 	
2626 		return FALSE;
2627 	}
2628 	
2629 	
2630 	static gboolean
2631 	start_supplicant_connection_timeout (NMDeviceWifi *self)
2632 	{
2633 		NMDeviceWifiPrivate *priv;
2634 		guint id;
2635 	
2636 		g_return_val_if_fail (self != NULL, FALSE);
2637 	
2638 		priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2639 	
2640 		/* Set up a timeout on the connection attempt to fail it after 25 seconds */
2641 		id = g_timeout_add_seconds (25, supplicant_connection_timeout_cb, self);
2642 		if (id == 0) {
2643 			nm_log_err (LOGD_DEVICE | LOGD_WIFI,
2644 			            "Activation (%s/wireless): couldn't start supplicant "
2645 			            "timeout timer.",
2646 			            nm_device_get_iface (NM_DEVICE (self)));
2647 			return FALSE;
2648 		}
2649 		priv->supplicant.con_timeout_id = id;
2650 		return TRUE;
2651 	}
2652 	
2653 	
2654 	static void
2655 	remove_supplicant_timeouts (NMDeviceWifi *self)
2656 	{
2657 		g_return_if_fail (self != NULL);
2658 	
2659 		remove_supplicant_connection_timeout (self);
2660 		remove_link_timeout (self);
2661 	}
2662 	
2663 	static NMSupplicantConfig *
2664 	build_supplicant_config (NMDeviceWifi *self,
2665 	                         NMConnection *connection,
2666 	                         NMAccessPoint *ap)
2667 	{
2668 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2669 		NMSupplicantConfig *config = NULL;
2670 		NMSettingWireless *s_wireless;
2671 		NMSettingWirelessSecurity *s_wireless_sec;
2672 	
2673 		g_return_val_if_fail (self != NULL, NULL);
2674 	
2675 		s_wireless = nm_connection_get_setting_wireless (connection);
2676 		g_return_val_if_fail (s_wireless != NULL, NULL);
2677 	
2678 		config = nm_supplicant_config_new ();
2679 		if (!config)
2680 			return NULL;
2681 	
2682 		/* Warn if AP mode may not be supported */
2683 		if (   g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0
2684 		    && nm_supplicant_interface_get_ap_support (priv->supplicant.iface) == AP_SUPPORT_UNKNOWN) {
2685 			nm_log_warn (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out.");
2686 		}
2687 	
2688 		if (!nm_supplicant_config_add_setting_wireless (config,
2689 		                                                s_wireless,
2690 		                                                nm_ap_get_broadcast (ap),
2691 		                                                nm_ap_get_freq (ap),
2692 		                                                wifi_utils_can_scan_ssid (priv->wifi_data))) {
2693 			nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config.");
2694 			goto error;
2695 		}
2696 	
2697 		s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
2698 		if (s_wireless_sec) {
2699 			NMSetting8021x *s_8021x;
2700 			const char *con_uuid = nm_connection_get_uuid (connection);
2701 	
2702 			g_assert (con_uuid);
2703 			s_8021x = nm_connection_get_setting_802_1x (connection);
2704 			if (!nm_supplicant_config_add_setting_wireless_security (config,
2705 			                                                         s_wireless_sec,
2706 			                                                         s_8021x,
2707 			                                                         con_uuid)) {
2708 				nm_log_err (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to "
2709 				            "supplicant config.");
2710 				goto error;
2711 			}
2712 		} else {
2713 			if (!nm_supplicant_config_add_no_security (config)) {
2714 				nm_log_err (LOGD_WIFI, "Couldn't add unsecured option to supplicant config.");
2715 				goto error;
2716 			}
2717 		}
2718 	
2719 		return config;
2720 	
2721 	error:
2722 		g_object_unref (config);
2723 		return NULL;
2724 	}
2725 	
2726 	/****************************************************************************/
2727 	
2728 	static void
2729 	update_permanent_hw_address (NMDevice *dev)
2730 	{
2731 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
2732 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2733 		struct ifreq req;
2734 		struct ethtool_perm_addr *epaddr = NULL;
2735 		int fd, ret;
2736 	
2737 		fd = socket (PF_INET, SOCK_DGRAM, 0);
2738 		if (fd < 0) {
2739 			nm_log_err (LOGD_HW, "could not open control socket.");
2740 			return;
2741 		}
2742 	
2743 		/* Get permanent MAC address */
2744 		memset (&req, 0, sizeof (struct ifreq));
2745 		strncpy (req.ifr_name, nm_device_get_iface (dev), IFNAMSIZ);
2746 	
2747 		epaddr = g_malloc0 (sizeof (struct ethtool_perm_addr) + ETH_ALEN);
2748 		epaddr->cmd = ETHTOOL_GPERMADDR;
2749 		epaddr->size = ETH_ALEN;
2750 		req.ifr_data = (void *) epaddr;
2751 	
2752 		errno = 0;
2753 		ret = ioctl (fd, SIOCETHTOOL, &req);
2754 		if ((ret < 0) || !nm_ethernet_address_is_valid ((struct ether_addr *) epaddr->data)) {
2755 			nm_log_dbg (LOGD_HW | LOGD_ETHER, "(%s): unable to read permanent MAC address (error %d)",
2756 			            nm_device_get_iface (dev), errno);
2757 			/* Fall back to current address */
2758 			memcpy (epaddr->data, nm_device_get_hw_address (dev, NULL), ETH_ALEN);
2759 		}
2760 	
2761 		if (memcmp (&priv->perm_hw_addr, epaddr->data, ETH_ALEN)) {
2762 			memcpy (&priv->perm_hw_addr, epaddr->data, ETH_ALEN);
2763 			g_object_notify (G_OBJECT (dev), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
2764 		}
2765 	
2766 		g_free (epaddr);
2767 		close (fd);
2768 	}
2769 	
2770 	static void
2771 	update_initial_hw_address (NMDevice *dev)
2772 	{
2773 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
2774 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2775 		char *mac_str;
2776 	
2777 		/* This sets initial MAC address from current MAC address. It should only
2778 		 * be called from NMDevice constructor() to really get the initial address.
2779 		 */
2780 		memcpy (priv->initial_hw_addr, nm_device_get_hw_address (dev, NULL), ETH_ALEN);
2781 	 
2782 		mac_str = nm_utils_hwaddr_ntoa (priv->initial_hw_addr, ARPHRD_ETHER);
2783 		nm_log_dbg (LOGD_DEVICE | LOGD_ETHER, "(%s): read initial MAC address %s",
2784 		            nm_device_get_iface (dev), mac_str);
2785 		g_free (mac_str);
2786 	}
2787 	
2788 	static NMActStageReturn
2789 	act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason)
2790 	{
2791 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
2792 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2793 		NMAccessPoint *ap = NULL;
2794 		NMActRequest *req;
2795 		NMConnection *connection;
2796 		NMSettingWireless *s_wireless;
2797 		const GByteArray *cloned_mac;
2798 		GSList *iter;
2799 		const char *mode;
2800 	
2801 		req = nm_device_get_act_request (NM_DEVICE (self));
2802 		g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE);
2803 	
2804 		connection = nm_act_request_get_connection (req);
2805 		g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
2806 	
2807 		s_wireless = nm_connection_get_setting_wireless (connection);
2808 		g_assert (s_wireless);
2809 	
2810 		mode = nm_setting_wireless_get_mode (s_wireless);
2811 		if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_INFRA) == 0)
2812 			priv->mode = NM_802_11_MODE_INFRA;
2813 		else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0)
2814 			priv->mode = NM_802_11_MODE_ADHOC;
2815 		else if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0) {
2816 			priv->mode = NM_802_11_MODE_AP;
2817 	
2818 			/* Scanning not done in AP mode; clear the scan list */
2819 			remove_all_aps (self);
2820 		}
2821 		g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_MODE);
2822 	
2823 		/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
2824 		 * and turns them into open networks.  It's been this way since at least
2825 		 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
2826 		 */
2827 		if (is_adhoc_wpa (connection)) {
2828 			nm_log_warn (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs");
2829 			*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
2830 			return NM_ACT_STAGE_RETURN_FAILURE;
2831 		}
2832 	
2833 		/* Set spoof MAC to the interface */
2834 		cloned_mac = nm_setting_wireless_get_cloned_mac_address (s_wireless);
2835 		if (cloned_mac && (cloned_mac->len == ETH_ALEN))
2836 			nm_device_set_hw_addr (dev, (const guint8 *) cloned_mac->data, "set", LOGD_WIFI);
2837 	
2838 		/* AP mode never uses a specific object or existing scanned AP */
2839 		if (priv->mode != NM_802_11_MODE_AP) {
2840 			ap = nm_device_wifi_get_activation_ap (self);
2841 			if (ap)
2842 				goto done;
2843 	
2844 			/* Find a compatible AP in the scan list */
2845 			for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) {
2846 				NMAccessPoint *candidate = NM_AP (iter->data);
2847 	
2848 				if (nm_ap_check_compatible (candidate, connection)) {
2849 					ap = candidate;
2850 					break;
2851 				}
2852 			}
2853 		}
2854 	
2855 		/* If the user is trying to connect to an AP that NM doesn't yet know about
2856 		 * (hidden network or something) or starting a Hotspot, create an fake AP
2857 		 * from the security settings in the connection.  This "fake" AP gets used
2858 		 * until the real one is found in the scan list (Ad-Hoc or Hidden), or until
2859 		 * the device is deactivated (Hotspot).
2860 		 */
2861 		if (!ap) {
2862 			ap = nm_ap_new_fake_from_connection (connection);
2863 			g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE);
2864 	
2865 			if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA)
2866 				nm_ap_set_broadcast (ap, FALSE);
2867 			else if (nm_ap_is_hotspot (ap))
2868 				nm_ap_set_address (ap, (const struct ether_addr *) nm_device_get_hw_address (dev, NULL));
2869 	
2870 			priv->ap_list = g_slist_prepend (priv->ap_list, ap);
2871 			nm_ap_export_to_dbus (ap);
2872 			g_signal_emit (self, signals[ACCESS_POINT_ADDED], 0, ap);
2873 			nm_device_recheck_available_connections (NM_DEVICE (self));
2874 		}
2875 	
2876 		nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap));
2877 	
2878 	done:
2879 		set_active_ap (self, ap);
2880 		return NM_ACT_STAGE_RETURN_SUCCESS;
2881 	}
2882 	
2883 	static void
2884 	ensure_hotspot_frequency (NMDeviceWifi *self,
2885 	                          NMSettingWireless *s_wifi,
2886 	                          NMAccessPoint *ap)
2887 	{
2888 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2889 		const char *band = nm_setting_wireless_get_band (s_wifi);
2890 		const guint32 a_freqs[] = { 5180, 5200, 5220, 5745, 5765, 5785, 5805, 0 };
2891 		const guint32 bg_freqs[] = { 2412, 2437, 2462, 2472, 0 };
2892 		guint32 freq = 0;
2893 	
2894 		g_assert (ap);
2895 	
2896 		if (nm_ap_get_freq (ap))
2897 			return;
2898 	
2899 		if (g_strcmp0 (band, "a") == 0)
2900 			freq = wifi_utils_find_freq (priv->wifi_data, a_freqs);
2901 		else
2902 			freq = wifi_utils_find_freq (priv->wifi_data, bg_freqs);
2903 	
2904 		if (!freq)
2905 			freq = (g_strcmp0 (band, "a") == 0) ? 5180 : 2462;
2906 	
2907 		nm_ap_set_freq (ap, freq);
2908 	}
2909 	
2910 	static NMActStageReturn
2911 	act_stage2_config (NMDevice *dev, NMDeviceStateReason *reason)
2912 	{
2913 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
2914 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
2915 		NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
2916 		const char *iface = nm_device_get_iface (dev);
2917 		NMSupplicantConfig *config = NULL;
2918 		gulong id = 0;
2919 		NMActRequest *req;
2920 		NMAccessPoint *ap;
2921 		NMConnection *connection;
2922 		const char *setting_name;
2923 		NMSettingWireless *s_wireless;
2924 	
2925 		g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE);
2926 	
2927 		remove_supplicant_timeouts (self);
2928 	
2929 		req = nm_device_get_act_request (dev);
2930 		g_assert (req);
2931 	
2932 		ap = nm_device_wifi_get_activation_ap (self);
2933 		g_assert (ap);
2934 	
2935 		connection = nm_act_request_get_connection (req);
2936 		g_assert (connection);
2937 	
2938 		s_wireless = nm_connection_get_setting_wireless (connection);
2939 		g_assert (s_wireless);
2940 	
2941 		/* If we need secrets, get them */
2942 		setting_name = nm_connection_need_secrets (connection, NULL);
2943 		if (setting_name) {
2944 			nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2945 			             "Activation (%s/wireless): access point '%s' has security,"
2946 			             " but secrets are required.",
2947 			             iface, nm_connection_get_id (connection));
2948 	
2949 			ret = handle_auth_or_fail (self, req, FALSE);
2950 			if (ret == NM_ACT_STAGE_RETURN_FAILURE)
2951 				*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
2952 			goto out;
2953 		}
2954 	
2955 		/* have secrets, or no secrets required */
2956 		if (nm_connection_get_setting_wireless_security (connection)) {
2957 			nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2958 			             "Activation (%s/wireless): connection '%s' has security"
2959 			             ", and secrets exist.  No new secrets needed.",
2960 			             iface, nm_connection_get_id (connection));
2961 		} else {
2962 			nm_log_info (LOGD_DEVICE | LOGD_WIFI,
2963 			             "Activation (%s/wireless): connection '%s' requires no "
2964 			             "security.  No secrets needed.",
2965 			             iface, nm_connection_get_id (connection));
2966 		}
2967 	
2968 		priv->ssid_found = FALSE;
2969 	
2970 		/* Supplicant requires an initial frequency for Ad-Hoc and Hotspot; if the user
2971 		 * didn't specify one and we didn't find an AP that matched the connection,
2972 		 * just pick a frequency the device supports.
2973 		 */
2974 		if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap))
2975 			ensure_hotspot_frequency (self, s_wireless, ap);
2976 	
2977 		/* Build up the supplicant configuration */
2978 		config = build_supplicant_config (self, connection, ap);
2979 		if (config == NULL) {
2980 			nm_log_err (LOGD_DEVICE | LOGD_WIFI,
2981 			             "Activation (%s/wireless): couldn't build wireless configuration.",
2982 			             iface);
2983 			*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
2984 			goto out;
2985 		}
2986 	
2987 		/* Hook up error signal handler to capture association errors */
2988 		id = g_signal_connect (priv->supplicant.iface,
2989 		                       NM_SUPPLICANT_INTERFACE_CONNECTION_ERROR,
2990 		                       G_CALLBACK (supplicant_iface_connection_error_cb),
2991 		                       self);
2992 		priv->supplicant.iface_error_id = id;
2993 	
2994 		if (!nm_supplicant_interface_set_config (priv->supplicant.iface, config)) {
2995 			nm_log_err (LOGD_DEVICE | LOGD_WIFI,
2996 			            "Activation (%s/wireless): couldn't send wireless "
2997 			            "configuration to the supplicant.", iface);
2998 			*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
2999 			goto out;
3000 		}
3001 	
3002 		if (!start_supplicant_connection_timeout (self)) {
3003 			*reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED;
3004 			goto out;
3005 		}
3006 	
3007 		if (!priv->periodic_source_id)
3008 			priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update, self);
3009 	
3010 		/* We'll get stage3 started when the supplicant connects */
3011 		ret = NM_ACT_STAGE_RETURN_POSTPONE;
3012 	
3013 	out:
3014 		if (ret == NM_ACT_STAGE_RETURN_FAILURE)
3015 			cleanup_association_attempt (self, TRUE);
3016 	
3017 		if (config) {
3018 			/* Supplicant interface object refs the config; we no longer care about
3019 			 * it after this function.
3020 			 */
3021 			g_object_unref (config);
3022 		}
3023 		return ret;
3024 	}
3025 	
3026 	static void
3027 	ip4_config_pre_commit (NMDevice *device, NMIP4Config *config)
3028 	{
3029 		NMConnection *connection;
3030 		NMSettingWireless *s_wifi;
3031 		guint32 mtu;
3032 	
3033 		connection = nm_device_get_connection (device);
3034 		g_assert (connection);
3035 		s_wifi = nm_connection_get_setting_wireless (connection);
3036 		g_assert (s_wifi);
3037 	
3038 		/* MTU override */
3039 		mtu = nm_setting_wireless_get_mtu (s_wifi);
3040 		if (mtu)
3041 			nm_ip4_config_set_mtu (config, mtu);
3042 	}
3043 	
3044 	static gboolean
3045 	is_static_wep (NMAccessPoint *ap, NMConnection *connection)
3046 	{
3047 		NM80211ApFlags flags;
3048 		NM80211ApSecurityFlags wpa_flags, rsn_flags;
3049 		NMSettingWirelessSecurity *s_wsec;
3050 		const char *key_mgmt;
3051 	
3052 		g_return_val_if_fail (ap != NULL, FALSE);
3053 		g_return_val_if_fail (connection != NULL, FALSE);
3054 	
3055 		flags = nm_ap_get_flags (ap);
3056 		wpa_flags = nm_ap_get_wpa_flags (ap);
3057 		rsn_flags = nm_ap_get_rsn_flags (ap);
3058 	
3059 		if (   (flags & NM_802_11_AP_FLAGS_PRIVACY)
3060 		    && (wpa_flags == NM_802_11_AP_SEC_NONE)
3061 		    && (rsn_flags == NM_802_11_AP_SEC_NONE)) {
3062 			s_wsec = nm_connection_get_setting_wireless_security (connection);
3063 			if (s_wsec) {
3064 				key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
3065 				if (g_strcmp0 (key_mgmt, "none") == 0)
3066 					return TRUE;
3067 			}
3068 		}
3069 	
3070 		return FALSE;
3071 	}
3072 	
3073 	static NMActStageReturn
3074 	handle_ip_config_timeout (NMDeviceWifi *self,
3075 	                          NMConnection *connection,
3076 	                          gboolean may_fail,
3077 	                          gboolean *chain_up,
3078 	                          NMDeviceStateReason *reason)
3079 	{
3080 		NMAccessPoint *ap;
3081 		NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE;
3082 	
3083 		g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE);
3084 	
3085 		if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) {
3086 			*chain_up = TRUE;
3087 			return ret;
3088 		}
3089 	
3090 		ap = nm_device_wifi_get_activation_ap (self);
3091 		g_assert (ap);
3092 	
3093 		/* If IP configuration times out and it's a static WEP connection, that
3094 		 * usually means the WEP key is wrong.  WEP's Open System auth mode has
3095 		 * no provision for figuring out if the WEP key is wrong, so you just have
3096 		 * to wait for DHCP to fail to figure it out.  For all other WiFi security
3097 		 * types (open, WPA, 802.1x, etc) if the secrets/certs were wrong the
3098 		 * connection would have failed before IP configuration.
3099 		 */
3100 		if (is_static_wep (ap, connection) && (may_fail == FALSE)) {
3101 			/* Activation failed, we must have bad encryption key */
3102 			nm_log_warn (LOGD_DEVICE | LOGD_WIFI,
3103 			             "Activation (%s/wireless): could not get IP configuration for "
3104 			             "connection '%s'.",
3105 			             nm_device_get_iface (NM_DEVICE (self)),
3106 			             nm_connection_get_id (connection));
3107 	
3108 			ret = handle_auth_or_fail (self, NULL, TRUE);
3109 			if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
3110 				nm_log_info (LOGD_DEVICE | LOGD_WIFI,
3111 				             "Activation (%s/wireless): asking for new secrets",
3112 				             nm_device_get_iface (NM_DEVICE (self)));
3113 			} else {
3114 				*reason = NM_DEVICE_STATE_REASON_NO_SECRETS;
3115 			}
3116 		} else {
3117 			/* Not static WEP or failure allowed; let superclass handle it */
3118 			*chain_up = TRUE;
3119 		}
3120 	
3121 		return ret;
3122 	}
3123 	
3124 	
3125 	static NMActStageReturn
3126 	act_stage4_ip4_config_timeout (NMDevice *dev, NMDeviceStateReason *reason)
3127 	{
3128 		NMConnection *connection;
3129 		NMSettingIP4Config *s_ip4;
3130 		gboolean may_fail = FALSE, chain_up = FALSE;
3131 		NMActStageReturn ret;
3132 	
3133 		connection = nm_device_get_connection (dev);
3134 		g_assert (connection);
3135 	
3136 		s_ip4 = nm_connection_get_setting_ip4_config (connection);
3137 		may_fail = nm_setting_ip4_config_get_may_fail (s_ip4);
3138 	
3139 		ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
3140 		if (chain_up)
3141 			ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip4_config_timeout (dev, reason);
3142 	
3143 		return ret;
3144 	}
3145 	
3146 	static NMActStageReturn
3147 	act_stage4_ip6_config_timeout (NMDevice *dev, NMDeviceStateReason *reason)
3148 	{
3149 		NMConnection *connection;
3150 		NMSettingIP6Config *s_ip6;
3151 		gboolean may_fail = FALSE, chain_up = FALSE;
3152 		NMActStageReturn ret;
3153 	
3154 		connection = nm_device_get_connection (dev);
3155 		g_assert (connection);
3156 	
3157 		s_ip6 = nm_connection_get_setting_ip6_config (connection);
3158 		may_fail = nm_setting_ip6_config_get_may_fail (s_ip6);
3159 	
3160 		ret = handle_ip_config_timeout (NM_DEVICE_WIFI (dev), connection, may_fail, &chain_up, reason);
3161 		if (chain_up)
3162 			ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage4_ip6_config_timeout (dev, reason);
3163 	
3164 		return ret;
3165 	}
3166 	
3167 	static void
3168 	activation_success_handler (NMDevice *dev)
3169 	{
3170 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
3171 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
3172 		NMAccessPoint *ap;
3173 		struct ether_addr bssid = { {0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
3174 		NMAccessPoint *tmp_ap;
3175 		NMActRequest *req;
3176 		NMConnection *connection;
3177 	
3178 		req = nm_device_get_act_request (dev);
3179 		g_assert (req);
3180 	
3181 		connection = nm_act_request_get_connection (req);
3182 		g_assert (connection);
3183 	
3184 		/* Clear wireless secrets tries on success */
3185 		g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
3186 	
3187 		ap = nm_device_wifi_get_activation_ap (self);
3188 	
3189 		/* If the AP isn't fake, it was found in the scan list and all its
3190 		 * details are known.
3191 		 */
3192 		if (!nm_ap_get_fake (ap))
3193 			goto done;
3194 	
3195 		/* If the activate AP was fake, it probably won't have a BSSID at all.
3196 		 * But if activation was successful, the card will know the BSSID.  Grab
3197 		 * the BSSID off the card and fill in the BSSID of the activation AP.
3198 		 */
3199 		wifi_utils_get_bssid (priv->wifi_data, &bssid);
3200 		if (!nm_ethernet_address_is_valid (nm_ap_get_address (ap)))
3201 			nm_ap_set_address (ap, &bssid);
3202 		if (!nm_ap_get_freq (ap))
3203 			nm_ap_set_freq (ap, wifi_utils_get_freq (priv->wifi_data));
3204 		if (!nm_ap_get_max_bitrate (ap))
3205 			nm_ap_set_max_bitrate (ap, wifi_utils_get_rate (priv->wifi_data));
3206 	
3207 		tmp_ap = get_active_ap (self, ap, TRUE);
3208 		if (tmp_ap) {
3209 			const GByteArray *ssid = nm_ap_get_ssid (tmp_ap);
3210 	
3211 			/* Found a better match in the scan list than the fake AP.  Use it
3212 			 * instead.
3213 			 */
3214 	
3215 			/* If the better match was a hidden AP, update it's SSID */
3216 			if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len))
3217 				nm_ap_set_ssid (tmp_ap, nm_ap_get_ssid (ap));
3218 	
3219 			nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
3220 			                                          nm_ap_get_dbus_path (tmp_ap));
3221 	
3222 			priv->ap_list = g_slist_remove (priv->ap_list, ap);
3223 			g_object_unref (ap);
3224 		}
3225 	
3226 	done:
3227 		periodic_update (self);
3228 	
3229 		/* Update seen BSSIDs cache with the connected AP */
3230 		update_seen_bssids_cache (self, priv->current_ap);
3231 	
3232 		/* Reset scan interval to something reasonable */
3233 		priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2);
3234 	}
3235 	
3236 	static void
3237 	activation_failure_handler (NMDevice *dev)
3238 	{
3239 		NMDeviceWifi *self = NM_DEVICE_WIFI (dev);
3240 		NMAccessPoint *ap;
3241 		NMConnection *connection;
3242 	
3243 		connection = nm_device_get_connection (dev);
3244 		g_assert (connection);
3245 	
3246 		/* Clear wireless secrets tries on failure */
3247 		g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL);
3248 	
3249 		if ((ap = nm_device_wifi_get_activation_ap (self))) {
3250 			if (nm_ap_get_fake (ap)) {
3251 				/* Fake APs are ones that don't show up in scans,
3252 				 * but which the user explicitly attempted to connect to.
3253 				 * However, if we fail on one of these, remove it from the
3254 				 * list because we don't have any scan or capability info
3255 				 * for it, and they are pretty much useless.
3256 				 */
3257 				remove_access_point (self, ap, TRUE);
3258 			}
3259 		}
3260 	}
3261 	
3262 	static gboolean
3263 	can_interrupt_activation (NMDevice *dev)
3264 	{
3265 		if (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH)
3266 			return TRUE;
3267 	
3268 		return FALSE;
3269 	}
3270 	
3271 	static void
3272 	device_state_changed (NMDevice *device,
3273 	                      NMDeviceState new_state,
3274 	                      NMDeviceState old_state,
3275 	                      NMDeviceStateReason reason)
3276 	{
3277 		NMDeviceWifi *self = NM_DEVICE_WIFI (device);
3278 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
3279 		gboolean clear_aps = FALSE;
3280 	
3281 		if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) {
3282 			/* Clean up the supplicant interface because in these states the
3283 			 * device cannot be used.
3284 			 */
3285 			if (priv->supplicant.iface)
3286 				supplicant_interface_release (self);
3287 	
3288 			if (priv->periodic_source_id) {
3289 				g_source_remove (priv->periodic_source_id);
3290 				priv->periodic_source_id = 0;
3291 			}
3292 	
3293 			cleanup_association_attempt (self, TRUE);
3294 			set_active_ap (self, NULL);
3295 			remove_all_aps (self);
3296 		}
3297 	
3298 		/* Start or stop the rfkill poll worker for ipw cards */
3299 		if (priv->ipw_rfkill_path) {
3300 			if (new_state > NM_DEVICE_STATE_UNMANAGED) {
3301 				if (!priv->ipw_rfkill_id)
3302 					priv->ipw_rfkill_id = g_timeout_add_seconds (3, ipw_rfkill_state_work, self);
3303 			} else if (new_state <= NM_DEVICE_STATE_UNMANAGED) {
3304 				if (priv->ipw_rfkill_id) {
3305 					g_source_remove (priv->ipw_rfkill_id);
3306 					priv->ipw_rfkill_id = 0;
3307 				}
3308 			}
3309 		}
3310 	
3311 		switch (new_state) {
3312 		case NM_DEVICE_STATE_UNMANAGED:
3313 			clear_aps = TRUE;
3314 			break;
3315 		case NM_DEVICE_STATE_UNAVAILABLE:
3316 			/* If the device is enabled and the supplicant manager is ready,
3317 			 * acquire a supplicant interface and transition to DISCONNECTED because
3318 			 * the device is now ready to use.
3319 			 */
3320 			if (priv->enabled && (nm_device_get_firmware_missing (device) == FALSE)) {
3321 				if (!priv->supplicant.iface)
3322 					supplicant_interface_acquire (self);
3323 			}
3324 			clear_aps = TRUE;
3325 			break;
3326 		case NM_DEVICE_STATE_NEED_AUTH:
3327 			if (priv->supplicant.iface)
3328 				nm_supplicant_interface_disconnect (priv->supplicant.iface);
3329 			break;
3330 		case NM_DEVICE_STATE_ACTIVATED:
3331 			activation_success_handler (device);
3332 			break;
3333 		case NM_DEVICE_STATE_FAILED:
3334 			activation_failure_handler (device);
3335 			break;
3336 		case NM_DEVICE_STATE_DISCONNECTED:
3337 			/* Kick off a scan to get latest results */
3338 			priv->scan_interval = SCAN_INTERVAL_MIN;
3339 			cancel_pending_scan (self);
3340 			request_wireless_scan (self);
3341 			break;
3342 		default:
3343 			break;
3344 		}
3345 	
3346 		if (clear_aps)
3347 			remove_all_aps (self);
3348 	}
3349 	
3350 	NMAccessPoint *
3351 	nm_device_wifi_get_activation_ap (NMDeviceWifi *self)
3352 	{
3353 		NMActRequest *req;
3354 		const char *ap_path;
3355 	
3356 		g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NULL);
3357 	
3358 		req = nm_device_get_act_request (NM_DEVICE (self));
3359 		if (!req)
3360 			return NULL;
3361 	
3362 		ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
3363 	
3364 		return ap_path ? get_ap_by_path (self, ap_path) : NULL;
3365 	}
3366 	
3367 	static void
3368 	set_enabled (NMDevice *device, gboolean enabled)
3369 	{
3370 		NMDeviceWifi *self = NM_DEVICE_WIFI (device);
3371 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
3372 		NMDeviceState state;
3373 	
3374 		if (priv->enabled == enabled)
3375 			return;
3376 	
3377 		priv->enabled = enabled;
3378 	
3379 		nm_log_dbg (LOGD_WIFI, "(%s): device now %s",
3380 		            nm_device_get_iface (NM_DEVICE (device)),
3381 		            enabled ? "enabled" : "disabled");
3382 	
3383 		state = nm_device_get_state (NM_DEVICE (self));
3384 		if (state < NM_DEVICE_STATE_UNAVAILABLE) {
3385 			nm_log_dbg (LOGD_WIFI, "(%s): %s blocked by UNMANAGED state",
3386 			            enabled ? "enable" : "disable",
3387 			            nm_device_get_iface (NM_DEVICE (device)));
3388 			return;
3389 		}
3390 	
3391 		if (enabled) {
3392 			gboolean no_firmware = FALSE;
3393 	
3394 			if (state != NM_DEVICE_STATE_UNAVAILABLE)
3395 				nm_log_warn (LOGD_CORE, "not in expected unavailable state!");
3396 	
3397 			if (!nm_device_bring_up (NM_DEVICE (self), TRUE, &no_firmware)) {
3398 				nm_log_dbg (LOGD_WIFI, "(%s): enable blocked by failure to bring device up",
3399 				            nm_device_get_iface (NM_DEVICE (device)));
3400 	
3401 				if (no_firmware)
3402 					nm_device_set_firmware_missing (NM_DEVICE (device), TRUE);
3403 				else {
3404 					/* The device sucks, or the kernel was lying to us about the killswitch state */
3405 					priv->enabled = FALSE;
3406 				}
3407 				return;
3408 			}
3409 	
3410 			/* Re-initialize the supplicant interface and wait for it to be ready */
3411 			if (priv->supplicant.iface)
3412 				supplicant_interface_release (self);
3413 			supplicant_interface_acquire (self);
3414 	
3415 			nm_log_dbg (LOGD_WIFI, "(%s): enable waiting on supplicant state",
3416 			            nm_device_get_iface (NM_DEVICE (device)));
3417 		} else {
3418 			nm_device_state_changed (NM_DEVICE (self),
3419 			                         NM_DEVICE_STATE_UNAVAILABLE,
3420 			                         NM_DEVICE_STATE_REASON_NONE);
3421 			nm_device_take_down (NM_DEVICE (self), TRUE);
3422 		}
3423 	}
3424 	
3425 	/********************************************************************/
3426 	
3427 	NMDevice *
3428 	nm_device_wifi_new (NMPlatformLink *platform_device)
3429 	{
3430 		g_return_val_if_fail (platform_device != NULL, NULL);
3431 	
3432 		return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI,
3433 		                                  NM_DEVICE_PLATFORM_DEVICE, platform_device,
3434 		                                  NM_DEVICE_TYPE_DESC, "802.11 WiFi",
3435 		                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI,
3436 		                                  NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN,
3437 		                                  NULL);
3438 	}
3439 	
3440 	static void
3441 	nm_device_wifi_init (NMDeviceWifi *self)
3442 	{
3443 		NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA;
3444 	}
3445 	
3446 	static void
3447 	dispose (GObject *object)
3448 	{
3449 		NMDeviceWifi *self = NM_DEVICE_WIFI (object);
3450 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
3451 	
3452 		if (priv->disposed) {
3453 			G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
3454 			return;
3455 		}
3456 	
3457 		priv->disposed = TRUE;
3458 	
3459 		if (priv->periodic_source_id) {
3460 			g_source_remove (priv->periodic_source_id);
3461 			priv->periodic_source_id = 0;
3462 		}
3463 	
3464 		cleanup_association_attempt (self, TRUE);
3465 		supplicant_interface_release (self);
3466 	
3467 		if (priv->supplicant.mgr) {
3468 			g_object_unref (priv->supplicant.mgr);
3469 			priv->supplicant.mgr = NULL;
3470 		}
3471 	
3472 		set_active_ap (self, NULL);
3473 		remove_all_aps (self);
3474 	
3475 		if (priv->wifi_data)
3476 			wifi_utils_deinit (priv->wifi_data);
3477 	
3478 		g_free (priv->ipw_rfkill_path);
3479 		if (priv->ipw_rfkill_id) {
3480 			g_source_remove (priv->ipw_rfkill_id);
3481 			priv->ipw_rfkill_id = 0;
3482 		}
3483 	
3484 		G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object);
3485 	}
3486 	
3487 	static void
3488 	get_property (GObject *object, guint prop_id,
3489 	              GValue *value, GParamSpec *pspec)
3490 	{
3491 		NMDeviceWifi *device = NM_DEVICE_WIFI (object);
3492 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
3493 	
3494 		switch (prop_id) {
3495 		case PROP_PERM_HW_ADDRESS:
3496 			g_value_take_string (value, nm_utils_hwaddr_ntoa (&priv->perm_hw_addr, ARPHRD_ETHER));
3497 			break;
3498 		case PROP_MODE:
3499 			g_value_set_uint (value, priv->mode);
3500 			break;
3501 		case PROP_BITRATE:
3502 			g_value_set_uint (value, priv->rate);
3503 			break;
3504 		case PROP_CAPABILITIES:
3505 			g_value_set_uint (value, priv->capabilities);
3506 			break;
3507 		case PROP_ACTIVE_ACCESS_POINT:
3508 			if (priv->current_ap)
3509 				g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap));
3510 			else
3511 				g_value_set_boxed (value, "/");
3512 			break;
3513 		case PROP_SCANNING:
3514 			g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->supplicant.iface));
3515 			break;
3516 		case PROP_IPW_RFKILL_STATE:
3517 			g_value_set_uint (value, nm_device_wifi_get_ipw_rfkill_state (device));
3518 			break;
3519 		default:
3520 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3521 			break;
3522 		}
3523 	}
3524 	
3525 	static void
3526 	set_property (GObject *object, guint prop_id,
3527 	              const GValue *value, GParamSpec *pspec)
3528 	{
3529 		NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
3530 	
3531 		switch (prop_id) {
3532 		case PROP_IPW_RFKILL_STATE:
3533 			/* construct only */
3534 			priv->ipw_rfkill_state = g_value_get_uint (value);
3535 			break;
3536 		default:
3537 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3538 			break;
3539 		}
3540 	}
3541 	
3542 	
3543 	static void
3544 	nm_device_wifi_class_init (NMDeviceWifiClass *klass)
3545 	{
3546 		GObjectClass *object_class = G_OBJECT_CLASS (klass);
3547 		NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
3548 	
3549 		g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate));
3550 	
3551 		object_class->constructor = constructor;
3552 		object_class->get_property = get_property;
3553 		object_class->set_property = set_property;
3554 		object_class->dispose = dispose;
3555 	
3556 		parent_class->bring_up = bring_up;
3557 		parent_class->update_permanent_hw_address = update_permanent_hw_address;
3558 		parent_class->update_initial_hw_address = update_initial_hw_address;
3559 		parent_class->can_auto_connect = can_auto_connect;
3560 		parent_class->is_available = is_available;
3561 		parent_class->check_connection_compatible = check_connection_compatible;
3562 		parent_class->check_connection_available = check_connection_available;
3563 		parent_class->complete_connection = complete_connection;
3564 		parent_class->set_enabled = set_enabled;
3565 	
3566 		parent_class->act_stage1_prepare = act_stage1_prepare;
3567 		parent_class->act_stage2_config = act_stage2_config;
3568 		parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
3569 		parent_class->act_stage4_ip4_config_timeout = act_stage4_ip4_config_timeout;
3570 		parent_class->act_stage4_ip6_config_timeout = act_stage4_ip6_config_timeout;
3571 		parent_class->deactivate = deactivate;
3572 		parent_class->can_interrupt_activation = can_interrupt_activation;
3573 	
3574 		parent_class->state_changed = device_state_changed;
3575 	
3576 		klass->scanning_allowed = scanning_allowed;
3577 	
3578 		/* Properties */
3579 		g_object_class_install_property (object_class, PROP_PERM_HW_ADDRESS,
3580 			g_param_spec_string (NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS,
3581 			                     "Permanent MAC Address",
3582 			                     "Permanent hardware MAC address",
3583 			                     NULL,
3584 			                     G_PARAM_READABLE));
3585 	
3586 		g_object_class_install_property (object_class, PROP_MODE,
3587 			g_param_spec_uint (NM_DEVICE_WIFI_MODE,
3588 			                   "Mode",
3589 			                   "Mode",
3590 			                   NM_802_11_MODE_UNKNOWN,
3591 			                   NM_802_11_MODE_AP,
3592 			                   NM_802_11_MODE_INFRA,
3593 			                   G_PARAM_READABLE));
3594 	
3595 		g_object_class_install_property (object_class, PROP_BITRATE,
3596 			g_param_spec_uint (NM_DEVICE_WIFI_BITRATE,
3597 			                   "Bitrate",
3598 			                   "Bitrate",
3599 			                   0, G_MAXUINT32, 0,
3600 			                   G_PARAM_READABLE));
3601 	
3602 		g_object_class_install_property (object_class, PROP_ACTIVE_ACCESS_POINT,
3603 			g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT,
3604 			                    "Active access point",
3605 			                    "Currently active access point",
3606 			                    DBUS_TYPE_G_OBJECT_PATH,
3607 			                    G_PARAM_READABLE));
3608 	
3609 		g_object_class_install_property (object_class, PROP_CAPABILITIES,
3610 			g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES,
3611 			                   "Wireless Capabilities",
3612 			                   "Wireless Capabilities",
3613 			                   0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE,
3614 			                   G_PARAM_READABLE));
3615 	
3616 		g_object_class_install_property (object_class, PROP_SCANNING,
3617 			g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING,
3618 			                   "Scanning",
3619 			                   "Scanning",
3620 			                   FALSE,
3621 			                   G_PARAM_READABLE));
3622 	
3623 		g_object_class_install_property (object_class, PROP_IPW_RFKILL_STATE,
3624 			g_param_spec_uint (NM_DEVICE_WIFI_IPW_RFKILL_STATE,
3625 			                   "IpwRfkillState",
3626 			                   "ipw rf-kill state",
3627 			                   RFKILL_UNBLOCKED, RFKILL_HARD_BLOCKED, RFKILL_UNBLOCKED,
3628 			                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
3629 	
3630 		/* Signals */
3631 		signals[ACCESS_POINT_ADDED] =
3632 			g_signal_new ("access-point-added",
3633 			              G_OBJECT_CLASS_TYPE (object_class),
3634 			              G_SIGNAL_RUN_FIRST,
3635 			              G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added),
3636 			              NULL, NULL, NULL,
3637 			              G_TYPE_NONE, 1,
3638 			              G_TYPE_OBJECT);
3639 	
3640 		signals[ACCESS_POINT_REMOVED] =
3641 			g_signal_new ("access-point-removed",
3642 			              G_OBJECT_CLASS_TYPE (object_class),
3643 			              G_SIGNAL_RUN_FIRST,
3644 			              0,
3645 			              NULL, NULL, NULL,
3646 			              G_TYPE_NONE, 1,
3647 			              G_TYPE_OBJECT);
3648 	
3649 		signals[HIDDEN_AP_FOUND] =
3650 			g_signal_new ("hidden-ap-found",
3651 			              G_OBJECT_CLASS_TYPE (object_class),
3652 			              G_SIGNAL_RUN_FIRST,
3653 			              G_STRUCT_OFFSET (NMDeviceWifiClass, hidden_ap_found),
3654 			              NULL, NULL, NULL,
3655 			              G_TYPE_NONE, 1,
3656 			              G_TYPE_OBJECT);
3657 	
3658 		signals[SCANNING_ALLOWED] =
3659 			g_signal_new ("scanning-allowed",
3660 			              G_OBJECT_CLASS_TYPE (object_class),
3661 			              G_SIGNAL_RUN_LAST,
3662 			              G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_allowed),
3663 			              scanning_allowed_accumulator, NULL, NULL,
3664 			              G_TYPE_BOOLEAN, 0);
3665 	
3666 		nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
3667 		                                        G_TYPE_FROM_CLASS (klass),
3668 		                                        &dbus_glib_nm_device_wifi_object_info);
3669 	
3670 		dbus_g_error_domain_register (NM_WIFI_ERROR, NULL, NM_TYPE_WIFI_ERROR);
3671 	}
3672 	
3673 	
3674