diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 76 |
1 files changed, 61 insertions, 15 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 | ||
749 | static void sta_apply_parameters(struct ieee80211_local *local, | 749 | static 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 | ||
875 | static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | 917 | static 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 |