aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-05-11 14:57:56 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-05-13 15:44:35 -0400
commiteccb8e8f0c3af47aeb6dbe4012eb8d4fc888767a (patch)
tree3705a833e4a5efb08beb2bfc4175775171e74295 /net/wireless
parent0e46724a48fcc3bac1fecea413d20af64a75844f (diff)
nl80211: improve station flags handling
It is currently not possible to modify station flags, but that capability would be very useful. This patch introduces a new nl80211 attribute that contains a set/mask for station flags, and updates the internal API (and mac80211) to mirror that. The new attribute is parsed before falling back to the old so that userspace can specify both (if it can) to work on all kernels. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-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();