aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 2353ddbf4934..66024ef57bab 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -123,6 +123,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
123 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG }, 123 [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
124 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG }, 124 [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
125 [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 }, 125 [NL80211_ATTR_USE_MFP] = { .type = NLA_U32 },
126 [NL80211_ATTR_STA_FLAGS2] = {
127 .len = sizeof(struct nl80211_sta_flag_update),
128 },
126}; 129};
127 130
128/* IE validation */ 131/* IE validation */
@@ -1334,13 +1337,33 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
1334 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG }, 1337 [NL80211_STA_FLAG_MFP] = { .type = NLA_FLAG },
1335}; 1338};
1336 1339
1337static int parse_station_flags(struct nlattr *nla, u32 *staflags) 1340static int parse_station_flags(struct genl_info *info,
1341 struct station_parameters *params)
1338{ 1342{
1339 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; 1343 struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
1344 struct nlattr *nla;
1340 int flag; 1345 int flag;
1341 1346
1342 *staflags = 0; 1347 /*
1348 * Try parsing the new attribute first so userspace
1349 * can specify both for older kernels.
1350 */
1351 nla = info->attrs[NL80211_ATTR_STA_FLAGS2];
1352 if (nla) {
1353 struct nl80211_sta_flag_update *sta_flags;
1354
1355 sta_flags = nla_data(nla);
1356 params->sta_flags_mask = sta_flags->mask;
1357 params->sta_flags_set = sta_flags->set;
1358 if ((params->sta_flags_mask |
1359 params->sta_flags_set) & BIT(__NL80211_STA_FLAG_INVALID))
1360 return -EINVAL;
1361 return 0;
1362 }
1363
1364 /* if present, parse the old attribute */
1343 1365
1366 nla = info->attrs[NL80211_ATTR_STA_FLAGS];
1344 if (!nla) 1367 if (!nla)
1345 return 0; 1368 return 0;
1346 1369
@@ -1348,11 +1371,12 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
1348 nla, sta_flags_policy)) 1371 nla, sta_flags_policy))
1349 return -EINVAL; 1372 return -EINVAL;
1350 1373
1351 *staflags = STATION_FLAG_CHANGED; 1374 params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1;
1375 params->sta_flags_mask &= ~1;
1352 1376
1353 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) 1377 for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
1354 if (flags[flag]) 1378 if (flags[flag])
1355 *staflags |= (1<<flag); 1379 params->sta_flags_set |= (1<<flag);
1356 1380
1357 return 0; 1381 return 0;
1358} 1382}
@@ -1648,8 +1672,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1648 params.ht_capa = 1672 params.ht_capa =
1649 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 1673 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1650 1674
1651 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], 1675 if (parse_station_flags(info, &params))
1652 &params.station_flags))
1653 return -EINVAL; 1676 return -EINVAL;
1654 1677
1655 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) 1678 if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
@@ -1718,8 +1741,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1718 params.ht_capa = 1741 params.ht_capa =
1719 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 1742 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
1720 1743
1721 if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], 1744 if (parse_station_flags(info, &params))
1722 &params.station_flags))
1723 return -EINVAL; 1745 return -EINVAL;
1724 1746
1725 rtnl_lock(); 1747 rtnl_lock();