aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/cfg.c76
-rw-r--r--net/mac80211/ibss.c5
-rw-r--r--net/mac80211/iface.c5
-rw-r--r--net/mac80211/mesh_plink.c7
-rw-r--r--net/mac80211/mlme.c6
-rw-r--r--net/mac80211/sta_info.c65
-rw-r--r--net/mac80211/sta_info.h37
-rw-r--r--net/mac80211/tx.c1
8 files changed, 172 insertions, 30 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3acda35df5cb..66ad9d9af87f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -746,10 +746,11 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
746 netif_rx_ni(skb); 746 netif_rx_ni(skb);
747} 747}
748 748
749static void sta_apply_parameters(struct ieee80211_local *local, 749static int sta_apply_parameters(struct ieee80211_local *local,
750 struct sta_info *sta, 750 struct sta_info *sta,
751 struct station_parameters *params) 751 struct station_parameters *params)
752{ 752{
753 int ret = 0;
753 u32 rates; 754 u32 rates;
754 int i, j; 755 int i, j;
755 struct ieee80211_supported_band *sband; 756 struct ieee80211_supported_band *sband;
@@ -761,13 +762,59 @@ static void sta_apply_parameters(struct ieee80211_local *local,
761 mask = params->sta_flags_mask; 762 mask = params->sta_flags_mask;
762 set = params->sta_flags_set; 763 set = params->sta_flags_set;
763 764
765 /*
766 * In mesh mode, we can clear AUTHENTICATED flag but must
767 * also make ASSOCIATED follow appropriately for the driver
768 * API. See also below, after AUTHORIZED changes.
769 */
770 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
771 /* cfg80211 should not allow this in non-mesh modes */
772 if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
773 return -EINVAL;
774
775 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
776 !test_sta_flag(sta, WLAN_STA_AUTH)) {
777 ret = sta_info_move_state_checked(sta,
778 IEEE80211_STA_AUTH);
779 if (ret)
780 return ret;
781 ret = sta_info_move_state_checked(sta,
782 IEEE80211_STA_ASSOC);
783 if (ret)
784 return ret;
785 }
786 }
787
764 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { 788 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
765 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) 789 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
766 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 790 ret = sta_info_move_state_checked(sta,
791 IEEE80211_STA_AUTHORIZED);
767 else 792 else
768 clear_sta_flag(sta, WLAN_STA_AUTHORIZED); 793 ret = sta_info_move_state_checked(sta,
794 IEEE80211_STA_ASSOC);
795 if (ret)
796 return ret;
769 } 797 }
770 798
799 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
800 /* cfg80211 should not allow this in non-mesh modes */
801 if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
802 return -EINVAL;
803
804 if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
805 test_sta_flag(sta, WLAN_STA_AUTH)) {
806 ret = sta_info_move_state_checked(sta,
807 IEEE80211_STA_AUTH);
808 if (ret)
809 return ret;
810 ret = sta_info_move_state_checked(sta,
811 IEEE80211_STA_NONE);
812 if (ret)
813 return ret;
814 }
815 }
816
817
771 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { 818 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
772 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) 819 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
773 set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE); 820 set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
@@ -792,13 +839,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
792 clear_sta_flag(sta, WLAN_STA_MFP); 839 clear_sta_flag(sta, WLAN_STA_MFP);
793 } 840 }
794 841
795 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
796 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
797 set_sta_flag(sta, WLAN_STA_AUTH);
798 else
799 clear_sta_flag(sta, WLAN_STA_AUTH);
800 }
801
802 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) { 842 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
803 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) 843 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
804 set_sta_flag(sta, WLAN_STA_TDLS_PEER); 844 set_sta_flag(sta, WLAN_STA_TDLS_PEER);
@@ -870,6 +910,8 @@ static void sta_apply_parameters(struct ieee80211_local *local,
870 } 910 }
871#endif 911#endif
872 } 912 }
913
914 return 0;
873} 915}
874 916
875static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, 917static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
@@ -900,10 +942,14 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
900 if (!sta) 942 if (!sta)
901 return -ENOMEM; 943 return -ENOMEM;
902 944
903 set_sta_flag(sta, WLAN_STA_AUTH); 945 sta_info_move_state(sta, IEEE80211_STA_AUTH);
904 set_sta_flag(sta, WLAN_STA_ASSOC); 946 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
905 947
906 sta_apply_parameters(local, sta, params); 948 err = sta_apply_parameters(local, sta, params);
949 if (err) {
950 sta_info_free(local, sta);
951 return err;
952 }
907 953
908 /* 954 /*
909 * for TDLS, rate control should be initialized only when supported 955 * for TDLS, rate control should be initialized only when supported
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index fe0e91e0b8bc..47e2db9133cb 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -512,7 +512,10 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
512 return NULL; 512 return NULL;
513 513
514 sta->last_rx = jiffies; 514 sta->last_rx = jiffies;
515 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 515
516 sta_info_move_state(sta, IEEE80211_STA_AUTH);
517 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
518 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
516 519
517 /* make sure mandatory rates are always added */ 520 /* make sure mandatory rates are always added */
518 sta->sta.supp_rates[band] = supp_rates | 521 sta->sta.supp_rates[band] = supp_rates |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 3d3bb5e9d8fa..e47768cb8cb3 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -318,8 +318,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
318 goto err_del_interface; 318 goto err_del_interface;
319 } 319 }
320 320
321 /* no atomic bitop required since STA is not live yet */ 321 sta_info_move_state(sta, IEEE80211_STA_AUTH);
322 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 322 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
323 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
323 324
324 res = sta_info_insert(sta); 325 res = sta_info_insert(sta);
325 if (res) { 326 if (res) {
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 7314372b12ba..41ef1b476442 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -96,9 +96,12 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
96 if (!sta) 96 if (!sta)
97 return NULL; 97 return NULL;
98 98
99 set_sta_flag(sta, WLAN_STA_AUTH); 99 sta_info_move_state(sta, IEEE80211_STA_AUTH);
100 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 100 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
101 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
102
101 set_sta_flag(sta, WLAN_STA_WME); 103 set_sta_flag(sta, WLAN_STA_WME);
104
102 sta->sta.supp_rates[local->hw.conf.channel->band] = rates; 105 sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
103 if (elems->ht_cap_elem) 106 if (elems->ht_cap_elem)
104 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, 107 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 09019d135942..3789b82f1098 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1577,10 +1577,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1577 return false; 1577 return false;
1578 } 1578 }
1579 1579
1580 set_sta_flag(sta, WLAN_STA_AUTH); 1580 sta_info_move_state(sta, IEEE80211_STA_AUTH);
1581 set_sta_flag(sta, WLAN_STA_ASSOC); 1581 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1582 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) 1582 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
1583 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 1583 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
1584 1584
1585 rates = 0; 1585 rates = 0;
1586 basic_rates = 0; 1586 basic_rates = 0;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index c6ca9bd81add..b22775cdcdf5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -204,16 +204,17 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
204} 204}
205 205
206/** 206/**
207 * __sta_info_free - internal STA free helper 207 * sta_info_free - free STA
208 * 208 *
209 * @local: pointer to the global information 209 * @local: pointer to the global information
210 * @sta: STA info to free 210 * @sta: STA info to free
211 * 211 *
212 * This function must undo everything done by sta_info_alloc() 212 * This function must undo everything done by sta_info_alloc()
213 * that may happen before sta_info_insert(). 213 * that may happen before sta_info_insert(). It may only be
214 * called when sta_info_insert() has not been attempted (and
215 * if that fails, the station is freed anyway.)
214 */ 216 */
215static void __sta_info_free(struct ieee80211_local *local, 217void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
216 struct sta_info *sta)
217{ 218{
218 if (sta->rate_ctrl) { 219 if (sta->rate_ctrl) {
219 rate_control_free_sta(sta); 220 rate_control_free_sta(sta);
@@ -598,7 +599,7 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)
598 return 0; 599 return 0;
599 out_free: 600 out_free:
600 BUG_ON(!err); 601 BUG_ON(!err);
601 __sta_info_free(local, sta); 602 sta_info_free(local, sta);
602 return err; 603 return err;
603} 604}
604 605
@@ -905,6 +906,9 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
905 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 906 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
906 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL); 907 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
907 908
909 while (sta->sta_state > IEEE80211_STA_NONE)
910 sta_info_move_state(sta, sta->sta_state - 1);
911
908 if (sta->uploaded) { 912 if (sta->uploaded) {
909 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 913 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
910 sdata = container_of(sdata->bss, 914 sdata = container_of(sdata->bss,
@@ -974,7 +978,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
974 kfree_rcu(tid_tx, rcu_head); 978 kfree_rcu(tid_tx, rcu_head);
975 } 979 }
976 980
977 __sta_info_free(local, sta); 981 sta_info_free(local, sta);
978 982
979 return 0; 983 return 0;
980} 984}
@@ -1538,3 +1542,52 @@ void ieee80211_sta_set_buffered(struct ieee80211_sta *pubsta,
1538 sta_info_recalc_tim(sta); 1542 sta_info_recalc_tim(sta);
1539} 1543}
1540EXPORT_SYMBOL(ieee80211_sta_set_buffered); 1544EXPORT_SYMBOL(ieee80211_sta_set_buffered);
1545
1546int sta_info_move_state_checked(struct sta_info *sta,
1547 enum ieee80211_sta_state new_state)
1548{
1549 /* might_sleep(); -- for driver notify later, fix IBSS first */
1550
1551 if (sta->sta_state == new_state)
1552 return 0;
1553
1554 switch (new_state) {
1555 case IEEE80211_STA_NONE:
1556 if (sta->sta_state == IEEE80211_STA_AUTH)
1557 clear_bit(WLAN_STA_AUTH, &sta->_flags);
1558 else
1559 return -EINVAL;
1560 break;
1561 case IEEE80211_STA_AUTH:
1562 if (sta->sta_state == IEEE80211_STA_NONE)
1563 set_bit(WLAN_STA_AUTH, &sta->_flags);
1564 else if (sta->sta_state == IEEE80211_STA_ASSOC)
1565 clear_bit(WLAN_STA_ASSOC, &sta->_flags);
1566 else
1567 return -EINVAL;
1568 break;
1569 case IEEE80211_STA_ASSOC:
1570 if (sta->sta_state == IEEE80211_STA_AUTH)
1571 set_bit(WLAN_STA_ASSOC, &sta->_flags);
1572 else if (sta->sta_state == IEEE80211_STA_AUTHORIZED)
1573 clear_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
1574 else
1575 return -EINVAL;
1576 break;
1577 case IEEE80211_STA_AUTHORIZED:
1578 if (sta->sta_state == IEEE80211_STA_ASSOC)
1579 set_bit(WLAN_STA_AUTHORIZED, &sta->_flags);
1580 else
1581 return -EINVAL;
1582 break;
1583 default:
1584 WARN(1, "invalid state %d", new_state);
1585 return -EINVAL;
1586 }
1587
1588 printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
1589 sta->sdata->name, sta->sta.addr, new_state);
1590 sta->sta_state = new_state;
1591
1592 return 0;
1593}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1a14fab4bc9a..63f4d316a954 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -73,6 +73,14 @@ enum ieee80211_sta_info_flags {
73 WLAN_STA_4ADDR_EVENT, 73 WLAN_STA_4ADDR_EVENT,
74}; 74};
75 75
76enum ieee80211_sta_state {
77 /* NOTE: These need to be ordered correctly! */
78 IEEE80211_STA_NONE,
79 IEEE80211_STA_AUTH,
80 IEEE80211_STA_ASSOC,
81 IEEE80211_STA_AUTHORIZED,
82};
83
76#define STA_TID_NUM 16 84#define STA_TID_NUM 16
77#define ADDBA_RESP_INTERVAL HZ 85#define ADDBA_RESP_INTERVAL HZ
78#define HT_AGG_MAX_RETRIES 0x3 86#define HT_AGG_MAX_RETRIES 0x3
@@ -262,6 +270,7 @@ struct sta_ampdu_mlme {
262 * @dummy: indicate a dummy station created for receiving 270 * @dummy: indicate a dummy station created for receiving
263 * EAP frames before association 271 * EAP frames before association
264 * @sta: station information we share with the driver 272 * @sta: station information we share with the driver
273 * @sta_state: duplicates information about station state (for debug)
265 */ 274 */
266struct sta_info { 275struct sta_info {
267 /* General information, mostly static */ 276 /* General information, mostly static */
@@ -283,6 +292,8 @@ struct sta_info {
283 292
284 bool uploaded; 293 bool uploaded;
285 294
295 enum ieee80211_sta_state sta_state;
296
286 /* use the accessors defined below */ 297 /* use the accessors defined below */
287 unsigned long _flags; 298 unsigned long _flags;
288 299
@@ -371,12 +382,18 @@ static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta)
371static inline void set_sta_flag(struct sta_info *sta, 382static inline void set_sta_flag(struct sta_info *sta,
372 enum ieee80211_sta_info_flags flag) 383 enum ieee80211_sta_info_flags flag)
373{ 384{
385 WARN_ON(flag == WLAN_STA_AUTH ||
386 flag == WLAN_STA_ASSOC ||
387 flag == WLAN_STA_AUTHORIZED);
374 set_bit(flag, &sta->_flags); 388 set_bit(flag, &sta->_flags);
375} 389}
376 390
377static inline void clear_sta_flag(struct sta_info *sta, 391static inline void clear_sta_flag(struct sta_info *sta,
378 enum ieee80211_sta_info_flags flag) 392 enum ieee80211_sta_info_flags flag)
379{ 393{
394 WARN_ON(flag == WLAN_STA_AUTH ||
395 flag == WLAN_STA_ASSOC ||
396 flag == WLAN_STA_AUTHORIZED);
380 clear_bit(flag, &sta->_flags); 397 clear_bit(flag, &sta->_flags);
381} 398}
382 399
@@ -389,15 +406,32 @@ static inline int test_sta_flag(struct sta_info *sta,
389static inline int test_and_clear_sta_flag(struct sta_info *sta, 406static inline int test_and_clear_sta_flag(struct sta_info *sta,
390 enum ieee80211_sta_info_flags flag) 407 enum ieee80211_sta_info_flags flag)
391{ 408{
409 WARN_ON(flag == WLAN_STA_AUTH ||
410 flag == WLAN_STA_ASSOC ||
411 flag == WLAN_STA_AUTHORIZED);
392 return test_and_clear_bit(flag, &sta->_flags); 412 return test_and_clear_bit(flag, &sta->_flags);
393} 413}
394 414
395static inline int test_and_set_sta_flag(struct sta_info *sta, 415static inline int test_and_set_sta_flag(struct sta_info *sta,
396 enum ieee80211_sta_info_flags flag) 416 enum ieee80211_sta_info_flags flag)
397{ 417{
418 WARN_ON(flag == WLAN_STA_AUTH ||
419 flag == WLAN_STA_ASSOC ||
420 flag == WLAN_STA_AUTHORIZED);
398 return test_and_set_bit(flag, &sta->_flags); 421 return test_and_set_bit(flag, &sta->_flags);
399} 422}
400 423
424int sta_info_move_state_checked(struct sta_info *sta,
425 enum ieee80211_sta_state new_state);
426
427static inline void sta_info_move_state(struct sta_info *sta,
428 enum ieee80211_sta_state new_state)
429{
430 int ret = sta_info_move_state_checked(sta, new_state);
431 WARN_ON_ONCE(ret);
432}
433
434
401void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, 435void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
402 struct tid_ampdu_tx *tid_tx); 436 struct tid_ampdu_tx *tid_tx);
403 437
@@ -489,6 +523,9 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
489 */ 523 */
490struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, 524struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
491 u8 *addr, gfp_t gfp); 525 u8 *addr, gfp_t gfp);
526
527void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
528
492/* 529/*
493 * Insert STA info into hash table/list, returns zero or a 530 * Insert STA info into hash table/list, returns zero or a
494 * -EEXIST if (if the same MAC address is already present). 531 * -EEXIST if (if the same MAC address is already present).
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e74652d38245..50c4be9a6404 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -295,7 +295,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
295 295
296 if (likely(tx->flags & IEEE80211_TX_UNICAST)) { 296 if (likely(tx->flags & IEEE80211_TX_UNICAST)) {
297 if (unlikely(!assoc && 297 if (unlikely(!assoc &&
298 tx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
299 ieee80211_is_data(hdr->frame_control))) { 298 ieee80211_is_data(hdr->frame_control))) {
300#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 299#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
301 printk(KERN_DEBUG "%s: dropped data frame to not " 300 printk(KERN_DEBUG "%s: dropped data frame to not "