forked from Minki/linux
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>
This commit is contained in:
commit
f93beba705
@ -1071,6 +1071,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
|
|||||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||||
|
|
||||||
|
if (sdata->wdev.cac_started) {
|
||||||
|
cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
|
||||||
|
cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
|
||||||
|
GFP_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
drv_stop_ap(sdata->local, sdata);
|
drv_stop_ap(sdata->local, sdata);
|
||||||
|
|
||||||
/* free all potentially still buffered bcast frames */
|
/* free all potentially still buffered bcast frames */
|
||||||
|
@ -1513,10 +1513,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
|
|||||||
ieee80211_tx_skb_tid(sdata, skb, 7);
|
ieee80211_tx_skb_tid(sdata, skb, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
|
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
u64 filter, u32 crc);
|
u64 filter, u32 crc);
|
||||||
static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
|
static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
|
||||||
|
bool action,
|
||||||
struct ieee802_11_elems *elems)
|
struct ieee802_11_elems *elems)
|
||||||
{
|
{
|
||||||
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
|
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
|
||||||
|
@ -159,10 +159,11 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
|
static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
|
||||||
bool check_dup)
|
bool check_dup)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_sub_if_data *iter;
|
||||||
u64 new, mask, tmp;
|
u64 new, mask, tmp;
|
||||||
u8 *m;
|
u8 *m;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -184,12 +185,15 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
list_for_each_entry(sdata, &local->interfaces, list) {
|
list_for_each_entry(iter, &local->interfaces, list) {
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
|
if (iter == sdata)
|
||||||
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m = sdata->vif.addr;
|
if (iter->vif.type == NL80211_IFTYPE_MONITOR &&
|
||||||
|
!(iter->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m = iter->vif.addr;
|
||||||
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
((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)
|
|||||||
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
check_dup = false;
|
check_dup = false;
|
||||||
|
|
||||||
ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup);
|
ret = ieee80211_verify_mac(sdata, sa->sa_data, check_dup);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1503,7 +1507,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pick address of existing interface in case user changed
|
||||||
|
* MAC address manually, default to perm_addr.
|
||||||
|
*/
|
||||||
m = local->hw.wiphy->perm_addr;
|
m = local->hw.wiphy->perm_addr;
|
||||||
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||||
|
continue;
|
||||||
|
m = sdata->vif.addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
|
||||||
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||||
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
||||||
|
@ -2502,8 +2502,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
u16 capab_info, aid;
|
u16 capab_info, aid;
|
||||||
struct ieee802_11_elems elems;
|
struct ieee802_11_elems elems;
|
||||||
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
|
||||||
|
const struct cfg80211_bss_ies *bss_ies = NULL;
|
||||||
|
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
int err;
|
int err;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
/* AssocResp and ReassocResp have identical structure */
|
/* AssocResp and ReassocResp have identical structure */
|
||||||
|
|
||||||
@ -2534,6 +2537,69 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
|
|
||||||
ifmgd->aid = aid;
|
ifmgd->aid = aid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some APs are erroneously not including some information in their
|
||||||
|
* (re)association response frames. Try to recover by using the data
|
||||||
|
* from the beacon or probe response. This seems to afflict mobile
|
||||||
|
* 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
|
||||||
|
* "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
|
||||||
|
*/
|
||||||
|
if ((assoc_data->wmm && !elems.wmm_param) ||
|
||||||
|
(!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
||||||
|
(!elems.ht_cap_elem || !elems.ht_operation)) ||
|
||||||
|
(!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
||||||
|
(!elems.vht_cap_elem || !elems.vht_operation))) {
|
||||||
|
const struct cfg80211_bss_ies *ies;
|
||||||
|
struct ieee802_11_elems bss_elems;
|
||||||
|
|
||||||
|
rcu_read_lock();
|
||||||
|
ies = rcu_dereference(cbss->ies);
|
||||||
|
if (ies)
|
||||||
|
bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
|
||||||
|
GFP_ATOMIC);
|
||||||
|
rcu_read_unlock();
|
||||||
|
if (!bss_ies)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
|
||||||
|
false, &bss_elems);
|
||||||
|
if (assoc_data->wmm &&
|
||||||
|
!elems.wmm_param && bss_elems.wmm_param) {
|
||||||
|
elems.wmm_param = bss_elems.wmm_param;
|
||||||
|
sdata_info(sdata,
|
||||||
|
"AP bug: WMM param missing from AssocResp\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Also check if we requested HT/VHT, otherwise the AP doesn't
|
||||||
|
* have to include the IEs in the (re)association response.
|
||||||
|
*/
|
||||||
|
if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
|
||||||
|
!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||||
|
elems.ht_cap_elem = bss_elems.ht_cap_elem;
|
||||||
|
sdata_info(sdata,
|
||||||
|
"AP bug: HT capability missing from AssocResp\n");
|
||||||
|
}
|
||||||
|
if (!elems.ht_operation && bss_elems.ht_operation &&
|
||||||
|
!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
||||||
|
elems.ht_operation = bss_elems.ht_operation;
|
||||||
|
sdata_info(sdata,
|
||||||
|
"AP bug: HT operation missing from AssocResp\n");
|
||||||
|
}
|
||||||
|
if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
|
||||||
|
!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||||
|
elems.vht_cap_elem = bss_elems.vht_cap_elem;
|
||||||
|
sdata_info(sdata,
|
||||||
|
"AP bug: VHT capa missing from AssocResp\n");
|
||||||
|
}
|
||||||
|
if (!elems.vht_operation && bss_elems.vht_operation &&
|
||||||
|
!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
|
||||||
|
elems.vht_operation = bss_elems.vht_operation;
|
||||||
|
sdata_info(sdata,
|
||||||
|
"AP bug: VHT operation missing from AssocResp\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We previously checked these in the beacon/probe response, so
|
* We previously checked these in the beacon/probe response, so
|
||||||
* they should be present here. This is just a safety net.
|
* they should be present here. This is just a safety net.
|
||||||
@ -2541,15 +2607,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
|
||||||
(!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
|
(!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"HT AP is missing WMM params or HT capability/operation in AssocResp\n");
|
"HT AP is missing WMM params or HT capability/operation\n");
|
||||||
return false;
|
ret = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
|
||||||
(!elems.vht_cap_elem || !elems.vht_operation)) {
|
(!elems.vht_cap_elem || !elems.vht_operation)) {
|
||||||
sdata_info(sdata,
|
sdata_info(sdata,
|
||||||
"VHT AP is missing VHT capability/operation in AssocResp\n");
|
"VHT AP is missing VHT capability/operation\n");
|
||||||
return false;
|
ret = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&sdata->local->sta_mtx);
|
mutex_lock(&sdata->local->sta_mtx);
|
||||||
@ -2560,7 +2628,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
sta = sta_info_get(sdata, cbss->bssid);
|
sta = sta_info_get(sdata, cbss->bssid);
|
||||||
if (WARN_ON(!sta)) {
|
if (WARN_ON(!sta)) {
|
||||||
mutex_unlock(&sdata->local->sta_mtx);
|
mutex_unlock(&sdata->local->sta_mtx);
|
||||||
return false;
|
ret = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
|
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,
|
|||||||
sta->sta.addr);
|
sta->sta.addr);
|
||||||
WARN_ON(__sta_info_destroy(sta));
|
WARN_ON(__sta_info_destroy(sta));
|
||||||
mutex_unlock(&sdata->local->sta_mtx);
|
mutex_unlock(&sdata->local->sta_mtx);
|
||||||
return false;
|
ret = false;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&sdata->local->sta_mtx);
|
mutex_unlock(&sdata->local->sta_mtx);
|
||||||
@ -2653,7 +2723,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
|
|||||||
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
|
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
|
||||||
ieee80211_sta_reset_beacon_monitor(sdata);
|
ieee80211_sta_reset_beacon_monitor(sdata);
|
||||||
|
|
||||||
return true;
|
ret = true;
|
||||||
|
out:
|
||||||
|
kfree(bss_ies);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@ -621,7 +621,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
|
|||||||
if (rates[i].idx < 0)
|
if (rates[i].idx < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
rate_idx_match_mask(&rates[i], sband, mask, chan_width,
|
rate_idx_match_mask(&rates[i], sband, chan_width, mask,
|
||||||
mcs_mask);
|
mcs_mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,12 +667,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
||||||
|
|
||||||
u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
|
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
u64 filter, u32 crc)
|
u64 filter, u32 crc)
|
||||||
{
|
{
|
||||||
size_t left = len;
|
size_t left = len;
|
||||||
u8 *pos = start;
|
const u8 *pos = start;
|
||||||
bool calc_crc = filter != 0;
|
bool calc_crc = filter != 0;
|
||||||
DECLARE_BITMAP(seen_elems, 256);
|
DECLARE_BITMAP(seen_elems, 256);
|
||||||
const u8 *ie;
|
const u8 *ie;
|
||||||
|
@ -1527,12 +1527,17 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
struct cfg80211_registered_device *dev;
|
struct cfg80211_registered_device *dev;
|
||||||
s64 filter_wiphy = -1;
|
s64 filter_wiphy = -1;
|
||||||
bool split = false;
|
bool split = false;
|
||||||
struct nlattr **tb = nl80211_fam.attrbuf;
|
struct nlattr **tb;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
/* will be zeroed in nlmsg_parse() */
|
||||||
|
tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL);
|
||||||
|
if (!tb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||||
tb, nl80211_fam.maxattr, nl80211_policy);
|
tb, NL80211_ATTR_MAX, nl80211_policy);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
|
split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
|
||||||
if (tb[NL80211_ATTR_WIPHY])
|
if (tb[NL80211_ATTR_WIPHY])
|
||||||
@ -1546,6 +1551,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
|
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
|
||||||
if (!netdev) {
|
if (!netdev) {
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
kfree(tb);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (netdev->ieee80211_ptr) {
|
if (netdev->ieee80211_ptr) {
|
||||||
@ -1556,6 +1562,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
|
|||||||
dev_put(netdev);
|
dev_put(netdev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
kfree(tb);
|
||||||
|
|
||||||
list_for_each_entry(dev, &cfg80211_rdev_list, list) {
|
list_for_each_entry(dev, &cfg80211_rdev_list, list) {
|
||||||
if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
|
if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))
|
||||||
|
Loading…
Reference in New Issue
Block a user