mirror of https://gitee.com/openkylin/linux.git
cfg80211: Pass TDLS peer's QoS/HT/VHT information during set_station
The information of the peer's capabilities is required for the driver to perform TDLS Peer UAPSD operations. This information of the peer is passed by the supplicant using NL80211_CMD_SET_STATION command. This commit enhances the function nl80211_set_station to pass this information of the peer to the driver in case this command is used with the TDLS peer STA. In addition, make the HT/VHT capability configuration handled more consistently for other STA cases (reject both instead of just HT). Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
9d62a98617
commit
df881293c6
|
@ -1412,9 +1412,11 @@ static int ieee80211_change_station(struct wiphy *wiphy,
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* in station mode, supported rates are only valid with TDLS */
|
/* in station mode, some updates are only valid with TDLS */
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||||
params->supported_rates &&
|
(params->supported_rates || params->ht_capa || params->vht_capa ||
|
||||||
|
params->sta_modify_mask ||
|
||||||
|
(params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) &&
|
||||||
!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
|
||||||
mutex_unlock(&local->sta_mtx);
|
mutex_unlock(&local->sta_mtx);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -3409,6 +3409,63 @@ static struct net_device *get_vlan(struct genl_info *info,
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct nla_policy
|
||||||
|
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
|
||||||
|
[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
|
||||||
|
[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int nl80211_set_station_tdls(struct genl_info *info,
|
||||||
|
struct station_parameters *params)
|
||||||
|
{
|
||||||
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
|
struct nlattr *tb[NL80211_STA_WME_MAX + 1];
|
||||||
|
struct nlattr *nla;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Can only set if TDLS ... */
|
||||||
|
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* ... with external setup is supported */
|
||||||
|
if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
/* Dummy STA entry gets updated once the peer capabilities are known */
|
||||||
|
if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
|
||||||
|
params->ht_capa =
|
||||||
|
nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
|
||||||
|
if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
|
||||||
|
params->vht_capa =
|
||||||
|
nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
|
||||||
|
|
||||||
|
/* parse WME attributes if present */
|
||||||
|
if (!info->attrs[NL80211_ATTR_STA_WME])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nla = info->attrs[NL80211_ATTR_STA_WME];
|
||||||
|
err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
|
||||||
|
nl80211_sta_wme_policy);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (tb[NL80211_STA_WME_UAPSD_QUEUES])
|
||||||
|
params->uapsd_queues = nla_get_u8(
|
||||||
|
tb[NL80211_STA_WME_UAPSD_QUEUES]);
|
||||||
|
if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (tb[NL80211_STA_WME_MAX_SP])
|
||||||
|
params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
|
||||||
|
|
||||||
|
if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
|
@ -3450,8 +3507,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
|
nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL] ||
|
if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
|
||||||
info->attrs[NL80211_ATTR_HT_CAPABILITY])
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rdev->ops->change_station)
|
if (!rdev->ops->change_station)
|
||||||
|
@ -3524,6 +3580,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
|
if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
|
||||||
|
info->attrs[NL80211_ATTR_VHT_CAPABILITY])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* must be last in here for error handling */
|
/* must be last in here for error handling */
|
||||||
params.vlan = get_vlan(info, rdev);
|
params.vlan = get_vlan(info, rdev);
|
||||||
|
@ -3539,13 +3598,29 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
* to change the flag.
|
* to change the flag.
|
||||||
*/
|
*/
|
||||||
params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
|
params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||||
/* fall through */
|
/* Include parameters for TDLS peer (driver will check) */
|
||||||
|
err = nl80211_set_station_tdls(info, ¶ms);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
/* disallow things sta doesn't support */
|
||||||
|
if (params.plink_action)
|
||||||
|
return -EINVAL;
|
||||||
|
if (params.local_pm)
|
||||||
|
return -EINVAL;
|
||||||
|
/* reject any changes other than AUTHORIZED or WME (for TDLS) */
|
||||||
|
if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
|
||||||
|
BIT(NL80211_STA_FLAG_WME)))
|
||||||
|
return -EINVAL;
|
||||||
|
break;
|
||||||
case NL80211_IFTYPE_ADHOC:
|
case NL80211_IFTYPE_ADHOC:
|
||||||
/* disallow things sta doesn't support */
|
/* disallow things sta doesn't support */
|
||||||
if (params.plink_action)
|
if (params.plink_action)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (params.local_pm)
|
if (params.local_pm)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
|
||||||
|
info->attrs[NL80211_ATTR_VHT_CAPABILITY])
|
||||||
|
return -EINVAL;
|
||||||
/* reject any changes other than AUTHORIZED */
|
/* reject any changes other than AUTHORIZED */
|
||||||
if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
|
if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -3560,6 +3635,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
|
if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
|
||||||
|
info->attrs[NL80211_ATTR_VHT_CAPABILITY])
|
||||||
|
return -EINVAL;
|
||||||
/*
|
/*
|
||||||
* No special handling for TDLS here -- the userspace
|
* No special handling for TDLS here -- the userspace
|
||||||
* mesh code doesn't have this bug.
|
* mesh code doesn't have this bug.
|
||||||
|
@ -3584,12 +3662,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nla_policy
|
|
||||||
nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
|
|
||||||
[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
|
|
||||||
[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||||
|
|
Loading…
Reference in New Issue