aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2013-02-14 14:10:54 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-15 03:41:43 -0500
commitdf881293c6ba9a12868491a717b25cb14ec1fa4a (patch)
tree37ac4ed0321ce4cf626108fff6afbf92beaf845d /net/wireless
parent9d62a98617298c1da288f50e84c5dd67732e79b7 (diff)
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>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c90
1 files changed, 81 insertions, 9 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index be9f2b5a403f..580ffeaef3d5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3409,6 +3409,63 @@ static struct net_device *get_vlan(struct genl_info *info,
3409 return ERR_PTR(ret); 3409 return ERR_PTR(ret);
3410} 3410}
3411 3411
3412static struct nla_policy
3413nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
3414 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
3415 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
3416};
3417
3418static int nl80211_set_station_tdls(struct genl_info *info,
3419 struct station_parameters *params)
3420{
3421 struct cfg80211_registered_device *rdev = info->user_ptr[0];
3422 struct nlattr *tb[NL80211_STA_WME_MAX + 1];
3423 struct nlattr *nla;
3424 int err;
3425
3426 /* Can only set if TDLS ... */
3427 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS))
3428 return -EOPNOTSUPP;
3429
3430 /* ... with external setup is supported */
3431 if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
3432 return -EOPNOTSUPP;
3433
3434 /* Dummy STA entry gets updated once the peer capabilities are known */
3435 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
3436 params->ht_capa =
3437 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
3438 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY])
3439 params->vht_capa =
3440 nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
3441
3442 /* parse WME attributes if present */
3443 if (!info->attrs[NL80211_ATTR_STA_WME])
3444 return 0;
3445
3446 nla = info->attrs[NL80211_ATTR_STA_WME];
3447 err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla,
3448 nl80211_sta_wme_policy);
3449 if (err)
3450 return err;
3451
3452 if (tb[NL80211_STA_WME_UAPSD_QUEUES])
3453 params->uapsd_queues = nla_get_u8(
3454 tb[NL80211_STA_WME_UAPSD_QUEUES]);
3455 if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
3456 return -EINVAL;
3457
3458 if (tb[NL80211_STA_WME_MAX_SP])
3459 params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]);
3460
3461 if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK)
3462 return -EINVAL;
3463
3464 params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD;
3465
3466 return 0;
3467}
3468
3412static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) 3469static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3413{ 3470{
3414 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3471 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)
3450 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); 3507 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
3451 } 3508 }
3452 3509
3453 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL] || 3510 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
3454 info->attrs[NL80211_ATTR_HT_CAPABILITY])
3455 return -EINVAL; 3511 return -EINVAL;
3456 3512
3457 if (!rdev->ops->change_station) 3513 if (!rdev->ops->change_station)
@@ -3524,6 +3580,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3524 return -EINVAL; 3580 return -EINVAL;
3525 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) 3581 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
3526 return -EINVAL; 3582 return -EINVAL;
3583 if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
3584 info->attrs[NL80211_ATTR_VHT_CAPABILITY])
3585 return -EINVAL;
3527 3586
3528 /* must be last in here for error handling */ 3587 /* must be last in here for error handling */
3529 params.vlan = get_vlan(info, rdev); 3588 params.vlan = get_vlan(info, rdev);
@@ -3539,13 +3598,29 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3539 * to change the flag. 3598 * to change the flag.
3540 */ 3599 */
3541 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); 3600 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3542 /* fall through */ 3601 /* Include parameters for TDLS peer (driver will check) */
3602 err = nl80211_set_station_tdls(info, &params);
3603 if (err)
3604 return err;
3605 /* disallow things sta doesn't support */
3606 if (params.plink_action)
3607 return -EINVAL;
3608 if (params.local_pm)
3609 return -EINVAL;
3610 /* reject any changes other than AUTHORIZED or WME (for TDLS) */
3611 if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
3612 BIT(NL80211_STA_FLAG_WME)))
3613 return -EINVAL;
3614 break;
3543 case NL80211_IFTYPE_ADHOC: 3615 case NL80211_IFTYPE_ADHOC:
3544 /* disallow things sta doesn't support */ 3616 /* disallow things sta doesn't support */
3545 if (params.plink_action) 3617 if (params.plink_action)
3546 return -EINVAL; 3618 return -EINVAL;
3547 if (params.local_pm) 3619 if (params.local_pm)
3548 return -EINVAL; 3620 return -EINVAL;
3621 if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
3622 info->attrs[NL80211_ATTR_VHT_CAPABILITY])
3623 return -EINVAL;
3549 /* reject any changes other than AUTHORIZED */ 3624 /* reject any changes other than AUTHORIZED */
3550 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) 3625 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
3551 return -EINVAL; 3626 return -EINVAL;
@@ -3560,6 +3635,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3560 return -EINVAL; 3635 return -EINVAL;
3561 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) 3636 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
3562 return -EINVAL; 3637 return -EINVAL;
3638 if (info->attrs[NL80211_ATTR_HT_CAPABILITY] ||
3639 info->attrs[NL80211_ATTR_VHT_CAPABILITY])
3640 return -EINVAL;
3563 /* 3641 /*
3564 * No special handling for TDLS here -- the userspace 3642 * No special handling for TDLS here -- the userspace
3565 * mesh code doesn't have this bug. 3643 * mesh code doesn't have this bug.
@@ -3584,12 +3662,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3584 return err; 3662 return err;
3585} 3663}
3586 3664
3587static struct nla_policy
3588nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
3589 [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
3590 [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 },
3591};
3592
3593static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) 3665static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
3594{ 3666{
3595 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 3667 struct cfg80211_registered_device *rdev = info->user_ptr[0];