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), ×tamp)) {
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), ×tamp))
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