~ubuntu-branches/ubuntu/precise/wpasupplicant/precise-proposed

« back to all changes in this revision

Viewing changes to wpa_supplicant/sme.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2013-06-12 15:57:50 UTC
  • Revision ID: package-import@ubuntu.com-20130612155750-go9lgylcef8n3f2f
Tags: 0.7.3-6ubuntu2.2
* Multiple patches to reduce the number of disconnections for WPA Enterprise
  roaming and Opportunistic Key Caching. (LP: #1187524)
* In debian/patches:
  0001-sme-fix-retry-after-auth-assoc-timeout-failure.patch,
  0002-sme-optimize-recovery-from-common-load-balancing-mechanisms.patch,
  0003-sme-blacklist-bss-on-first-failure-if-only-a-*.patch,
  0004-sme-extend-load-balancing-optimization-in-bss-blacklisting.patch,
  0005-sme-optimize-recovery-from-association-command-failures.patch,
  0006-sme-add-timers-for-authentication-and-association.patch,
  0007-sme-nl80211-set-cipher-suites.patch:
  Cherry-pick patches fixing SME (Session Management Entity) for the nl80211
  driver, which works as a basis for the OKC patches.
* In debian/patches:
  0001-pmkokc-Set-portValid-TRUE-on-association-for-driver-based-4.patch,
  0002-pmkokc-Clear-WPA-and-EAPOL-state-machine-config-pointer-on-.patch,
  0003-pmkokc-Clear-driver-PMKSA-cache-entry-on-PMKSA-cache-expira.patch,
  0004-pmkokc-Flush-PMKSA-cache-entries-and-invalidate-EAP-state-o.patch,
  0005-pmkokc-Fix-proactive_key_caching-configuration-to-WPA-code.patch,
  0006-pmkokc-RSN-Add-a-debug-message-when-considing-addition-of-O.patch,
  0007-pmkokc-Clear-OKC-based-PMKSA-caching-entries-if-PMK-is-chan.patch,
  0008-pmkokc-Move-wpa_sm_remove_pmkid-call-to-PMKSA-cache-entry-f.patch,
  0009-pmkokc-Use-PMKSA-cache-entries-with-only-a-single-network-c.patch,
  0010-pmkokc-PMKSA-Do-not-evict-active-cache-entry-when-adding-ne.patch,
  0011-pmkokc-PMKSA-Set-cur_pmksa-pointer-during-initial-associati.patch,
  0012-pmkokc-PMKSA-make-deauthentication-due-to-cache-entry-remov.patch,
  0013-pmkokc-PMKSA-update-current-cache-entry-due-to-association-.patch:
  Cherry-pick patches to properly do OKC (Opportunistic Key Caching) which
  helps maintaining connectivity on networks secured with WPA Enterprise,
  especially on nl80211-based drivers -- these patches require SME, and add
  or fix key caching and handling of the cache entries.
* debian/patches/force-enable-okc.patch: force Opportunistic Key Caching to
  be enabled.
* debian/patches/less-aggressive-roaming.patch: use less aggressive roaming
  settings to avoid switching to another AP unnecessarily, when the actual
  signal level difference is small.
* debian/patches/wpa_supplicant-dbus-null-error.patch: Don't send NULL to
  dbus_message_new_error().
* debian/patches/0001-nl80211-Fix-UNSPEC-signal-quality-reporting.patch: fix
  marking qual as invalid rather than signal level.
* debian/patches/wpa_supplicant-squelch-driver-disconnect-spam.patch: recover
  cleanly from streams of disconnect messages (like on iwl3945).
* debian/patches/wpa_supplicant-assoc-timeout.patch: increase association
  timeouts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include "includes.h"
16
16
 
17
17
#include "common.h"
 
18
#include "utils/eloop.h"
18
19
#include "common/ieee802_11_defs.h"
19
20
#include "common/ieee802_11_common.h"
20
21
#include "eapol_supp/eapol_supp_sm.h"
32
33
#include "scan.h"
33
34
#include "sme.h"
34
35
 
 
36
#define SME_AUTH_TIMEOUT 5
 
37
#define SME_ASSOC_TIMEOUT 5
 
38
 
 
39
static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
 
40
static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
 
41
 
 
42
 
35
43
void sme_authenticate(struct wpa_supplicant *wpa_s,
36
44
                      struct wpa_bss *bss, struct wpa_ssid *ssid)
37
45
{
232
240
                return;
233
241
        }
234
242
 
235
 
        /* TODO: add timeout on authentication */
 
243
        eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
 
244
                               NULL);
236
245
 
237
246
        /*
238
247
         * Association will be started based on the authentication event from
271
280
        wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
272
281
                    data->auth.ies, data->auth.ies_len);
273
282
 
 
283
        eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 
284
 
274
285
        if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
275
286
                wpa_printf(MSG_DEBUG, "SME: Authentication failed (status "
276
287
                           "code %d)", data->auth.status_code);
278
289
                if (data->auth.status_code !=
279
290
                    WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
280
291
                    wpa_s->sme.auth_alg == data->auth.auth_type ||
281
 
                    wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP)
 
292
                    wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
 
293
                        wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
282
294
                        return;
 
295
                }
283
296
 
284
297
                switch (data->auth.auth_type) {
285
298
                case WLAN_AUTH_OPEN:
333
346
        params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
334
347
                wpa_s->sme.assoc_req_ie : NULL;
335
348
        params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
 
349
        params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher);
 
350
        params.group_suite = cipher_suite2driver(wpa_s->group_cipher);
336
351
#ifdef CONFIG_IEEE80211R
337
352
        if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
338
353
                params.wpa_ie = wpa_s->sme.ft_ies;
369
384
        if (wpa_drv_associate(wpa_s, &params) < 0) {
370
385
                wpa_msg(wpa_s, MSG_INFO, "Association request to the driver "
371
386
                        "failed");
372
 
                wpa_supplicant_req_scan(wpa_s, 5, 0);
 
387
                wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 
388
                os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
373
389
                return;
374
390
        }
375
391
 
376
 
        /* TODO: add timeout on association */
 
392
        eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
 
393
                               NULL);
377
394
}
378
395
 
379
396
 
401
418
}
402
419
 
403
420
 
 
421
static void sme_deauth(struct wpa_supplicant *wpa_s)
 
422
{
 
423
        int bssid_changed;
 
424
 
 
425
        bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
 
426
 
 
427
        if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
 
428
                                   WLAN_REASON_DEAUTH_LEAVING) < 0) {
 
429
                wpa_msg(wpa_s, MSG_INFO,
 
430
                        "Deauth request to the driver failed");
 
431
        }
 
432
        wpa_s->sme.prev_bssid_set = 0;
 
433
 
 
434
        wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
 
435
        wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 
436
        os_memset(wpa_s->bssid, 0, ETH_ALEN);
 
437
        os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 
438
        if (bssid_changed)
 
439
                wpas_notify_bssid_changed(wpa_s);
 
440
}
 
441
 
 
442
 
404
443
void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
405
444
                            union wpa_event_data *data)
406
445
{
407
 
        int bssid_changed;
408
 
        int timeout = 5000;
409
 
 
410
446
        wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: "
411
447
                   "status code %d", MAC2STR(wpa_s->pending_bssid),
412
448
                   data->assoc_reject.status_code);
413
449
 
414
 
        bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
 
450
        eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
415
451
 
416
452
        /*
417
453
         * For now, unconditionally terminate the previous authentication. In
420
456
         * benefit from using the previous authentication, so this could be
421
457
         * optimized in the future.
422
458
         */
423
 
        if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
424
 
                                   WLAN_REASON_DEAUTH_LEAVING) < 0) {
425
 
                wpa_msg(wpa_s, MSG_INFO,
426
 
                        "Deauth request to the driver failed");
427
 
        }
428
 
        wpa_s->sme.prev_bssid_set = 0;
429
 
 
430
 
        if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) {
431
 
                struct wpa_blacklist *b;
432
 
                b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid);
433
 
                if (b && b->count < 3) {
434
 
                        /*
435
 
                         * Speed up next attempt if there could be other APs
436
 
                         * that could accept association.
437
 
                         */
438
 
                        timeout = 100;
439
 
                }
440
 
        }
441
 
        wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
442
 
        os_memset(wpa_s->bssid, 0, ETH_ALEN);
443
 
        os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
444
 
        if (bssid_changed)
445
 
                wpas_notify_bssid_changed(wpa_s);
446
 
 
447
 
        /*
448
 
         * TODO: if more than one possible AP is available in scan results,
449
 
         * could try the other ones before requesting a new scan.
450
 
         */
451
 
        wpa_supplicant_req_scan(wpa_s, timeout / 1000,
452
 
                                1000 * (timeout % 1000));
 
459
        sme_deauth(wpa_s);
453
460
}
454
461
 
455
462
 
457
464
                              union wpa_event_data *data)
458
465
{
459
466
        wpa_printf(MSG_DEBUG, "SME: Authentication timed out");
460
 
        wpa_supplicant_req_scan(wpa_s, 5, 0);
 
467
        wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
461
468
}
462
469
 
463
470
 
465
472
                               union wpa_event_data *data)
466
473
{
467
474
        wpa_printf(MSG_DEBUG, "SME: Association timed out");
 
475
        wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
468
476
        wpa_supplicant_mark_disassoc(wpa_s);
469
 
        wpa_supplicant_req_scan(wpa_s, 5, 0);
470
477
}
471
478
 
472
479
 
488
495
                                       WLAN_REASON_DEAUTH_LEAVING);
489
496
        }
490
497
}
 
498
 
 
499
 
 
500
static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
 
501
{
 
502
        struct wpa_supplicant *wpa_s = eloop_ctx;
 
503
        if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
 
504
                wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
 
505
                sme_deauth(wpa_s);
 
506
        }
 
507
}
 
508
 
 
509
 
 
510
static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
 
511
{
 
512
        struct wpa_supplicant *wpa_s = eloop_ctx;
 
513
        if (wpa_s->wpa_state == WPA_ASSOCIATING) {
 
514
                wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
 
515
                sme_deauth(wpa_s);
 
516
        }
 
517
}
 
518
 
 
519
 
 
520
void sme_state_changed(struct wpa_supplicant *wpa_s)
 
521
{
 
522
        /* Make sure timers are cleaned up appropriately. */
 
523
        if (wpa_s->wpa_state != WPA_ASSOCIATING)
 
524
                eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
 
525
        if (wpa_s->wpa_state != WPA_AUTHENTICATING)
 
526
                eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 
527
}
 
528
 
 
529
 
 
530
void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
 
531
                                       const u8 *prev_pending_bssid)
 
532
{
 
533
        /*
 
534
         * mac80211-workaround to force deauth on failed auth cmd,
 
535
         * requires us to remain in authenticating state to allow the
 
536
         * second authentication attempt to be continued properly.
 
537
         */
 
538
        wpa_printf(MSG_DEBUG, "SME: Allow pending authentication "
 
539
                "to proceed after disconnection event");
 
540
        wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
 
541
        os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
 
542
 
 
543
        /*
 
544
         * Re-arm authentication timer in case auth fails for whatever reason.
 
545
         */
 
546
        eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 
547
        eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
 
548
                               NULL);
 
549
}
 
550
 
 
551
 
 
552
void sme_deinit(struct wpa_supplicant *wpa_s)
 
553
{
 
554
        os_free(wpa_s->sme.ft_ies);
 
555
        wpa_s->sme.ft_ies = NULL;
 
556
        wpa_s->sme.ft_ies_len = 0;
 
557
 
 
558
        eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
 
559
        eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
 
560
}