mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
This time we have various things - all across the board:
* MU-MIMO sniffer support in mac80211 * a create_singlethread_workqueue() cleanup * interface dump filtering that was documented but not implemented * support for the new radiotap timestamp field * send delBA in two unexpected conditions (as required by the spec) * connect keys cleanups - allow only WEP with index 0-3 * per-station aggregation limit to work around broken APs * debugfs improvement for the integrated codel algorithm and various other small improvements and cleanups. -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJX2+umAAoJEGt7eEactAAdIMkP/jMmpbxkzD64L7nTkO4APGva r6RmMM1SmgVD/CtVkjlBLuvo5YOTWv/vWvy6KoUESOINAx/e6T3T7bmmCOXzbsOL e5/YYcS1AOqgn5SdhgIj1E5cpdYIhlUGRlNJ0qEjeLLrh4/TLUNbCcuPhOYybUMz fUrdPKgDeWb7x9EHLENhPsVtCXWwKnkDIS4qclPZCWgRj46XM4pNB4OlvCUzGY6k bOqGJfrtjYjgKFDmPFqfYA4JDA56980qqO41+eEKXeMvDKNs+pSiNco130Q+uU3E o7tk9DMnAnCy2GihpV1ZYVkLr6O+7o9xVuenj3NRlhyd1mn2gXxLcO4AkHcrZBkf Ei+2L+KgnWELyqiSOaGTJKlugsgS4DDoNnFEIVjSweQ9DIoBA/Gj/6+4uZeHXJ3M bEjtHnCLi5CuI067uBoevwXFoMi1poWra2KnZKOZzFS5OL3xHv4//x/Wmnn2/5Jz ffEwVyRmTY76sLWfnwXUDClrFWAYQrpNyTryc+k3cpYKzhnseiqt+z43cBuISm00 uh5B9PpPB8RhtUnXrL/SHRyf8YEluaidTsI2lc1LvwXOc0+Zbp73mTCgP+rzLs9p K2qVRiozpIXanW6hKmmaDwjKlcAKKLP0xN2v90MqwQt4YdLIKlXnll1AH2BawzuP OWB3n8D0I6y0PWH+Yo8o =s1MY -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2016-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== This time we have various things - all across the board: * MU-MIMO sniffer support in mac80211 * a create_singlethread_workqueue() cleanup * interface dump filtering that was documented but not implemented * support for the new radiotap timestamp field * send delBA in two unexpected conditions (as required by the spec) * connect keys cleanups - allow only WEP with index 0-3 * per-station aggregation limit to work around broken APs * debugfs improvement for the integrated codel algorithm and various other small improvements and cleanups. ==================== Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
commit
c13ed534b8
34 changed files with 484 additions and 277 deletions
|
|
@ -1252,7 +1252,7 @@ static int __init cfg80211_init(void)
|
|||
if (err)
|
||||
goto out_fail_reg;
|
||||
|
||||
cfg80211_wq = create_singlethread_workqueue("cfg80211");
|
||||
cfg80211_wq = alloc_ordered_workqueue("cfg80211", WQ_MEM_RECLAIM);
|
||||
if (!cfg80211_wq) {
|
||||
err = -ENOMEM;
|
||||
goto out_fail_wq;
|
||||
|
|
|
|||
|
|
@ -249,9 +249,9 @@ struct cfg80211_event {
|
|||
};
|
||||
|
||||
struct cfg80211_cached_keys {
|
||||
struct key_params params[6];
|
||||
u8 data[6][WLAN_MAX_KEY_LEN];
|
||||
int def, defmgmt;
|
||||
struct key_params params[4];
|
||||
u8 data[4][WLAN_KEY_LEN_WEP104];
|
||||
int def;
|
||||
};
|
||||
|
||||
enum cfg80211_chan_mode {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(connkeys && connkeys->def < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(wdev->connect_keys))
|
||||
kzfree(wdev->connect_keys);
|
||||
wdev->connect_keys = connkeys;
|
||||
|
|
@ -284,18 +287,16 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
|||
if (!netif_running(wdev->netdev))
|
||||
return 0;
|
||||
|
||||
if (wdev->wext.keys) {
|
||||
if (wdev->wext.keys)
|
||||
wdev->wext.keys->def = wdev->wext.default_key;
|
||||
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
|
||||
}
|
||||
|
||||
wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
|
||||
|
||||
if (wdev->wext.keys) {
|
||||
if (wdev->wext.keys && wdev->wext.keys->def != -1) {
|
||||
ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
|
||||
if (!ck)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < 6; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
ck->params[i].key = ck->data[i];
|
||||
}
|
||||
err = __cfg80211_join_ibss(rdev, wdev->netdev,
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
|
|||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
||||
if (auth_type == NL80211_AUTHTYPE_SHARED_KEY)
|
||||
if (!key || !key_len || key_idx < 0 || key_idx > 4)
|
||||
if (!key || !key_len || key_idx < 0 || key_idx > 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (wdev->current_bss &&
|
||||
|
|
|
|||
|
|
@ -848,13 +848,21 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
|
|||
struct nlattr *key;
|
||||
struct cfg80211_cached_keys *result;
|
||||
int rem, err, def = 0;
|
||||
bool have_key = false;
|
||||
|
||||
nla_for_each_nested(key, keys, rem) {
|
||||
have_key = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!have_key)
|
||||
return NULL;
|
||||
|
||||
result = kzalloc(sizeof(*result), GFP_KERNEL);
|
||||
if (!result)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
result->def = -1;
|
||||
result->defmgmt = -1;
|
||||
|
||||
nla_for_each_nested(key, keys, rem) {
|
||||
memset(&parse, 0, sizeof(parse));
|
||||
|
|
@ -866,7 +874,7 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
|
|||
err = -EINVAL;
|
||||
if (!parse.p.key)
|
||||
goto error;
|
||||
if (parse.idx < 0 || parse.idx > 4)
|
||||
if (parse.idx < 0 || parse.idx > 3)
|
||||
goto error;
|
||||
if (parse.def) {
|
||||
if (def)
|
||||
|
|
@ -881,16 +889,24 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
|
|||
parse.idx, false, NULL);
|
||||
if (err)
|
||||
goto error;
|
||||
if (parse.p.cipher != WLAN_CIPHER_SUITE_WEP40 &&
|
||||
parse.p.cipher != WLAN_CIPHER_SUITE_WEP104) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
result->params[parse.idx].cipher = parse.p.cipher;
|
||||
result->params[parse.idx].key_len = parse.p.key_len;
|
||||
result->params[parse.idx].key = result->data[parse.idx];
|
||||
memcpy(result->data[parse.idx], parse.p.key, parse.p.key_len);
|
||||
|
||||
if (parse.p.cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
parse.p.cipher == WLAN_CIPHER_SUITE_WEP104) {
|
||||
if (no_ht)
|
||||
*no_ht = true;
|
||||
}
|
||||
/* must be WEP key if we got here */
|
||||
if (no_ht)
|
||||
*no_ht = true;
|
||||
}
|
||||
|
||||
if (result->def < 0) {
|
||||
err = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -2525,10 +2541,35 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|||
int if_idx = 0;
|
||||
int wp_start = cb->args[0];
|
||||
int if_start = cb->args[1];
|
||||
int filter_wiphy = -1;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
rtnl_lock();
|
||||
if (!cb->args[2]) {
|
||||
struct nl80211_dump_wiphy_state state = {
|
||||
.filter_wiphy = -1,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = nl80211_dump_wiphy_parse(skb, cb, &state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
filter_wiphy = state.filter_wiphy;
|
||||
|
||||
/*
|
||||
* if filtering, set cb->args[2] to +1 since 0 is the default
|
||||
* value needed to determine that parsing is necessary.
|
||||
*/
|
||||
if (filter_wiphy >= 0)
|
||||
cb->args[2] = filter_wiphy + 1;
|
||||
else
|
||||
cb->args[2] = -1;
|
||||
} else if (cb->args[2] > 0) {
|
||||
filter_wiphy = cb->args[2] - 1;
|
||||
}
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
|
||||
continue;
|
||||
|
|
@ -2536,6 +2577,10 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
|
|||
wp_idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (filter_wiphy >= 0 && filter_wiphy != rdev->wiphy_idx)
|
||||
continue;
|
||||
|
||||
if_idx = 0;
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
|
|
@ -7359,7 +7404,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
(key.p.cipher != WLAN_CIPHER_SUITE_WEP104 ||
|
||||
key.p.key_len != WLAN_KEY_LEN_WEP104))
|
||||
return -EINVAL;
|
||||
if (key.idx > 4)
|
||||
if (key.idx > 3)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
key.p.key_len = 0;
|
||||
|
|
@ -7977,6 +8022,8 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
|
|||
}
|
||||
|
||||
data = nla_nest_start(skb, attr);
|
||||
if (!data)
|
||||
goto nla_put_failure;
|
||||
|
||||
((void **)skb->cb)[0] = rdev;
|
||||
((void **)skb->cb)[1] = hdr;
|
||||
|
|
@ -9406,18 +9453,27 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
|
|||
if (!freqs)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < req->n_channels; i++)
|
||||
nla_put_u32(msg, i, req->channels[i]->center_freq);
|
||||
for (i = 0; i < req->n_channels; i++) {
|
||||
if (nla_put_u32(msg, i, req->channels[i]->center_freq))
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, freqs);
|
||||
|
||||
if (req->n_match_sets) {
|
||||
matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
|
||||
if (!matches)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
match = nla_nest_start(msg, i);
|
||||
nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
|
||||
req->match_sets[i].ssid.ssid_len,
|
||||
req->match_sets[i].ssid.ssid);
|
||||
if (!match)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
|
||||
req->match_sets[i].ssid.ssid_len,
|
||||
req->match_sets[i].ssid.ssid))
|
||||
return -ENOBUFS;
|
||||
nla_nest_end(msg, match);
|
||||
}
|
||||
nla_nest_end(msg, matches);
|
||||
|
|
@ -9429,6 +9485,9 @@ static int nl80211_send_wowlan_nd(struct sk_buff *msg,
|
|||
|
||||
for (i = 0; i < req->n_scan_plans; i++) {
|
||||
scan_plan = nla_nest_start(msg, i + 1);
|
||||
if (!scan_plan)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (!scan_plan ||
|
||||
nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL,
|
||||
req->scan_plans[i].interval) ||
|
||||
|
|
|
|||
|
|
@ -352,52 +352,48 @@ void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
|
|||
__cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
|
||||
}
|
||||
|
||||
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len)
|
||||
const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
|
||||
const u8 *match, int match_len,
|
||||
int match_offset)
|
||||
{
|
||||
while (len > 2 && ies[0] != eid) {
|
||||
/* match_offset can't be smaller than 2, unless match_len is
|
||||
* zero, in which case match_offset must be zero as well.
|
||||
*/
|
||||
if (WARN_ON((match_len && match_offset < 2) ||
|
||||
(!match_len && match_offset)))
|
||||
return NULL;
|
||||
|
||||
while (len >= 2 && len >= ies[1] + 2) {
|
||||
if ((ies[0] == eid) &&
|
||||
(ies[1] + 2 >= match_offset + match_len) &&
|
||||
!memcmp(ies + match_offset, match, match_len))
|
||||
return ies;
|
||||
|
||||
len -= ies[1] + 2;
|
||||
ies += ies[1] + 2;
|
||||
}
|
||||
if (len < 2)
|
||||
return NULL;
|
||||
if (len < 2 + ies[1])
|
||||
return NULL;
|
||||
return ies;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_find_ie);
|
||||
EXPORT_SYMBOL(cfg80211_find_ie_match);
|
||||
|
||||
const u8 *cfg80211_find_vendor_ie(unsigned int oui, int oui_type,
|
||||
const u8 *ies, int len)
|
||||
{
|
||||
struct ieee80211_vendor_ie *ie;
|
||||
const u8 *pos = ies, *end = ies + len;
|
||||
int ie_oui;
|
||||
const u8 *ie;
|
||||
u8 match[] = { oui >> 16, oui >> 8, oui, oui_type };
|
||||
int match_len = (oui_type < 0) ? 3 : sizeof(match);
|
||||
|
||||
if (WARN_ON(oui_type > 0xff))
|
||||
return NULL;
|
||||
|
||||
while (pos < end) {
|
||||
pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
|
||||
end - pos);
|
||||
if (!pos)
|
||||
return NULL;
|
||||
ie = cfg80211_find_ie_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,
|
||||
match, match_len, 2);
|
||||
|
||||
ie = (struct ieee80211_vendor_ie *)pos;
|
||||
if (ie && (ie[1] < 4))
|
||||
return NULL;
|
||||
|
||||
/* make sure we can access ie->len */
|
||||
BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1);
|
||||
|
||||
if (ie->len < sizeof(*ie))
|
||||
goto cont;
|
||||
|
||||
ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
|
||||
if (ie_oui == oui &&
|
||||
(oui_type < 0 || ie->oui_type == oui_type))
|
||||
return pos;
|
||||
cont:
|
||||
pos += 2 + ie->len;
|
||||
}
|
||||
return NULL;
|
||||
return ie;
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_find_vendor_ie);
|
||||
|
||||
|
|
|
|||
|
|
@ -1043,6 +1043,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
|||
connect->crypto.ciphers_pairwise[0] = cipher;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (WARN_ON(connkeys))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wdev->connect_keys = connkeys;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static ssize_t addresses_show(struct device *dev,
|
|||
return sprintf(buf, "%pM\n", wiphy->perm_addr);
|
||||
|
||||
for (i = 0; i < wiphy->n_addresses; i++)
|
||||
buf += sprintf(buf, "%pM\n", &wiphy->addresses[i].addr);
|
||||
buf += sprintf(buf, "%pM\n", wiphy->addresses[i].addr);
|
||||
|
||||
return buf - start;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
|||
struct key_params *params, int key_idx,
|
||||
bool pairwise, const u8 *mac_addr)
|
||||
{
|
||||
if (key_idx > 5)
|
||||
if (key_idx < 0 || key_idx > 5)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
|
||||
|
|
@ -249,7 +249,13 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
|
|||
/* Disallow BIP (group-only) cipher as pairwise cipher */
|
||||
if (pairwise)
|
||||
return -EINVAL;
|
||||
if (key_idx < 4)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case WLAN_CIPHER_SUITE_WEP40:
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
if (key_idx > 3)
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -906,7 +912,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
|
|||
if (!wdev->connect_keys)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!wdev->connect_keys->params[i].cipher)
|
||||
continue;
|
||||
if (rdev_add_key(rdev, dev, i, false, NULL,
|
||||
|
|
@ -919,9 +925,6 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
|
|||
netdev_err(dev, "failed to set defkey %d\n", i);
|
||||
continue;
|
||||
}
|
||||
if (wdev->connect_keys->defmgmt == i)
|
||||
if (rdev_set_default_mgmt_key(rdev, dev, i))
|
||||
netdev_err(dev, "failed to set mgtdef %d\n", i);
|
||||
}
|
||||
|
||||
kzfree(wdev->connect_keys);
|
||||
|
|
|
|||
|
|
@ -408,10 +408,10 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
|
||||
if (!wdev->wext.keys) {
|
||||
wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
|
||||
GFP_KERNEL);
|
||||
GFP_KERNEL);
|
||||
if (!wdev->wext.keys)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < 6; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
wdev->wext.keys->params[i].key =
|
||||
wdev->wext.keys->data[i];
|
||||
}
|
||||
|
|
@ -460,7 +460,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
if (err == -ENOENT)
|
||||
err = 0;
|
||||
if (!err) {
|
||||
if (!addr) {
|
||||
if (!addr && idx < 4) {
|
||||
memset(wdev->wext.keys->data[idx], 0,
|
||||
sizeof(wdev->wext.keys->data[idx]));
|
||||
wdev->wext.keys->params[idx].key_len = 0;
|
||||
|
|
@ -487,6 +487,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
|
|||
err = 0;
|
||||
if (wdev->current_bss)
|
||||
err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
|
||||
else if (params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
|
||||
params->cipher != WLAN_CIPHER_SUITE_WEP104)
|
||||
return -EINVAL;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
|
|||
|
||||
if (wdev->wext.keys) {
|
||||
wdev->wext.keys->def = wdev->wext.default_key;
|
||||
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
|
||||
if (wdev->wext.default_key != -1)
|
||||
wdev->wext.connect.privacy = true;
|
||||
}
|
||||
|
|
@ -43,11 +42,11 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
|
|||
if (!wdev->wext.connect.ssid_len)
|
||||
return 0;
|
||||
|
||||
if (wdev->wext.keys) {
|
||||
if (wdev->wext.keys && wdev->wext.keys->def != -1) {
|
||||
ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
|
||||
if (!ck)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < 6; i++)
|
||||
for (i = 0; i < 4; i++)
|
||||
ck->params[i].key = ck->data[i];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue