aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/linux/nl80211.h21
-rw-r--r--include/net/cfg80211.h28
-rw-r--r--net/mac80211/cfg.c28
-rw-r--r--net/wireless/nl80211.c38
4 files changed, 71 insertions, 44 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 58c4ee1822d3..aeefccfac0e1 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -25,6 +25,8 @@
25 * 25 *
26 */ 26 */
27 27
28#include <linux/types.h>
29
28/** 30/**
29 * DOC: Station handling 31 * DOC: Station handling
30 * 32 *
@@ -380,7 +382,7 @@ enum nl80211_commands {
380 * 382 *
381 * @NL80211_ATTR_STA_AID: Association ID for the station (u16) 383 * @NL80211_ATTR_STA_AID: Association ID for the station (u16)
382 * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of 384 * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of
383 * &enum nl80211_sta_flags. 385 * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2)
384 * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by 386 * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by
385 * IEEE 802.11 7.3.1.6 (u16). 387 * IEEE 802.11 7.3.1.6 (u16).
386 * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported 388 * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported
@@ -499,6 +501,9 @@ enum nl80211_commands {
499 * this attribute can be used 501 * this attribute can be used
500 * with %NL80211_CMD_ASSOCIATE request 502 * with %NL80211_CMD_ASSOCIATE request
501 * 503 *
504 * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
505 * &struct nl80211_sta_flag_update.
506 *
502 * @NL80211_ATTR_MAX: highest attribute number currently defined 507 * @NL80211_ATTR_MAX: highest attribute number currently defined
503 * @__NL80211_ATTR_AFTER_LAST: internal use 508 * @__NL80211_ATTR_AFTER_LAST: internal use
504 */ 509 */
@@ -603,6 +608,8 @@ enum nl80211_attrs {
603 608
604 NL80211_ATTR_USE_MFP, 609 NL80211_ATTR_USE_MFP,
605 610
611 NL80211_ATTR_STA_FLAGS2,
612
606 /* add attributes here, update the policy in nl80211.c */ 613 /* add attributes here, update the policy in nl80211.c */
607 614
608 __NL80211_ATTR_AFTER_LAST, 615 __NL80211_ATTR_AFTER_LAST,
@@ -692,6 +699,18 @@ enum nl80211_sta_flags {
692}; 699};
693 700
694/** 701/**
702 * struct nl80211_sta_flag_update - station flags mask/set
703 * @mask: mask of station flags to set
704 * @set: which values to set them to
705 *
706 * Both mask and set contain bits as per &enum nl80211_sta_flags.
707 */
708struct nl80211_sta_flag_update {
709 __u32 mask;
710 __u32 set;
711} __attribute__((packed));
712
713/**
695 * enum nl80211_rate_info - bitrate information 714 * enum nl80211_rate_info - bitrate information
696 * 715 *
697 * These attribute types are used with %NL80211_STA_INFO_TXRATE 716 * These attribute types are used with %NL80211_STA_INFO_TXRATE
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e69e6c66dd16..0dae6b382940 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -252,27 +252,6 @@ struct beacon_parameters {
252}; 252};
253 253
254/** 254/**
255 * enum station_flags - station flags
256 *
257 * Station capability flags. Note that these must be the bits
258 * according to the nl80211 flags.
259 *
260 * @STATION_FLAG_CHANGED: station flags were changed
261 * @STATION_FLAG_AUTHORIZED: station is authorized to send frames (802.1X)
262 * @STATION_FLAG_SHORT_PREAMBLE: station is capable of receiving frames
263 * with short preambles
264 * @STATION_FLAG_WME: station is WME/QoS capable
265 * @STATION_FLAG_MFP: station uses management frame protection
266 */
267enum station_flags {
268 STATION_FLAG_CHANGED = 1<<0,
269 STATION_FLAG_AUTHORIZED = 1<<NL80211_STA_FLAG_AUTHORIZED,
270 STATION_FLAG_SHORT_PREAMBLE = 1<<NL80211_STA_FLAG_SHORT_PREAMBLE,
271 STATION_FLAG_WME = 1<<NL80211_STA_FLAG_WME,
272 STATION_FLAG_MFP = 1<<NL80211_STA_FLAG_MFP,
273};
274
275/**
276 * enum plink_action - actions to perform in mesh peers 255 * enum plink_action - actions to perform in mesh peers
277 * 256 *
278 * @PLINK_ACTION_INVALID: action 0 is reserved 257 * @PLINK_ACTION_INVALID: action 0 is reserved
@@ -294,14 +273,17 @@ enum plink_actions {
294 * @supported_rates: supported rates in IEEE 802.11 format 273 * @supported_rates: supported rates in IEEE 802.11 format
295 * (or NULL for no change) 274 * (or NULL for no change)
296 * @supported_rates_len: number of supported rates 275 * @supported_rates_len: number of supported rates
297 * @station_flags: station flags (see &enum station_flags) 276 * @sta_flags_mask: station flags that changed
277 * (bitmask of BIT(NL80211_STA_FLAG_...))
278 * @sta_flags_set: station flags values
279 * (bitmask of BIT(NL80211_STA_FLAG_...))
298 * @listen_interval: listen interval or -1 for no change 280 * @listen_interval: listen interval or -1 for no change
299 * @aid: AID or zero for no change 281 * @aid: AID or zero for no change
300 */ 282 */
301struct station_parameters { 283struct station_parameters {
302 u8 *supported_rates; 284 u8 *supported_rates;
303 struct net_device *vlan; 285 struct net_device *vlan;
304 u32 station_flags; 286 u32 sta_flags_mask, sta_flags_set;
305 int listen_interval; 287 int listen_interval;
306 u16 aid; 288 u16 aid;
307 u8 supported_rates_len; 289 u8 supported_rates_len;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index be86e159e6ef..d591a936f5c4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -629,34 +629,38 @@ static void sta_apply_parameters(struct ieee80211_local *local,
629 int i, j; 629 int i, j;
630 struct ieee80211_supported_band *sband; 630 struct ieee80211_supported_band *sband;
631 struct ieee80211_sub_if_data *sdata = sta->sdata; 631 struct ieee80211_sub_if_data *sdata = sta->sdata;
632 u32 mask, set;
632 633
633 sband = local->hw.wiphy->bands[local->oper_channel->band]; 634 sband = local->hw.wiphy->bands[local->oper_channel->band];
634 635
635 /* 636 spin_lock_bh(&sta->lock);
636 * FIXME: updating the flags is racy when this function is 637 mask = params->sta_flags_mask;
637 * called from ieee80211_change_station(), this will 638 set = params->sta_flags_set;
638 * be resolved in a future patch.
639 */
640 639
641 if (params->station_flags & STATION_FLAG_CHANGED) { 640 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
642 spin_lock_bh(&sta->lock);
643 sta->flags &= ~WLAN_STA_AUTHORIZED; 641 sta->flags &= ~WLAN_STA_AUTHORIZED;
644 if (params->station_flags & STATION_FLAG_AUTHORIZED) 642 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
645 sta->flags |= WLAN_STA_AUTHORIZED; 643 sta->flags |= WLAN_STA_AUTHORIZED;
644 }
646 645
646 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
647 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; 647 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
648 if (params->station_flags & STATION_FLAG_SHORT_PREAMBLE) 648 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
649 sta->flags |= WLAN_STA_SHORT_PREAMBLE; 649 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
650 }
650 651
652 if (mask & BIT(NL80211_STA_FLAG_WME)) {
651 sta->flags &= ~WLAN_STA_WME; 653 sta->flags &= ~WLAN_STA_WME;
652 if (params->station_flags & STATION_FLAG_WME) 654 if (set & BIT(NL80211_STA_FLAG_WME))
653 sta->flags |= WLAN_STA_WME; 655 sta->flags |= WLAN_STA_WME;
656 }
654 657
658 if (mask & BIT(NL80211_STA_FLAG_MFP)) {
655 sta->flags &= ~WLAN_STA_MFP; 659 sta->flags &= ~WLAN_STA_MFP;
656 if (params->station_flags & STATION_FLAG_MFP) 660 if (set & BIT(NL80211_STA_FLAG_MFP))
657 sta->flags |= WLAN_STA_MFP; 661 sta->flags |= WLAN_STA_MFP;
658 spin_unlock_bh(&sta->lock);
659 } 662 }
663 spin_unlock_bh(&sta->lock);
660 664
661 /* 665 /*
662 * FIXME: updating the following information is racy when this 666 * FIXME: updating the following information is racy when this
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();