aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
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/mlme.c
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/mlme.c')
-rw-r--r--net/mac80211/mlme.c79
1 files changed, 67 insertions, 12 deletions
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 {