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 | |
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>
-rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 5 | ||||
-rw-r--r-- | net/mac80211/iface.c | 28 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 87 | ||||
-rw-r--r-- | net/mac80211/rate.c | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 11 |
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 | ||
1516 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, | 1516 | u32 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); |
1519 | static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, | 1519 | static 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 | ||
162 | static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr, | 162 | static 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 | ||
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, |
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 | } |
668 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | 668 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); |
669 | 669 | ||
670 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, | 670 | u32 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))) |