|
@@ -354,6 +354,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
|
|
|
[NL80211_ATTR_CSA_IES] = { .type = NLA_NESTED },
|
|
|
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
|
|
|
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .type = NLA_U16 },
|
|
|
+ [NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
|
|
|
+ [NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
|
|
|
};
|
|
|
|
|
|
/* policy for the key attributes */
|
|
@@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_parse_sta_channel_info(struct genl_info *info,
|
|
|
+ struct station_parameters *params)
|
|
|
+{
|
|
|
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
|
|
|
+ params->supported_channels =
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
|
|
|
+ params->supported_channels_len =
|
|
|
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
|
|
|
+ /*
|
|
|
+ * Need to include at least one (first channel, number of
|
|
|
+ * channels) tuple for each subband, and must have proper
|
|
|
+ * tuples for the rest of the data as well.
|
|
|
+ */
|
|
|
+ if (params->supported_channels_len < 2)
|
|
|
+ return -EINVAL;
|
|
|
+ if (params->supported_channels_len % 2)
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
|
|
|
+ params->supported_oper_classes =
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
|
|
+ params->supported_oper_classes_len =
|
|
|
+ nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
|
|
|
+ /*
|
|
|
+ * The value of the Length field of the Supported Operating
|
|
|
+ * Classes element is between 2 and 253.
|
|
|
+ */
|
|
|
+ if (params->supported_oper_classes_len < 2 ||
|
|
|
+ params->supported_oper_classes_len > 253)
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int nl80211_set_station_tdls(struct genl_info *info,
|
|
|
struct station_parameters *params)
|
|
|
{
|
|
|
+ int err;
|
|
|
/* Dummy STA entry gets updated once the peer capabilities are known */
|
|
|
if (info->attrs[NL80211_ATTR_PEER_AID])
|
|
|
params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
|
|
@@ -3909,6 +3947,10 @@ static int nl80211_set_station_tdls(struct genl_info *info,
|
|
|
params->vht_capa =
|
|
|
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
|
|
|
|
|
|
+ err = nl80211_parse_sta_channel_info(info, params);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
return nl80211_parse_sta_wme(info, params);
|
|
|
}
|
|
|
|
|
@@ -4089,6 +4131,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ err = nl80211_parse_sta_channel_info(info, ¶ms);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
err = nl80211_parse_sta_wme(info, ¶ms);
|
|
|
if (err)
|
|
|
return err;
|