aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h9
-rw-r--r--net/mac80211/mlme.c79
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 */
301enum ieee80211_sta_mlme_state { 302enum 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,
595static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 595static 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
659static 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
658static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, 690static 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 {