aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-06-19 12:55:06 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-06-19 12:55:12 -0400
commitf93beba705842af466e7c916b39630cacb40e9c6 (patch)
tree0f296f0b1e419eb4fc242e188376a4fdd80085fa
parent52874a5e3917dde3b081521b014d6e4b226aacff (diff)
parent3a5a423bb958ad22eeccca66c533e85bf69ba10e (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>
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/iface.c28
-rw-r--r--net/mac80211/mlme.c87
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/mac80211/util.c4
-rw-r--r--net/wireless/nl80211.c11
7 files changed, 122 insertions, 21 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 18ba7ed3ef0b..93120de776f0 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 00d71e9a8fb8..8412a303993a 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/iface.c b/net/mac80211/iface.c
index 7cabaf261fed..a2a8250e2f84 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -159,10 +159,11 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
159 return 0; 159 return 0;
160} 160}
161 161
162static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, 162static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
163 bool check_dup) 163 bool check_dup)
164{ 164{
165 struct ieee80211_sub_if_data *sdata; 165 struct ieee80211_local *local = sdata->local;
166 struct ieee80211_sub_if_data *iter;
166 u64 new, mask, tmp; 167 u64 new, mask, tmp;
167 u8 *m; 168 u8 *m;
168 int ret = 0; 169 int ret = 0;
@@ -184,12 +185,15 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
184 return ret; 185 return ret;
185 186
186 mutex_lock(&local->iflist_mtx); 187 mutex_lock(&local->iflist_mtx);
187 list_for_each_entry(sdata, &local->interfaces, list) { 188 list_for_each_entry(iter, &local->interfaces, list) {
188 if (sdata->vif.type == NL80211_IFTYPE_MONITOR && 189 if (iter == sdata)
189 !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
190 continue; 190 continue;
191 191
192 m = sdata->vif.addr; 192 if (iter->vif.type == NL80211_IFTYPE_MONITOR &&
193 !(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE))
194 continue;
195
196 m = iter->vif.addr;
193 tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | 197 tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
194 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | 198 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
195 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); 199 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@ -218,7 +222,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
218 !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE)) 222 !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
219 check_dup = false; 223 check_dup = false;
220 224
221 ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup); 225 ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup);
222 if (ret) 226 if (ret)
223 return ret; 227 return ret;
224 228
@@ -1503,7 +1507,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
1503 break; 1507 break;
1504 } 1508 }
1505 1509
1510 /*
1511 * Pick address of existing interface in case user changed
1512 * MAC address manually, default to perm_addr.
1513 */
1506 m = local->hw.wiphy->perm_addr; 1514 m = local->hw.wiphy->perm_addr;
1515 list_for_each_entry(sdata, &local->interfaces, list) {
1516 if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
1517 continue;
1518 m = sdata->vif.addr;
1519 break;
1520 }
1507 start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | 1521 start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
1508 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | 1522 ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
1509 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); 1523 ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
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
2659static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, 2732static 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 dbbcd57b0fc6..30d58d2d13e2 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -621,7 +621,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
621 if (rates[i].idx < 0) 621 if (rates[i].idx < 0)
622 break; 622 break;
623 623
624 rate_idx_match_mask(&rates[i], sband, mask, chan_width, 624 rate_idx_match_mask(&rates[i], sband, chan_width, mask,
625 mcs_mask); 625 mcs_mask);
626 } 626 }
627} 627}
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;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4ab1ffa9df11..f8ffb9a59c83 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1527,12 +1527,17 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1527 struct cfg80211_registered_device *dev; 1527 struct cfg80211_registered_device *dev;
1528 s64 filter_wiphy = -1; 1528 s64 filter_wiphy = -1;
1529 bool split = false; 1529 bool split = false;
1530 struct nlattr **tb = nl80211_fam.attrbuf; 1530 struct nlattr **tb;
1531 int res; 1531 int res;
1532 1532
1533 /* will be zeroed in nlmsg_parse() */
1534 tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL);
1535 if (!tb)
1536 return -ENOMEM;
1537
1533 rtnl_lock(); 1538 rtnl_lock();
1534 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1539 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1535 tb, nl80211_fam.maxattr, nl80211_policy); 1540 tb, NL80211_ATTR_MAX, nl80211_policy);
1536 if (res == 0) { 1541 if (res == 0) {
1537 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; 1542 split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
1538 if (tb[NL80211_ATTR_WIPHY]) 1543 if (tb[NL80211_ATTR_WIPHY])
@@ -1546,6 +1551,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1546 netdev = dev_get_by_index(sock_net(skb->sk), ifidx); 1551 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1547 if (!netdev) { 1552 if (!netdev) {
1548 rtnl_unlock(); 1553 rtnl_unlock();
1554 kfree(tb);
1549 return -ENODEV; 1555 return -ENODEV;
1550 } 1556 }
1551 if (netdev->ieee80211_ptr) { 1557 if (netdev->ieee80211_ptr) {
@@ -1556,6 +1562,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1556 dev_put(netdev); 1562 dev_put(netdev);
1557 } 1563 }
1558 } 1564 }
1565 kfree(tb);
1559 1566
1560 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 1567 list_for_each_entry(dev, &cfg80211_rdev_list, list) {
1561 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 1568 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))