diff options
-rw-r--r-- | include/linux/nl80211.h | 21 | ||||
-rw-r--r-- | include/net/cfg80211.h | 28 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 28 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 38 |
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 | */ | ||
708 | struct 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 | */ | ||
267 | enum 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 | */ |
301 | struct station_parameters { | 283 | struct 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 | ||
1337 | static int parse_station_flags(struct nlattr *nla, u32 *staflags) | 1340 | static 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, ¶ms)) |
1652 | ¶ms.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, ¶ms)) |
1722 | ¶ms.station_flags)) | ||
1723 | return -EINVAL; | 1745 | return -EINVAL; |
1724 | 1746 | ||
1725 | rtnl_lock(); | 1747 | rtnl_lock(); |