summaryrefslogtreecommitdiff
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-14 23:43:25 +0100
committerJohannes Berg <johannes.berg@intel.com>2013-03-06 16:35:39 +0100
commit984c311b0918248e0835334c41cb16856f3c5697 (patch)
tree851b2b81fea6abb2fbf5250d8d604a2ae38ebc3b /net/wireless
parent2c1aabf33d1832befc5291a14c870cd09dc2182d (diff)
cfg80211: clean up station WME attribute parsing
Parse the attributes first, and then disable the apply flag if needed. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c68
1 files changed, 37 insertions, 31 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9e7ece0e5e5..3b82f95b1a7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3619,6 +3619,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
memset(&params, 0, sizeof(params));
+ if (!rdev->ops->add_station)
+ return -EOPNOTSUPP;
+
if (!info->attrs[NL80211_ATTR_MAC])
return -EINVAL;
@@ -3671,8 +3674,30 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
- if (!rdev->ops->add_station)
- return -EOPNOTSUPP;
+ if (info->attrs[NL80211_ATTR_STA_WME]) {
+ struct nlattr *tb[NL80211_STA_WME_MAX + 1];
+ struct nlattr *nla;
+
+ 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;
+ }
if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
return -EINVAL;
@@ -3681,36 +3706,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_GO:
- /* parse WME attributes if sta is WME capable */
- if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
- (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
- info->attrs[NL80211_ATTR_STA_WME]) {
- struct nlattr *tb[NL80211_STA_WME_MAX + 1];
- struct nlattr *nla;
-
- 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;
+ /* ignore WME attributes if iface/sta is not capable */
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) ||
+ !(params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
+ params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
- 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;
- }
/* TDLS peers cannot be added */
if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
return -EINVAL;
@@ -3731,6 +3731,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return PTR_ERR(params.vlan);
break;
case NL80211_IFTYPE_MESH_POINT:
+ /* ignore uAPSD data */
+ params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
+
/* associated is disallowed */
if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
return -EINVAL;
@@ -3739,6 +3742,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
break;
case NL80211_IFTYPE_STATION:
+ /* ignore uAPSD data */
+ params.sta_modify_mask &= ~STATION_PARAM_APPLY_UAPSD;
+
/* associated is disallowed */
if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
return -EINVAL;