diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-06-19 12:55:06 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-06-19 12:55:12 -0400 |
commit | f93beba705842af466e7c916b39630cacb40e9c6 (patch) | |
tree | 0f296f0b1e419eb4fc242e188376a4fdd80085fa /net/mac80211/mlme.c | |
parent | 52874a5e3917dde3b081521b014d6e4b226aacff (diff) | |
parent | 3a5a423bb958ad22eeccca66c533e85bf69ba10e (diff) |
Merge remote-tracking branch 'mac80211/master' into HEAD
Merge mac80211 to avoid conflicts with the nl80211 attrbuf
changes.
Conflicts:
net/mac80211/iface.c
net/wireless/nl80211.c
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 87 |
1 files changed, 80 insertions, 7 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e0939eb79060..34d54fe81483 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2502,8 +2502,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2502 | u16 capab_info, aid; | 2502 | u16 capab_info, aid; |
2503 | struct ieee802_11_elems elems; | 2503 | struct ieee802_11_elems elems; |
2504 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 2504 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
2505 | const struct cfg80211_bss_ies *bss_ies = NULL; | ||
2506 | struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; | ||
2505 | u32 changed = 0; | 2507 | u32 changed = 0; |
2506 | int err; | 2508 | int err; |
2509 | bool ret; | ||
2507 | 2510 | ||
2508 | /* AssocResp and ReassocResp have identical structure */ | 2511 | /* AssocResp and ReassocResp have identical structure */ |
2509 | 2512 | ||
@@ -2535,21 +2538,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2535 | ifmgd->aid = aid; | 2538 | ifmgd->aid = aid; |
2536 | 2539 | ||
2537 | /* | 2540 | /* |
2541 | * Some APs are erroneously not including some information in their | ||
2542 | * (re)association response frames. Try to recover by using the data | ||
2543 | * from the beacon or probe response. This seems to afflict mobile | ||
2544 | * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", | ||
2545 | * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. | ||
2546 | */ | ||
2547 | if ((assoc_data->wmm && !elems.wmm_param) || | ||
2548 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | ||
2549 | (!elems.ht_cap_elem || !elems.ht_operation)) || | ||
2550 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | ||
2551 | (!elems.vht_cap_elem || !elems.vht_operation))) { | ||
2552 | const struct cfg80211_bss_ies *ies; | ||
2553 | struct ieee802_11_elems bss_elems; | ||
2554 | |||
2555 | rcu_read_lock(); | ||
2556 | ies = rcu_dereference(cbss->ies); | ||
2557 | if (ies) | ||
2558 | bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, | ||
2559 | GFP_ATOMIC); | ||
2560 | rcu_read_unlock(); | ||
2561 | if (!bss_ies) | ||
2562 | return false; | ||
2563 | |||
2564 | ieee802_11_parse_elems(bss_ies->data, bss_ies->len, | ||
2565 | false, &bss_elems); | ||
2566 | if (assoc_data->wmm && | ||
2567 | !elems.wmm_param && bss_elems.wmm_param) { | ||
2568 | elems.wmm_param = bss_elems.wmm_param; | ||
2569 | sdata_info(sdata, | ||
2570 | "AP bug: WMM param missing from AssocResp\n"); | ||
2571 | } | ||
2572 | |||
2573 | /* | ||
2574 | * Also check if we requested HT/VHT, otherwise the AP doesn't | ||
2575 | * have to include the IEs in the (re)association response. | ||
2576 | */ | ||
2577 | if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && | ||
2578 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
2579 | elems.ht_cap_elem = bss_elems.ht_cap_elem; | ||
2580 | sdata_info(sdata, | ||
2581 | "AP bug: HT capability missing from AssocResp\n"); | ||
2582 | } | ||
2583 | if (!elems.ht_operation && bss_elems.ht_operation && | ||
2584 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
2585 | elems.ht_operation = bss_elems.ht_operation; | ||
2586 | sdata_info(sdata, | ||
2587 | "AP bug: HT operation missing from AssocResp\n"); | ||
2588 | } | ||
2589 | if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && | ||
2590 | !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
2591 | elems.vht_cap_elem = bss_elems.vht_cap_elem; | ||
2592 | sdata_info(sdata, | ||
2593 | "AP bug: VHT capa missing from AssocResp\n"); | ||
2594 | } | ||
2595 | if (!elems.vht_operation && bss_elems.vht_operation && | ||
2596 | !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
2597 | elems.vht_operation = bss_elems.vht_operation; | ||
2598 | sdata_info(sdata, | ||
2599 | "AP bug: VHT operation missing from AssocResp\n"); | ||
2600 | } | ||
2601 | } | ||
2602 | |||
2603 | /* | ||
2538 | * We previously checked these in the beacon/probe response, so | 2604 | * We previously checked these in the beacon/probe response, so |
2539 | * they should be present here. This is just a safety net. | 2605 | * they should be present here. This is just a safety net. |
2540 | */ | 2606 | */ |
2541 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | 2607 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && |
2542 | (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { | 2608 | (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { |
2543 | sdata_info(sdata, | 2609 | sdata_info(sdata, |
2544 | "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); | 2610 | "HT AP is missing WMM params or HT capability/operation\n"); |
2545 | return false; | 2611 | ret = false; |
2612 | goto out; | ||
2546 | } | 2613 | } |
2547 | 2614 | ||
2548 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | 2615 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && |
2549 | (!elems.vht_cap_elem || !elems.vht_operation)) { | 2616 | (!elems.vht_cap_elem || !elems.vht_operation)) { |
2550 | sdata_info(sdata, | 2617 | sdata_info(sdata, |
2551 | "VHT AP is missing VHT capability/operation in AssocResp\n"); | 2618 | "VHT AP is missing VHT capability/operation\n"); |
2552 | return false; | 2619 | ret = false; |
2620 | goto out; | ||
2553 | } | 2621 | } |
2554 | 2622 | ||
2555 | mutex_lock(&sdata->local->sta_mtx); | 2623 | mutex_lock(&sdata->local->sta_mtx); |
@@ -2560,7 +2628,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2560 | sta = sta_info_get(sdata, cbss->bssid); | 2628 | sta = sta_info_get(sdata, cbss->bssid); |
2561 | if (WARN_ON(!sta)) { | 2629 | if (WARN_ON(!sta)) { |
2562 | mutex_unlock(&sdata->local->sta_mtx); | 2630 | mutex_unlock(&sdata->local->sta_mtx); |
2563 | return false; | 2631 | ret = false; |
2632 | goto out; | ||
2564 | } | 2633 | } |
2565 | 2634 | ||
2566 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | 2635 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
@@ -2613,7 +2682,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2613 | sta->sta.addr); | 2682 | sta->sta.addr); |
2614 | WARN_ON(__sta_info_destroy(sta)); | 2683 | WARN_ON(__sta_info_destroy(sta)); |
2615 | mutex_unlock(&sdata->local->sta_mtx); | 2684 | mutex_unlock(&sdata->local->sta_mtx); |
2616 | return false; | 2685 | ret = false; |
2686 | goto out; | ||
2617 | } | 2687 | } |
2618 | 2688 | ||
2619 | mutex_unlock(&sdata->local->sta_mtx); | 2689 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -2653,7 +2723,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2653 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 2723 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
2654 | ieee80211_sta_reset_beacon_monitor(sdata); | 2724 | ieee80211_sta_reset_beacon_monitor(sdata); |
2655 | 2725 | ||
2656 | return true; | 2726 | ret = true; |
2727 | out: | ||
2728 | kfree(bss_ies); | ||
2729 | return ret; | ||
2657 | } | 2730 | } |
2658 | 2731 | ||
2659 | static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | 2732 | static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, |