aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-12 14:26:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-12 14:26:48 -0400
commit6bb7aabf73401c9cfca26c71ccae1e3d6e1640d5 (patch)
tree515bdf9875c34447c51ed7512749bbaa93641588 /net
parent8c8d2017ba25c510ddf093419048460db1109bc4 (diff)
parent795d855d56c6d172f50a974f603ba923ac93ee76 (diff)
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/mlme.c87
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/mac80211/util.c4
5 files changed, 92 insertions, 12 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1a89c80e6407..4fdb306e42e0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1057,6 +1057,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1057 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1057 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
1058 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 1058 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
1059 1059
1060 if (sdata->wdev.cac_started) {
1061 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
1062 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
1063 GFP_KERNEL);
1064 }
1065
1060 drv_stop_ap(sdata->local, sdata); 1066 drv_stop_ap(sdata->local, sdata);
1061 1067
1062 /* free all potentially still buffered bcast frames */ 1068 /* free all potentially still buffered bcast frames */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 44be28cfc6c4..9ca8e3278cc0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1497,10 +1497,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
1497 ieee80211_tx_skb_tid(sdata, skb, 7); 1497 ieee80211_tx_skb_tid(sdata, skb, 7);
1498} 1498}
1499 1499
1500u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 1500u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1501 struct ieee802_11_elems *elems, 1501 struct ieee802_11_elems *elems,
1502 u64 filter, u32 crc); 1502 u64 filter, u32 crc);
1503static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, 1503static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
1504 bool action,
1504 struct ieee802_11_elems *elems) 1505 struct ieee802_11_elems *elems)
1505{ 1506{
1506 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); 1507 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a8c2130c8ba4..741448b30825 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2522,8 +2522,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2522 u16 capab_info, aid; 2522 u16 capab_info, aid;
2523 struct ieee802_11_elems elems; 2523 struct ieee802_11_elems elems;
2524 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 2524 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2525 const struct cfg80211_bss_ies *bss_ies = NULL;
2526 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
2525 u32 changed = 0; 2527 u32 changed = 0;
2526 int err; 2528 int err;
2529 bool ret;
2527 2530
2528 /* AssocResp and ReassocResp have identical structure */ 2531 /* AssocResp and ReassocResp have identical structure */
2529 2532
@@ -2555,21 +2558,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2555 ifmgd->aid = aid; 2558 ifmgd->aid = aid;
2556 2559
2557 /* 2560 /*
2561 * Some APs are erroneously not including some information in their
2562 * (re)association response frames. Try to recover by using the data
2563 * from the beacon or probe response. This seems to afflict mobile
2564 * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
2565 * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
2566 */
2567 if ((assoc_data->wmm && !elems.wmm_param) ||
2568 (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2569 (!elems.ht_cap_elem || !elems.ht_operation)) ||
2570 (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2571 (!elems.vht_cap_elem || !elems.vht_operation))) {
2572 const struct cfg80211_bss_ies *ies;
2573 struct ieee802_11_elems bss_elems;
2574
2575 rcu_read_lock();
2576 ies = rcu_dereference(cbss->ies);
2577 if (ies)
2578 bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
2579 GFP_ATOMIC);
2580 rcu_read_unlock();
2581 if (!bss_ies)
2582 return false;
2583
2584 ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
2585 false, &bss_elems);
2586 if (assoc_data->wmm &&
2587 !elems.wmm_param && bss_elems.wmm_param) {
2588 elems.wmm_param = bss_elems.wmm_param;
2589 sdata_info(sdata,
2590 "AP bug: WMM param missing from AssocResp\n");
2591 }
2592
2593 /*
2594 * Also check if we requested HT/VHT, otherwise the AP doesn't
2595 * have to include the IEs in the (re)association response.
2596 */
2597 if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
2598 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2599 elems.ht_cap_elem = bss_elems.ht_cap_elem;
2600 sdata_info(sdata,
2601 "AP bug: HT capability missing from AssocResp\n");
2602 }
2603 if (!elems.ht_operation && bss_elems.ht_operation &&
2604 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2605 elems.ht_operation = bss_elems.ht_operation;
2606 sdata_info(sdata,
2607 "AP bug: HT operation missing from AssocResp\n");
2608 }
2609 if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
2610 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2611 elems.vht_cap_elem = bss_elems.vht_cap_elem;
2612 sdata_info(sdata,
2613 "AP bug: VHT capa missing from AssocResp\n");
2614 }
2615 if (!elems.vht_operation && bss_elems.vht_operation &&
2616 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2617 elems.vht_operation = bss_elems.vht_operation;
2618 sdata_info(sdata,
2619 "AP bug: VHT operation missing from AssocResp\n");
2620 }
2621 }
2622
2623 /*
2558 * We previously checked these in the beacon/probe response, so 2624 * We previously checked these in the beacon/probe response, so
2559 * they should be present here. This is just a safety net. 2625 * they should be present here. This is just a safety net.
2560 */ 2626 */
2561 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && 2627 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2562 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { 2628 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
2563 sdata_info(sdata, 2629 sdata_info(sdata,
2564 "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); 2630 "HT AP is missing WMM params or HT capability/operation\n");
2565 return false; 2631 ret = false;
2632 goto out;
2566 } 2633 }
2567 2634
2568 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && 2635 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2569 (!elems.vht_cap_elem || !elems.vht_operation)) { 2636 (!elems.vht_cap_elem || !elems.vht_operation)) {
2570 sdata_info(sdata, 2637 sdata_info(sdata,
2571 "VHT AP is missing VHT capability/operation in AssocResp\n"); 2638 "VHT AP is missing VHT capability/operation\n");
2572 return false; 2639 ret = false;
2640 goto out;
2573 } 2641 }
2574 2642
2575 mutex_lock(&sdata->local->sta_mtx); 2643 mutex_lock(&sdata->local->sta_mtx);
@@ -2580,7 +2648,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2580 sta = sta_info_get(sdata, cbss->bssid); 2648 sta = sta_info_get(sdata, cbss->bssid);
2581 if (WARN_ON(!sta)) { 2649 if (WARN_ON(!sta)) {
2582 mutex_unlock(&sdata->local->sta_mtx); 2650 mutex_unlock(&sdata->local->sta_mtx);
2583 return false; 2651 ret = false;
2652 goto out;
2584 } 2653 }
2585 2654
2586 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; 2655 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
@@ -2633,7 +2702,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2633 sta->sta.addr); 2702 sta->sta.addr);
2634 WARN_ON(__sta_info_destroy(sta)); 2703 WARN_ON(__sta_info_destroy(sta));
2635 mutex_unlock(&sdata->local->sta_mtx); 2704 mutex_unlock(&sdata->local->sta_mtx);
2636 return false; 2705 ret = false;
2706 goto out;
2637 } 2707 }
2638 2708
2639 mutex_unlock(&sdata->local->sta_mtx); 2709 mutex_unlock(&sdata->local->sta_mtx);
@@ -2673,7 +2743,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2673 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 2743 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
2674 ieee80211_sta_reset_beacon_monitor(sdata); 2744 ieee80211_sta_reset_beacon_monitor(sdata);
2675 2745
2676 return true; 2746 ret = true;
2747 out:
2748 kfree(bss_ies);
2749 return ret;
2677} 2750}
2678 2751
2679static enum rx_mgmt_action __must_check 2752static enum rx_mgmt_action __must_check
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index d3f414fe67e0..a02bef35b134 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
615 if (rates[i].idx < 0) 615 if (rates[i].idx < 0)
616 break; 616 break;
617 617
618 rate_idx_match_mask(&rates[i], sband, mask, chan_width, 618 rate_idx_match_mask(&rates[i], sband, chan_width, mask,
619 mcs_mask); 619 mcs_mask);
620 } 620 }
621} 621}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27e07150eb46..72e6292955bb 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -661,12 +661,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
661} 661}
662EXPORT_SYMBOL(ieee80211_queue_delayed_work); 662EXPORT_SYMBOL(ieee80211_queue_delayed_work);
663 663
664u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 664u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
665 struct ieee802_11_elems *elems, 665 struct ieee802_11_elems *elems,
666 u64 filter, u32 crc) 666 u64 filter, u32 crc)
667{ 667{
668 size_t left = len; 668 size_t left = len;
669 u8 *pos = start; 669 const u8 *pos = start;
670 bool calc_crc = filter != 0; 670 bool calc_crc = filter != 0;
671 DECLARE_BITMAP(seen_elems, 256); 671 DECLARE_BITMAP(seen_elems, 256);
672 const u8 *ie; 672 const u8 *ie;