|
@@ -510,6 +510,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|
|
BIT(NL80211_STA_FLAG_WME) |
|
|
|
BIT(NL80211_STA_FLAG_MFP) |
|
|
|
BIT(NL80211_STA_FLAG_AUTHENTICATED) |
|
|
|
+ BIT(NL80211_STA_FLAG_ASSOCIATED) |
|
|
|
BIT(NL80211_STA_FLAG_TDLS_PEER);
|
|
|
if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
|
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
|
|
@@ -521,6 +522,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|
|
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
|
|
|
if (test_sta_flag(sta, WLAN_STA_AUTH))
|
|
|
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
|
|
|
+ if (test_sta_flag(sta, WLAN_STA_ASSOC))
|
|
|
+ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
|
|
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
|
|
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
|
|
}
|
|
@@ -1077,6 +1080,58 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
|
|
|
netif_rx_ni(skb);
|
|
|
}
|
|
|
|
|
|
+static int sta_apply_auth_flags(struct ieee80211_local *local,
|
|
|
+ struct sta_info *sta,
|
|
|
+ u32 mask, u32 set)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
|
|
|
+ set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
|
|
|
+ !test_sta_flag(sta, WLAN_STA_AUTH)) {
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
|
|
|
+ set & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
|
|
|
+ !test_sta_flag(sta, WLAN_STA_ASSOC)) {
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
|
|
+ if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
|
|
+ else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
+ else
|
|
|
+ ret = 0;
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
|
|
|
+ !(set & BIT(NL80211_STA_FLAG_ASSOCIATED)) &&
|
|
|
+ test_sta_flag(sta, WLAN_STA_ASSOC)) {
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
|
|
|
+ !(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
|
|
|
+ test_sta_flag(sta, WLAN_STA_AUTH)) {
|
|
|
+ ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int sta_apply_parameters(struct ieee80211_local *local,
|
|
|
struct sta_info *sta,
|
|
|
struct station_parameters *params)
|
|
@@ -1094,52 +1149,20 @@ static int sta_apply_parameters(struct ieee80211_local *local,
|
|
|
mask = params->sta_flags_mask;
|
|
|
set = params->sta_flags_set;
|
|
|
|
|
|
- /*
|
|
|
- * In mesh mode, we can clear AUTHENTICATED flag but must
|
|
|
- * also make ASSOCIATED follow appropriately for the driver
|
|
|
- * API. See also below, after AUTHORIZED changes.
|
|
|
- */
|
|
|
- if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
|
|
|
- /* cfg80211 should not allow this in non-mesh modes */
|
|
|
- if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
|
|
|
- !test_sta_flag(sta, WLAN_STA_AUTH)) {
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
|
|
|
- if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
|
|
|
- else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
-
|
|
|
- if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
|
|
|
- /* cfg80211 should not allow this in non-mesh modes */
|
|
|
- if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
|
|
|
- test_sta_flag(sta, WLAN_STA_AUTH)) {
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
|
|
+ /*
|
|
|
+ * In mesh mode, ASSOCIATED isn't part of the nl80211
|
|
|
+ * API but must follow AUTHENTICATED for driver state.
|
|
|
+ */
|
|
|
+ if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED))
|
|
|
+ mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
|
|
+ if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
|
|
|
+ set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
|
|
}
|
|
|
|
|
|
+ ret = sta_apply_auth_flags(local, sta, mask, set);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
|
|
|
if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
|
|
@@ -1273,6 +1296,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
|
|
|
if (!sta)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ /*
|
|
|
+ * defaults -- if userspace wants something else we'll
|
|
|
+ * change it accordingly in sta_apply_parameters()
|
|
|
+ */
|
|
|
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
|
|
|
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
|
|
|
|