aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorRon Rindjunsky <ron.rindjunsky@intel.com>2008-08-08 20:02:19 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 16:30:00 -0400
commit9859b81eaeb8d48563b5fbd90215c0ae606455a3 (patch)
tree4d4a68d4033801c4a58653634f18eeb8b091aead /net/mac80211
parent32ddf0718590f410d5f18cb4fcda419f4aeefc57 (diff)
mac80211: add direct probe before association
This patch adds a direct probe request as first step in the association flow if data we have is not up to date. Motivation of this step is to make sure that the bss information we have is correct, since last scan could have been done a while ago, and beacons do not fully answer this need as there are potential differences between them and probe responses (e.g. WMM parameter element) Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-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 {