diff options
-rw-r--r-- | net/mac80211/ieee80211_i.h | 9 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 79 |
2 files changed, 73 insertions, 15 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c6de3156930c..8361054fb7cf 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -100,7 +100,7 @@ struct ieee80211_sta_bss { | |||
100 | u64 timestamp; | 100 | u64 timestamp; |
101 | int beacon_int; | 101 | int beacon_int; |
102 | 102 | ||
103 | bool probe_resp; | 103 | unsigned long last_probe_resp; |
104 | unsigned long last_update; | 104 | unsigned long last_update; |
105 | 105 | ||
106 | /* during assocation, we save an ERP value from a probe response so | 106 | /* during assocation, we save an ERP value from a probe response so |
@@ -294,12 +294,14 @@ struct mesh_config { | |||
294 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 294 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
295 | /* flags for MLME request*/ | 295 | /* flags for MLME request*/ |
296 | #define IEEE80211_STA_REQ_SCAN 0 | 296 | #define IEEE80211_STA_REQ_SCAN 0 |
297 | #define IEEE80211_STA_REQ_AUTH 1 | 297 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 |
298 | #define IEEE80211_STA_REQ_RUN 2 | 298 | #define IEEE80211_STA_REQ_AUTH 2 |
299 | #define IEEE80211_STA_REQ_RUN 3 | ||
299 | 300 | ||
300 | /* flags used for setting mlme state */ | 301 | /* flags used for setting mlme state */ |
301 | enum ieee80211_sta_mlme_state { | 302 | enum ieee80211_sta_mlme_state { |
302 | IEEE80211_STA_MLME_DISABLED, | 303 | IEEE80211_STA_MLME_DISABLED, |
304 | IEEE80211_STA_MLME_DIRECT_PROBE, | ||
303 | IEEE80211_STA_MLME_AUTHENTICATE, | 305 | IEEE80211_STA_MLME_AUTHENTICATE, |
304 | IEEE80211_STA_MLME_ASSOCIATE, | 306 | IEEE80211_STA_MLME_ASSOCIATE, |
305 | IEEE80211_STA_MLME_ASSOCIATED, | 307 | IEEE80211_STA_MLME_ASSOCIATED, |
@@ -362,6 +364,7 @@ struct ieee80211_if_sta { | |||
362 | struct sk_buff_head skb_queue; | 364 | struct sk_buff_head skb_queue; |
363 | 365 | ||
364 | int assoc_scan_tries; /* number of scans done pre-association */ | 366 | int assoc_scan_tries; /* number of scans done pre-association */ |
367 | int direct_probe_tries; /* retries for direct probes */ | ||
365 | int auth_tries; /* retries for auth req */ | 368 | int auth_tries; /* retries for auth req */ |
366 | int assoc_tries; /* retries for assoc req */ | 369 | int assoc_tries; /* retries for assoc req */ |
367 | 370 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e821d1ac5b00..84999791a332 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -595,8 +595,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
595 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 595 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
596 | struct ieee80211_if_sta *ifsta, int deauth) | 596 | struct ieee80211_if_sta *ifsta, int deauth) |
597 | { | 597 | { |
598 | if (deauth) | 598 | if (deauth) { |
599 | ifsta->direct_probe_tries = 0; | ||
599 | ifsta->auth_tries = 0; | 600 | ifsta->auth_tries = 0; |
601 | } | ||
600 | ifsta->assoc_scan_tries = 0; | 602 | ifsta->assoc_scan_tries = 0; |
601 | ifsta->assoc_tries = 0; | 603 | ifsta->assoc_tries = 0; |
602 | ieee80211_set_associated(sdata, ifsta, 0); | 604 | ieee80211_set_associated(sdata, ifsta, 0); |
@@ -654,6 +656,36 @@ static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
654 | ieee80211_sta_tx(sdata, skb, encrypt); | 656 | ieee80211_sta_tx(sdata, skb, encrypt); |
655 | } | 657 | } |
656 | 658 | ||
659 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | ||
660 | struct ieee80211_if_sta *ifsta) | ||
661 | { | ||
662 | DECLARE_MAC_BUF(mac); | ||
663 | |||
664 | ifsta->direct_probe_tries++; | ||
665 | if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { | ||
666 | printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", | ||
667 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | ||
668 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
669 | return; | ||
670 | } | ||
671 | |||
672 | printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", | ||
673 | sdata->dev->name, print_mac(mac, ifsta->bssid), | ||
674 | ifsta->direct_probe_tries); | ||
675 | |||
676 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | ||
677 | |||
678 | set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); | ||
679 | |||
680 | /* Direct probe is sent to broadcast address as some APs | ||
681 | * will not answer to direct packet in unassociated state. | ||
682 | */ | ||
683 | ieee80211_send_probe_req(sdata, NULL, | ||
684 | ifsta->ssid, ifsta->ssid_len); | ||
685 | |||
686 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | ||
687 | } | ||
688 | |||
657 | 689 | ||
658 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | 690 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, |
659 | struct ieee80211_if_sta *ifsta) | 691 | struct ieee80211_if_sta *ifsta) |
@@ -1947,7 +1979,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1947 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || | 1979 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || |
1948 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || | 1980 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || |
1949 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { | 1981 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1950 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | 1982 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1951 | mod_timer(&ifsta->timer, jiffies + | 1983 | mod_timer(&ifsta->timer, jiffies + |
1952 | IEEE80211_RETRY_AUTH_INTERVAL); | 1984 | IEEE80211_RETRY_AUTH_INTERVAL); |
1953 | } | 1985 | } |
@@ -2540,8 +2572,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2540 | struct ieee80211_mgmt *mgmt, | 2572 | struct ieee80211_mgmt *mgmt, |
2541 | size_t len, | 2573 | size_t len, |
2542 | struct ieee80211_rx_status *rx_status, | 2574 | struct ieee80211_rx_status *rx_status, |
2543 | struct ieee802_11_elems *elems, | 2575 | struct ieee802_11_elems *elems) |
2544 | int beacon) | ||
2545 | { | 2576 | { |
2546 | struct ieee80211_local *local = sdata->local; | 2577 | struct ieee80211_local *local = sdata->local; |
2547 | int freq, clen; | 2578 | int freq, clen; |
@@ -2549,6 +2580,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2549 | struct sta_info *sta; | 2580 | struct sta_info *sta; |
2550 | u64 beacon_timestamp, rx_timestamp; | 2581 | u64 beacon_timestamp, rx_timestamp; |
2551 | struct ieee80211_channel *channel; | 2582 | struct ieee80211_channel *channel; |
2583 | bool beacon = ieee80211_is_beacon(mgmt->frame_control); | ||
2552 | DECLARE_MAC_BUF(mac); | 2584 | DECLARE_MAC_BUF(mac); |
2553 | DECLARE_MAC_BUF(mac2); | 2585 | DECLARE_MAC_BUF(mac2); |
2554 | 2586 | ||
@@ -2705,15 +2737,14 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2705 | bss->signal = rx_status->signal; | 2737 | bss->signal = rx_status->signal; |
2706 | bss->noise = rx_status->noise; | 2738 | bss->noise = rx_status->noise; |
2707 | bss->qual = rx_status->qual; | 2739 | bss->qual = rx_status->qual; |
2708 | if (!beacon && !bss->probe_resp) | 2740 | if (!beacon) |
2709 | bss->probe_resp = true; | 2741 | bss->last_probe_resp = jiffies; |
2710 | |||
2711 | /* | 2742 | /* |
2712 | * In STA mode, the remaining parameters should not be overridden | 2743 | * In STA mode, the remaining parameters should not be overridden |
2713 | * by beacons because they're not necessarily accurate there. | 2744 | * by beacons because they're not necessarily accurate there. |
2714 | */ | 2745 | */ |
2715 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 2746 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && |
2716 | bss->probe_resp && beacon) { | 2747 | bss->last_probe_resp && beacon) { |
2717 | ieee80211_rx_bss_put(local, bss); | 2748 | ieee80211_rx_bss_put(local, bss); |
2718 | return; | 2749 | return; |
2719 | } | 2750 | } |
@@ -2868,6 +2899,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2868 | { | 2899 | { |
2869 | size_t baselen; | 2900 | size_t baselen; |
2870 | struct ieee802_11_elems elems; | 2901 | struct ieee802_11_elems elems; |
2902 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
2871 | 2903 | ||
2872 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | 2904 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) |
2873 | return; /* ignore ProbeResp to foreign address */ | 2905 | return; /* ignore ProbeResp to foreign address */ |
@@ -2879,7 +2911,15 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2879 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 2911 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
2880 | &elems); | 2912 | &elems); |
2881 | 2913 | ||
2882 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 0); | 2914 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2915 | |||
2916 | /* direct probe may be part of the association flow */ | ||
2917 | if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, | ||
2918 | &ifsta->request)) { | ||
2919 | printk(KERN_DEBUG "%s direct probe responded\n", | ||
2920 | sdata->dev->name); | ||
2921 | ieee80211_authenticate(sdata, ifsta); | ||
2922 | } | ||
2883 | } | 2923 | } |
2884 | 2924 | ||
2885 | 2925 | ||
@@ -2902,7 +2942,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2902 | 2942 | ||
2903 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | 2943 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
2904 | 2944 | ||
2905 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, 1); | 2945 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2906 | 2946 | ||
2907 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 2947 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) |
2908 | return; | 2948 | return; |
@@ -3329,7 +3369,8 @@ void ieee80211_sta_work(struct work_struct *work) | |||
3329 | mesh_path_start_discovery(sdata); | 3369 | mesh_path_start_discovery(sdata); |
3330 | #endif | 3370 | #endif |
3331 | 3371 | ||
3332 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | 3372 | if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && |
3373 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | ||
3333 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && | 3374 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && |
3334 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { | 3375 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { |
3335 | if (ifsta->scan_ssid_len) | 3376 | if (ifsta->scan_ssid_len) |
@@ -3349,6 +3390,9 @@ void ieee80211_sta_work(struct work_struct *work) | |||
3349 | switch (ifsta->state) { | 3390 | switch (ifsta->state) { |
3350 | case IEEE80211_STA_MLME_DISABLED: | 3391 | case IEEE80211_STA_MLME_DISABLED: |
3351 | break; | 3392 | break; |
3393 | case IEEE80211_STA_MLME_DIRECT_PROBE: | ||
3394 | ieee80211_direct_probe(sdata, ifsta); | ||
3395 | break; | ||
3352 | case IEEE80211_STA_MLME_AUTHENTICATE: | 3396 | case IEEE80211_STA_MLME_AUTHENTICATE: |
3353 | ieee80211_authenticate(sdata, ifsta); | 3397 | ieee80211_authenticate(sdata, ifsta); |
3354 | break; | 3398 | break; |
@@ -3408,6 +3452,7 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, | |||
3408 | ifsta->auth_transaction = -1; | 3452 | ifsta->auth_transaction = -1; |
3409 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 3453 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
3410 | ifsta->assoc_scan_tries = 0; | 3454 | ifsta->assoc_scan_tries = 0; |
3455 | ifsta->direct_probe_tries = 0; | ||
3411 | ifsta->auth_tries = 0; | 3456 | ifsta->auth_tries = 0; |
3412 | ifsta->assoc_tries = 0; | 3457 | ifsta->assoc_tries = 0; |
3413 | netif_carrier_off(sdata->dev); | 3458 | netif_carrier_off(sdata->dev); |
@@ -3509,8 +3554,18 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, | |||
3509 | selected->ssid_len); | 3554 | selected->ssid_len); |
3510 | ieee80211_sta_set_bssid(sdata, selected->bssid); | 3555 | ieee80211_sta_set_bssid(sdata, selected->bssid); |
3511 | ieee80211_sta_def_wmm_params(sdata, selected, 0); | 3556 | ieee80211_sta_def_wmm_params(sdata, selected, 0); |
3557 | |||
3558 | /* Send out direct probe if no probe resp was received or | ||
3559 | * the one we have is outdated | ||
3560 | */ | ||
3561 | if (!selected->last_probe_resp || | ||
3562 | time_after(jiffies, selected->last_probe_resp | ||
3563 | + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
3564 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | ||
3565 | else | ||
3566 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
3567 | |||
3512 | ieee80211_rx_bss_put(local, selected); | 3568 | ieee80211_rx_bss_put(local, selected); |
3513 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
3514 | ieee80211_sta_reset_auth(sdata, ifsta); | 3569 | ieee80211_sta_reset_auth(sdata, ifsta); |
3515 | return 0; | 3570 | return 0; |
3516 | } else { | 3571 | } else { |