Commit c01fc9ad authored by Sunil Dutt's avatar Sunil Dutt Committed by Johannes Berg

cfg80211: pass station supported channel and oper class info

The information of the peer's supported channels and supported operating
classes are required for the driver to perform TDLS off channel
operations. This commit enhances the function nl80211_(new)set_station
to pass this information of the peer to the driver.
Signed-off-by: default avatarSunil Dutt <c_duttus@qti.qualcomm.com>
[return errors for malformed tuples]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 789fd033
...@@ -744,6 +744,10 @@ enum station_parameters_apply_mask { ...@@ -744,6 +744,10 @@ enum station_parameters_apply_mask {
* @capability: station capability * @capability: station capability
* @ext_capab: extended capabilities of the station * @ext_capab: extended capabilities of the station
* @ext_capab_len: number of extended capabilities * @ext_capab_len: number of extended capabilities
* @supported_channels: supported channels in IEEE 802.11 format
* @supported_channels_len: number of supported channels
* @supported_oper_classes: supported oper classes in IEEE 802.11 format
* @supported_oper_classes_len: number of supported operating classes
*/ */
struct station_parameters { struct station_parameters {
const u8 *supported_rates; const u8 *supported_rates;
...@@ -763,6 +767,10 @@ struct station_parameters { ...@@ -763,6 +767,10 @@ struct station_parameters {
u16 capability; u16 capability;
const u8 *ext_capab; const u8 *ext_capab;
u8 ext_capab_len; u8 ext_capab_len;
const u8 *supported_channels;
u8 supported_channels_len;
const u8 *supported_oper_classes;
u8 supported_oper_classes_len;
}; };
/** /**
......
...@@ -1496,6 +1496,11 @@ enum nl80211_commands { ...@@ -1496,6 +1496,11 @@ enum nl80211_commands {
* @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
* As specified in the &enum nl80211_rxmgmt_flags. * As specified in the &enum nl80211_rxmgmt_flags.
* *
* @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels.
*
* @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported
* supported operating classes.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
*/ */
...@@ -1806,6 +1811,10 @@ enum nl80211_attrs { ...@@ -1806,6 +1811,10 @@ enum nl80211_attrs {
NL80211_ATTR_RXMGMT_FLAGS, NL80211_ATTR_RXMGMT_FLAGS,
NL80211_ATTR_STA_SUPPORTED_CHANNELS,
NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
......
...@@ -354,6 +354,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { ...@@ -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_IES] = { .type = NLA_NESTED },
[NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 }, [NL80211_ATTR_CSA_C_OFF_BEACON] = { .type = NLA_U16 },
[NL80211_ATTR_CSA_C_OFF_PRESP] = { .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 */ /* policy for the key attributes */
...@@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info, ...@@ -3896,9 +3898,45 @@ static int nl80211_parse_sta_wme(struct genl_info *info,
return 0; 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, static int nl80211_set_station_tdls(struct genl_info *info,
struct station_parameters *params) struct station_parameters *params)
{ {
int err;
/* Dummy STA entry gets updated once the peer capabilities are known */ /* Dummy STA entry gets updated once the peer capabilities are known */
if (info->attrs[NL80211_ATTR_PEER_AID]) if (info->attrs[NL80211_ATTR_PEER_AID])
params->aid = nla_get_u16(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, ...@@ -3909,6 +3947,10 @@ static int nl80211_set_station_tdls(struct genl_info *info,
params->vht_capa = params->vht_capa =
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); 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); return nl80211_parse_sta_wme(info, params);
} }
...@@ -4089,6 +4131,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) ...@@ -4089,6 +4131,10 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL; return -EINVAL;
} }
err = nl80211_parse_sta_channel_info(info, &params);
if (err)
return err;
err = nl80211_parse_sta_wme(info, &params); err = nl80211_parse_sta_wme(info, &params);
if (err) if (err)
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment