Merge tag 'mac80211-next-for-net-next-2020-02-24' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
A new set of changes:
 * lots of small documentation fixes, from Jérôme Pouiller
 * beacon protection (BIGTK) support from Jouni Malinen
 * some initial code for TID configuration, from Tamizh chelvam
 * I reverted some new API before it's actually used, because
   it's wrong to mix controlled port and preauth
 * a few other cleanups/fixes
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller
2020-02-24 15:41:54 -08:00
24 changed files with 909 additions and 150 deletions

View File

@@ -328,6 +328,22 @@ he_bss_color_policy[NL80211_HE_BSS_COLOR_ATTR_MAX + 1] = {
[NL80211_HE_BSS_COLOR_ATTR_PARTIAL] = { .type = NLA_FLAG },
};
static const struct nla_policy
nl80211_tid_config_attr_policy[NL80211_TID_CONFIG_ATTR_MAX + 1] = {
[NL80211_TID_CONFIG_ATTR_VIF_SUPP] = { .type = NLA_U64 },
[NL80211_TID_CONFIG_ATTR_PEER_SUPP] = { .type = NLA_U64 },
[NL80211_TID_CONFIG_ATTR_OVERRIDE] = { .type = NLA_FLAG },
[NL80211_TID_CONFIG_ATTR_TIDS] = NLA_POLICY_RANGE(NLA_U16, 1, 0xff),
[NL80211_TID_CONFIG_ATTR_NOACK] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
[NL80211_TID_CONFIG_ATTR_RETRY_SHORT] = NLA_POLICY_MIN(NLA_U8, 1),
[NL80211_TID_CONFIG_ATTR_RETRY_LONG] = NLA_POLICY_MIN(NLA_U8, 1),
[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL] =
NLA_POLICY_MAX(NLA_U8, NL80211_TID_CONFIG_DISABLE),
};
const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -368,7 +384,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
[NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
.len = WLAN_MAX_KEY_LEN },
[NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 5),
[NL80211_ATTR_KEY_IDX] = NLA_POLICY_MAX(NLA_U8, 7),
[NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
[NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
[NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 },
@@ -634,8 +650,8 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_HE_OBSS_PD] = NLA_POLICY_NESTED(he_obss_pd_policy),
[NL80211_ATTR_VLAN_ID] = NLA_POLICY_RANGE(NLA_U16, 1, VLAN_N_VID - 2),
[NL80211_ATTR_HE_BSS_COLOR] = NLA_POLICY_NESTED(he_bss_color_policy),
[NL80211_ATTR_SRC_MAC] = NLA_POLICY_ETH_ADDR,
[NL80211_ATTR_DST_MAC] = NLA_POLICY_ETH_ADDR,
[NL80211_ATTR_TID_CONFIG] =
NLA_POLICY_NESTED_ARRAY(nl80211_tid_config_attr_policy),
};
/* policy for the key attributes */
@@ -1039,7 +1055,7 @@ struct key_parse {
struct key_params p;
int idx;
int type;
bool def, defmgmt;
bool def, defmgmt, defbeacon;
bool def_uni, def_multi;
};
@@ -1055,12 +1071,13 @@ static int nl80211_parse_key_new(struct genl_info *info, struct nlattr *key,
k->def = !!tb[NL80211_KEY_DEFAULT];
k->defmgmt = !!tb[NL80211_KEY_DEFAULT_MGMT];
k->defbeacon = !!tb[NL80211_KEY_DEFAULT_BEACON];
if (k->def) {
k->def_uni = true;
k->def_multi = true;
}
if (k->defmgmt)
if (k->defmgmt || k->defbeacon)
k->def_multi = true;
if (tb[NL80211_KEY_IDX])
@@ -1167,14 +1184,17 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
if (err)
return err;
if (k->def && k->defmgmt) {
GENL_SET_ERR_MSG(info, "key with def && defmgmt is invalid");
if ((k->def ? 1 : 0) + (k->defmgmt ? 1 : 0) +
(k->defbeacon ? 1 : 0) > 1) {
GENL_SET_ERR_MSG(info,
"key with multiple default flags is invalid");
return -EINVAL;
}
if (k->defmgmt) {
if (k->defmgmt || k->defbeacon) {
if (k->def_uni || !k->def_multi) {
GENL_SET_ERR_MSG(info, "defmgmt key must be mcast");
GENL_SET_ERR_MSG(info,
"defmgmt/defbeacon key must be mcast");
return -EINVAL;
}
}
@@ -1186,14 +1206,20 @@ static int nl80211_parse_key(struct genl_info *info, struct key_parse *k)
"defmgmt key idx not 4 or 5");
return -EINVAL;
}
} else if (k->defbeacon) {
if (k->idx < 6 || k->idx > 7) {
GENL_SET_ERR_MSG(info,
"defbeacon key idx not 6 or 7");
return -EINVAL;
}
} else if (k->def) {
if (k->idx < 0 || k->idx > 3) {
GENL_SET_ERR_MSG(info, "def key idx not 0-3");
return -EINVAL;
}
} else {
if (k->idx < 0 || k->idx > 5) {
GENL_SET_ERR_MSG(info, "key idx not 0-5");
if (k->idx < 0 || k->idx > 7) {
GENL_SET_ERR_MSG(info, "key idx not 0-7");
return -EINVAL;
}
}
@@ -1939,6 +1965,48 @@ nl80211_put_iftype_akm_suites(struct cfg80211_registered_device *rdev,
return 0;
}
static int
nl80211_put_tid_config_support(struct cfg80211_registered_device *rdev,
struct sk_buff *msg)
{
struct nlattr *supp;
if (!rdev->wiphy.tid_config_support.vif &&
!rdev->wiphy.tid_config_support.peer)
return 0;
supp = nla_nest_start(msg, NL80211_ATTR_TID_CONFIG);
if (!supp)
return -ENOSPC;
if (rdev->wiphy.tid_config_support.vif &&
nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_VIF_SUPP,
rdev->wiphy.tid_config_support.vif,
NL80211_TID_CONFIG_ATTR_PAD))
goto fail;
if (rdev->wiphy.tid_config_support.peer &&
nla_put_u64_64bit(msg, NL80211_TID_CONFIG_ATTR_PEER_SUPP,
rdev->wiphy.tid_config_support.peer,
NL80211_TID_CONFIG_ATTR_PAD))
goto fail;
/* for now we just use the same value ... makes more sense */
if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_SHORT,
rdev->wiphy.tid_config_support.max_retry))
goto fail;
if (nla_put_u8(msg, NL80211_TID_CONFIG_ATTR_RETRY_LONG,
rdev->wiphy.tid_config_support.max_retry))
goto fail;
nla_nest_end(msg, supp);
return 0;
fail:
nla_nest_cancel(msg, supp);
return -ENOBUFS;
}
struct nl80211_dump_wiphy_state {
s64 filter_wiphy;
long start;
@@ -2500,6 +2568,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
if (nl80211_put_iftype_akm_suites(rdev, msg))
goto nla_put_failure;
if (nl80211_put_tid_config_support(rdev, msg))
goto nla_put_failure;
/* done */
state->split_start = 0;
break;
@@ -3819,8 +3890,14 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
void *hdr;
struct sk_buff *msg;
if (info->attrs[NL80211_ATTR_KEY_IDX])
if (info->attrs[NL80211_ATTR_KEY_IDX]) {
key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
if (key_idx > 5 &&
!wiphy_ext_feature_isset(
&rdev->wiphy,
NL80211_EXT_FEATURE_BEACON_PROTECTION))
return -EINVAL;
}
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -3896,7 +3973,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
/* Only support setting default key and
* Extended Key ID action NL80211_KEY_SET_TX.
*/
if (!key.def && !key.defmgmt &&
if (!key.def && !key.defmgmt && !key.defbeacon &&
!(key.p.mode == NL80211_KEY_SET_TX))
return -EINVAL;
@@ -3943,6 +4020,24 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
#ifdef CONFIG_CFG80211_WEXT
dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
#endif
} else if (key.defbeacon) {
if (key.def_uni || !key.def_multi) {
err = -EINVAL;
goto out;
}
if (!rdev->ops->set_default_beacon_key) {
err = -EOPNOTSUPP;
goto out;
}
err = nl80211_key_allowed(dev->ieee80211_ptr);
if (err)
goto out;
err = rdev_set_default_beacon_key(rdev, dev, key.idx);
if (err)
goto out;
} else if (key.p.mode == NL80211_KEY_SET_TX &&
wiphy_ext_feature_isset(&rdev->wiphy,
NL80211_EXT_FEATURE_EXT_KEY_ID)) {
@@ -3980,8 +4075,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
if (!key.p.key)
if (!key.p.key) {
GENL_SET_ERR_MSG(info, "no key");
return -EINVAL;
}
if (info->attrs[NL80211_ATTR_MAC])
mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -3995,8 +4092,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
/* for now */
if (key.type != NL80211_KEYTYPE_PAIRWISE &&
key.type != NL80211_KEYTYPE_GROUP)
key.type != NL80211_KEYTYPE_GROUP) {
GENL_SET_ERR_MSG(info, "key type not pairwise or group");
return -EINVAL;
}
if (key.type == NL80211_KEYTYPE_GROUP &&
info->attrs[NL80211_ATTR_VLAN_ID])
@@ -4007,15 +4106,22 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
if (cfg80211_validate_key_settings(rdev, &key.p, key.idx,
key.type == NL80211_KEYTYPE_PAIRWISE,
mac_addr))
mac_addr)) {
GENL_SET_ERR_MSG(info, "key setting validation failed");
return -EINVAL;
}
wdev_lock(dev->ieee80211_ptr);
err = nl80211_key_allowed(dev->ieee80211_ptr);
if (!err)
if (err)
GENL_SET_ERR_MSG(info, "key not allowed");
if (!err) {
err = rdev_add_key(rdev, dev, key.idx,
key.type == NL80211_KEYTYPE_PAIRWISE,
mac_addr, &key.p);
if (err)
GENL_SET_ERR_MSG(info, "key addition failed");
}
wdev_unlock(dev->ieee80211_ptr);
return err;
@@ -13698,7 +13804,6 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
const u8 *buf;
size_t len;
u8 *dest;
u8 src[ETH_ALEN];
u16 proto;
bool noencrypt;
int err;
@@ -13736,13 +13841,6 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
goto out;
}
/* copy src address under wdev_lock, as we may copy wdev_address */
if (info->attrs[NL80211_ATTR_SRC_MAC])
ether_addr_copy(src,
nla_data(info->attrs[NL80211_ATTR_SRC_MAC]));
else
ether_addr_copy(src, wdev_address(wdev));
wdev_unlock(wdev);
buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
@@ -13753,7 +13851,7 @@ static int nl80211_tx_control_port(struct sk_buff *skb, struct genl_info *info)
nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT]);
return rdev_tx_control_port(rdev, dev, buf, len,
dest, src, cpu_to_be16(proto), noencrypt);
dest, cpu_to_be16(proto), noencrypt);
out:
wdev_unlock(wdev);
@@ -13899,6 +13997,141 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
}
static int parse_tid_conf(struct cfg80211_registered_device *rdev,
struct nlattr *attrs[], struct net_device *dev,
struct cfg80211_tid_cfg *tid_conf,
struct genl_info *info, const u8 *peer)
{
struct netlink_ext_ack *extack = info->extack;
u64 mask;
int err;
if (!attrs[NL80211_TID_CONFIG_ATTR_TIDS])
return -EINVAL;
tid_conf->config_override =
nla_get_flag(attrs[NL80211_TID_CONFIG_ATTR_OVERRIDE]);
tid_conf->tids = nla_get_u16(attrs[NL80211_TID_CONFIG_ATTR_TIDS]);
if (tid_conf->config_override) {
if (rdev->ops->reset_tid_config) {
err = rdev_reset_tid_config(rdev, dev, peer,
tid_conf->tids);
/* If peer is there no other configuration will be
* allowed
*/
if (err || peer)
return err;
} else {
return -EINVAL;
}
}
if (attrs[NL80211_TID_CONFIG_ATTR_NOACK]) {
tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_NOACK);
tid_conf->noack =
nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_NOACK]);
}
if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]) {
tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT);
tid_conf->retry_short =
nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_SHORT]);
if (tid_conf->retry_short > rdev->wiphy.max_data_retry_count)
return -EINVAL;
}
if (attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]) {
tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG);
tid_conf->retry_long =
nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RETRY_LONG]);
if (tid_conf->retry_long > rdev->wiphy.max_data_retry_count)
return -EINVAL;
}
if (attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]) {
tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL);
tid_conf->ampdu =
nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_AMPDU_CTRL]);
}
if (attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]) {
tid_conf->mask |= BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL);
tid_conf->rtscts =
nla_get_u8(attrs[NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL]);
}
if (peer)
mask = rdev->wiphy.tid_config_support.peer;
else
mask = rdev->wiphy.tid_config_support.vif;
if (tid_conf->mask & ~mask) {
NL_SET_ERR_MSG(extack, "unsupported TID configuration");
return -ENOTSUPP;
}
return 0;
}
static int nl80211_set_tid_config(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct nlattr *attrs[NL80211_TID_CONFIG_ATTR_MAX + 1];
struct net_device *dev = info->user_ptr[1];
struct cfg80211_tid_config *tid_config;
struct nlattr *tid;
int conf_idx = 0, rem_conf;
int ret = -EINVAL;
u32 num_conf = 0;
if (!info->attrs[NL80211_ATTR_TID_CONFIG])
return -EINVAL;
if (!rdev->ops->set_tid_config)
return -EOPNOTSUPP;
nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
rem_conf)
num_conf++;
tid_config = kzalloc(struct_size(tid_config, tid_conf, num_conf),
GFP_KERNEL);
if (!tid_config)
return -ENOMEM;
tid_config->n_tid_conf = num_conf;
if (info->attrs[NL80211_ATTR_MAC])
tid_config->peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
nla_for_each_nested(tid, info->attrs[NL80211_ATTR_TID_CONFIG],
rem_conf) {
ret = nla_parse_nested(attrs, NL80211_TID_CONFIG_ATTR_MAX,
tid, NULL, NULL);
if (ret)
goto bad_tid_conf;
ret = parse_tid_conf(rdev, attrs, dev,
&tid_config->tid_conf[conf_idx],
info, tid_config->peer);
if (ret)
goto bad_tid_conf;
conf_idx++;
}
ret = rdev_set_tid_config(rdev, dev, tid_config);
bad_tid_conf:
kfree(tid_config);
return ret;
}
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -14853,6 +15086,13 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_TID_CONFIG,
.doit = nl80211_set_tid_config,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
};
static struct genl_family nl80211_fam __ro_after_init = {
@@ -16010,8 +16250,7 @@ static int __nl80211_rx_control_port(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct ethhdr *ehdr = eth_hdr(skb);
const u8 *daddr = ehdr->h_dest;
const u8 *saddr = ehdr->h_source;
const u8 *addr = ehdr->h_source;
u16 proto = be16_to_cpu(skb->protocol);
struct sk_buff *msg;
void *hdr;
@@ -16036,8 +16275,7 @@ static int __nl80211_rx_control_port(struct net_device *dev,
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
NL80211_ATTR_PAD) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, saddr) ||
nla_put(msg, NL80211_ATTR_DST_MAC, ETH_ALEN, daddr) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) ||
(unencrypted && nla_put_flag(msg,
NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT)))