aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-06-18 14:04:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-06-18 14:04:51 -0400
commit9d1059c2481885ba7a2af02fc1bf87cae88b302a (patch)
treeb9ff1d502017ea7939d26a99720801ffdbe2b3da /net/mac80211
parentc4d827c5ccc3a49227dbf9d4b248a2e86f388023 (diff)
parentfcb3701849957917a234a61b58ad70ed35c83eda (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Diffstat (limited to 'net/mac80211')
-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 64cf294c2b96..082f270b5912 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1071,6 +1071,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1071 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); 1071 clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
1072 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); 1072 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
1073 1073
1074 if (sdata->wdev.cac_started) {
1075 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
1076 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
1077 GFP_KERNEL);
1078 }
1079
1074 drv_stop_ap(sdata->local, sdata); 1080 drv_stop_ap(sdata->local, sdata);
1075 1081
1076 /* free all potentially still buffered bcast frames */ 1082 /* free all potentially still buffered bcast frames */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7a6f1a0207ec..f97cd9d9105f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1513,10 +1513,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
1513 ieee80211_tx_skb_tid(sdata, skb, 7); 1513 ieee80211_tx_skb_tid(sdata, skb, 7);
1514} 1514}
1515 1515
1516u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 1516u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
1517 struct ieee802_11_elems *elems, 1517 struct ieee802_11_elems *elems,
1518 u64 filter, u32 crc); 1518 u64 filter, u32 crc);
1519static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, 1519static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
1520 bool action,
1520 struct ieee802_11_elems *elems) 1521 struct ieee802_11_elems *elems)
1521{ 1522{
1522 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); 1523 ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ad9bb9e10cbb..9e49f557fa5c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2492,8 +2492,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2492 u16 capab_info, aid; 2492 u16 capab_info, aid;
2493 struct ieee802_11_elems elems; 2493 struct ieee802_11_elems elems;
2494 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 2494 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
2495 const struct cfg80211_bss_ies *bss_ies = NULL;
2496 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
2495 u32 changed = 0; 2497 u32 changed = 0;
2496 int err; 2498 int err;
2499 bool ret;
2497 2500
2498 /* AssocResp and ReassocResp have identical structure */ 2501 /* AssocResp and ReassocResp have identical structure */
2499 2502
@@ -2525,21 +2528,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2525 ifmgd->aid = aid; 2528 ifmgd->aid = aid;
2526 2529
2527 /* 2530 /*
2531 * Some APs are erroneously not including some information in their
2532 * (re)association response frames. Try to recover by using the data
2533 * from the beacon or probe response. This seems to afflict mobile
2534 * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
2535 * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
2536 */
2537 if ((assoc_data->wmm && !elems.wmm_param) ||
2538 (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2539 (!elems.ht_cap_elem || !elems.ht_operation)) ||
2540 (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2541 (!elems.vht_cap_elem || !elems.vht_operation))) {
2542 const struct cfg80211_bss_ies *ies;
2543 struct ieee802_11_elems bss_elems;
2544
2545 rcu_read_lock();
2546 ies = rcu_dereference(cbss->ies);
2547 if (ies)
2548 bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
2549 GFP_ATOMIC);
2550 rcu_read_unlock();
2551 if (!bss_ies)
2552 return false;
2553
2554 ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
2555 false, &bss_elems);
2556 if (assoc_data->wmm &&
2557 !elems.wmm_param && bss_elems.wmm_param) {
2558 elems.wmm_param = bss_elems.wmm_param;
2559 sdata_info(sdata,
2560 "AP bug: WMM param missing from AssocResp\n");
2561 }
2562
2563 /*
2564 * Also check if we requested HT/VHT, otherwise the AP doesn't
2565 * have to include the IEs in the (re)association response.
2566 */
2567 if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
2568 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2569 elems.ht_cap_elem = bss_elems.ht_cap_elem;
2570 sdata_info(sdata,
2571 "AP bug: HT capability missing from AssocResp\n");
2572 }
2573 if (!elems.ht_operation && bss_elems.ht_operation &&
2574 !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
2575 elems.ht_operation = bss_elems.ht_operation;
2576 sdata_info(sdata,
2577 "AP bug: HT operation missing from AssocResp\n");
2578 }
2579 if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
2580 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2581 elems.vht_cap_elem = bss_elems.vht_cap_elem;
2582 sdata_info(sdata,
2583 "AP bug: VHT capa missing from AssocResp\n");
2584 }
2585 if (!elems.vht_operation && bss_elems.vht_operation &&
2586 !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
2587 elems.vht_operation = bss_elems.vht_operation;
2588 sdata_info(sdata,
2589 "AP bug: VHT operation missing from AssocResp\n");
2590 }
2591 }
2592
2593 /*
2528 * We previously checked these in the beacon/probe response, so 2594 * We previously checked these in the beacon/probe response, so
2529 * they should be present here. This is just a safety net. 2595 * they should be present here. This is just a safety net.
2530 */ 2596 */
2531 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && 2597 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
2532 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { 2598 (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
2533 sdata_info(sdata, 2599 sdata_info(sdata,
2534 "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); 2600 "HT AP is missing WMM params or HT capability/operation\n");
2535 return false; 2601 ret = false;
2602 goto out;
2536 } 2603 }
2537 2604
2538 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && 2605 if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
2539 (!elems.vht_cap_elem || !elems.vht_operation)) { 2606 (!elems.vht_cap_elem || !elems.vht_operation)) {
2540 sdata_info(sdata, 2607 sdata_info(sdata,
2541 "VHT AP is missing VHT capability/operation in AssocResp\n"); 2608 "VHT AP is missing VHT capability/operation\n");
2542 return false; 2609 ret = false;
2610 goto out;
2543 } 2611 }
2544 2612
2545 mutex_lock(&sdata->local->sta_mtx); 2613 mutex_lock(&sdata->local->sta_mtx);
@@ -2550,7 +2618,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2550 sta = sta_info_get(sdata, cbss->bssid); 2618 sta = sta_info_get(sdata, cbss->bssid);
2551 if (WARN_ON(!sta)) { 2619 if (WARN_ON(!sta)) {
2552 mutex_unlock(&sdata->local->sta_mtx); 2620 mutex_unlock(&sdata->local->sta_mtx);
2553 return false; 2621 ret = false;
2622 goto out;
2554 } 2623 }
2555 2624
2556 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; 2625 sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
@@ -2603,7 +2672,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2603 sta->sta.addr); 2672 sta->sta.addr);
2604 WARN_ON(__sta_info_destroy(sta)); 2673 WARN_ON(__sta_info_destroy(sta));
2605 mutex_unlock(&sdata->local->sta_mtx); 2674 mutex_unlock(&sdata->local->sta_mtx);
2606 return false; 2675 ret = false;
2676 goto out;
2607 } 2677 }
2608 2678
2609 mutex_unlock(&sdata->local->sta_mtx); 2679 mutex_unlock(&sdata->local->sta_mtx);
@@ -2643,7 +2713,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
2643 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 2713 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
2644 ieee80211_sta_reset_beacon_monitor(sdata); 2714 ieee80211_sta_reset_beacon_monitor(sdata);
2645 2715
2646 return true; 2716 ret = true;
2717 out:
2718 kfree(bss_ies);
2719 return ret;
2647} 2720}
2648 2721
2649static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, 2722static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
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 5a6c1351d1d3..22654452a561 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -667,12 +667,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
667} 667}
668EXPORT_SYMBOL(ieee80211_queue_delayed_work); 668EXPORT_SYMBOL(ieee80211_queue_delayed_work);
669 669
670u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, 670u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
671 struct ieee802_11_elems *elems, 671 struct ieee802_11_elems *elems,
672 u64 filter, u32 crc) 672 u64 filter, u32 crc)
673{ 673{
674 size_t left = len; 674 size_t left = len;
675 u8 *pos = start; 675 const u8 *pos = start;
676 bool calc_crc = filter != 0; 676 bool calc_crc = filter != 0;
677 DECLARE_BITMAP(seen_elems, 256); 677 DECLARE_BITMAP(seen_elems, 256);
678 const u8 *ie; 678 const u8 *ie;