aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/nl80211.h16
-rw-r--r--net/mac80211/cfg.c115
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/wireless/nl80211.c24
4 files changed, 113 insertions, 45 deletions
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e3e19f8b16f2..547017100a30 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1697,6 +1697,9 @@ enum nl80211_iftype {
1697 * flag can't be changed, it is only valid while adding a station, and 1697 * flag can't be changed, it is only valid while adding a station, and
1698 * attempts to change it will silently be ignored (rather than rejected 1698 * attempts to change it will silently be ignored (rather than rejected
1699 * as errors.) 1699 * as errors.)
1700 * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers
1701 * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a
1702 * previously added station into associated state
1700 * @NL80211_STA_FLAG_MAX: highest station flag number currently defined 1703 * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
1701 * @__NL80211_STA_FLAG_AFTER_LAST: internal use 1704 * @__NL80211_STA_FLAG_AFTER_LAST: internal use
1702 */ 1705 */
@@ -1708,6 +1711,7 @@ enum nl80211_sta_flags {
1708 NL80211_STA_FLAG_MFP, 1711 NL80211_STA_FLAG_MFP,
1709 NL80211_STA_FLAG_AUTHENTICATED, 1712 NL80211_STA_FLAG_AUTHENTICATED,
1710 NL80211_STA_FLAG_TDLS_PEER, 1713 NL80211_STA_FLAG_TDLS_PEER,
1714 NL80211_STA_FLAG_ASSOCIATED,
1711 1715
1712 /* keep last */ 1716 /* keep last */
1713 __NL80211_STA_FLAG_AFTER_LAST, 1717 __NL80211_STA_FLAG_AFTER_LAST,
@@ -3140,6 +3144,17 @@ enum nl80211_ap_sme_features {
3140 * setting 3144 * setting
3141 * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic 3145 * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic
3142 * powersave 3146 * powersave
3147 * @NL80211_FEATURE_FULL_AP_CLIENT_STATE: The driver supports full state
3148 * transitions for AP clients. Without this flag (and if the driver
3149 * doesn't have the AP SME in the device) the driver supports adding
3150 * stations only when they're associated and adds them in associated
3151 * state (to later be transitioned into authorized), with this flag
3152 * they should be added before even sending the authentication reply
3153 * and then transitioned into authenticated, associated and authorized
3154 * states using station flags.
3155 * Note that even for drivers that support this, the default is to add
3156 * stations in authenticated/associated state, so to add unauthenticated
3157 * stations the authenticated/associated bits have to be set in the mask.
3143 */ 3158 */
3144enum nl80211_feature_flags { 3159enum nl80211_feature_flags {
3145 NL80211_FEATURE_SK_TX_STATUS = 1 << 0, 3160 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3155,6 +3170,7 @@ enum nl80211_feature_flags {
3155 NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, 3170 NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10,
3156 NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, 3171 NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
3157 NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, 3172 NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
3173 NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 13,
3158}; 3174};
3159 3175
3160/** 3176/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3e7d557fd481..f4d12c71928d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -510,6 +510,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
510 BIT(NL80211_STA_FLAG_WME) | 510 BIT(NL80211_STA_FLAG_WME) |
511 BIT(NL80211_STA_FLAG_MFP) | 511 BIT(NL80211_STA_FLAG_MFP) |
512 BIT(NL80211_STA_FLAG_AUTHENTICATED) | 512 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
513 BIT(NL80211_STA_FLAG_ASSOCIATED) |
513 BIT(NL80211_STA_FLAG_TDLS_PEER); 514 BIT(NL80211_STA_FLAG_TDLS_PEER);
514 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) 515 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
515 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); 516 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)
521 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); 522 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
522 if (test_sta_flag(sta, WLAN_STA_AUTH)) 523 if (test_sta_flag(sta, WLAN_STA_AUTH))
523 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); 524 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
525 if (test_sta_flag(sta, WLAN_STA_ASSOC))
526 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
524 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) 527 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
525 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); 528 sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
526} 529}
@@ -1077,6 +1080,58 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
1077 netif_rx_ni(skb); 1080 netif_rx_ni(skb);
1078} 1081}
1079 1082
1083static int sta_apply_auth_flags(struct ieee80211_local *local,
1084 struct sta_info *sta,
1085 u32 mask, u32 set)
1086{
1087 int ret;
1088
1089 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
1090 set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
1091 !test_sta_flag(sta, WLAN_STA_AUTH)) {
1092 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
1093 if (ret)
1094 return ret;
1095 }
1096
1097 if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
1098 set & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
1099 !test_sta_flag(sta, WLAN_STA_ASSOC)) {
1100 ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1101 if (ret)
1102 return ret;
1103 }
1104
1105 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
1106 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
1107 ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
1108 else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
1109 ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1110 else
1111 ret = 0;
1112 if (ret)
1113 return ret;
1114 }
1115
1116 if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
1117 !(set & BIT(NL80211_STA_FLAG_ASSOCIATED)) &&
1118 test_sta_flag(sta, WLAN_STA_ASSOC)) {
1119 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
1120 if (ret)
1121 return ret;
1122 }
1123
1124 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
1125 !(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
1126 test_sta_flag(sta, WLAN_STA_AUTH)) {
1127 ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
1128 if (ret)
1129 return ret;
1130 }
1131
1132 return 0;
1133}
1134
1080static int sta_apply_parameters(struct ieee80211_local *local, 1135static int sta_apply_parameters(struct ieee80211_local *local,
1081 struct sta_info *sta, 1136 struct sta_info *sta,
1082 struct station_parameters *params) 1137 struct station_parameters *params)
@@ -1094,52 +1149,20 @@ static int sta_apply_parameters(struct ieee80211_local *local,
1094 mask = params->sta_flags_mask; 1149 mask = params->sta_flags_mask;
1095 set = params->sta_flags_set; 1150 set = params->sta_flags_set;
1096 1151
1097 /* 1152 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1098 * In mesh mode, we can clear AUTHENTICATED flag but must 1153 /*
1099 * also make ASSOCIATED follow appropriately for the driver 1154 * In mesh mode, ASSOCIATED isn't part of the nl80211
1100 * API. See also below, after AUTHORIZED changes. 1155 * API but must follow AUTHENTICATED for driver state.
1101 */ 1156 */
1102 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { 1157 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED))
1103 /* cfg80211 should not allow this in non-mesh modes */ 1158 mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
1104 if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) 1159 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
1105 return -EINVAL; 1160 set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
1106
1107 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
1108 !test_sta_flag(sta, WLAN_STA_AUTH)) {
1109 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
1110 if (ret)
1111 return ret;
1112 ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1113 if (ret)
1114 return ret;
1115 }
1116 }
1117
1118 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
1119 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
1120 ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
1121 else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
1122 ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1123 if (ret)
1124 return ret;
1125 }
1126
1127 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
1128 /* cfg80211 should not allow this in non-mesh modes */
1129 if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif)))
1130 return -EINVAL;
1131
1132 if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
1133 test_sta_flag(sta, WLAN_STA_AUTH)) {
1134 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
1135 if (ret)
1136 return ret;
1137 ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
1138 if (ret)
1139 return ret;
1140 }
1141 } 1161 }
1142 1162
1163 ret = sta_apply_auth_flags(local, sta, mask, set);
1164 if (ret)
1165 return ret;
1143 1166
1144 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { 1167 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
1145 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) 1168 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
@@ -1273,6 +1296,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
1273 if (!sta) 1296 if (!sta)
1274 return -ENOMEM; 1297 return -ENOMEM;
1275 1298
1299 /*
1300 * defaults -- if userspace wants something else we'll
1301 * change it accordingly in sta_apply_parameters()
1302 */
1276 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); 1303 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
1277 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); 1304 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
1278 1305
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index e6514f240fce..39cfe8f10ad2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -541,7 +541,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
541 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS | 541 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
542 NL80211_FEATURE_SAE | 542 NL80211_FEATURE_SAE |
543 NL80211_FEATURE_HT_IBSS | 543 NL80211_FEATURE_HT_IBSS |
544 NL80211_FEATURE_VIF_TXPOWER; 544 NL80211_FEATURE_VIF_TXPOWER |
545 NL80211_FEATURE_FULL_AP_CLIENT_STATE;
545 546
546 if (!ops->hw_scan) 547 if (!ops->hw_scan)
547 wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | 548 wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b3cf7cc0d4a1..087f68ba6d7a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3231,11 +3231,21 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3231 /* accept only the listed bits */ 3231 /* accept only the listed bits */
3232 if (params.sta_flags_mask & 3232 if (params.sta_flags_mask &
3233 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | 3233 ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
3234 BIT(NL80211_STA_FLAG_AUTHENTICATED) |
3235 BIT(NL80211_STA_FLAG_ASSOCIATED) |
3234 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | 3236 BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
3235 BIT(NL80211_STA_FLAG_WME) | 3237 BIT(NL80211_STA_FLAG_WME) |
3236 BIT(NL80211_STA_FLAG_MFP))) 3238 BIT(NL80211_STA_FLAG_MFP)))
3237 return -EINVAL; 3239 return -EINVAL;
3238 3240
3241 /* but authenticated/associated only if driver handles it */
3242 if (!(rdev->wiphy.features &
3243 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
3244 params.sta_flags_mask &
3245 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
3246 BIT(NL80211_STA_FLAG_ASSOCIATED)))
3247 return -EINVAL;
3248
3239 /* must be last in here for error handling */ 3249 /* must be last in here for error handling */
3240 params.vlan = get_vlan(info, rdev); 3250 params.vlan = get_vlan(info, rdev);
3241 if (IS_ERR(params.vlan)) 3251 if (IS_ERR(params.vlan))
@@ -3393,17 +3403,31 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
3393 /* but don't bother the driver with it */ 3403 /* but don't bother the driver with it */
3394 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); 3404 params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
3395 3405
3406 /* allow authenticated/associated only if driver handles it */
3407 if (!(rdev->wiphy.features &
3408 NL80211_FEATURE_FULL_AP_CLIENT_STATE) &&
3409 params.sta_flags_mask &
3410 (BIT(NL80211_STA_FLAG_AUTHENTICATED) |
3411 BIT(NL80211_STA_FLAG_ASSOCIATED)))
3412 return -EINVAL;
3413
3396 /* must be last in here for error handling */ 3414 /* must be last in here for error handling */
3397 params.vlan = get_vlan(info, rdev); 3415 params.vlan = get_vlan(info, rdev);
3398 if (IS_ERR(params.vlan)) 3416 if (IS_ERR(params.vlan))
3399 return PTR_ERR(params.vlan); 3417 return PTR_ERR(params.vlan);
3400 break; 3418 break;
3401 case NL80211_IFTYPE_MESH_POINT: 3419 case NL80211_IFTYPE_MESH_POINT:
3420 /* associated is disallowed */
3421 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
3422 return -EINVAL;
3402 /* TDLS peers cannot be added */ 3423 /* TDLS peers cannot be added */
3403 if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) 3424 if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
3404 return -EINVAL; 3425 return -EINVAL;
3405 break; 3426 break;
3406 case NL80211_IFTYPE_STATION: 3427 case NL80211_IFTYPE_STATION:
3428 /* associated is disallowed */
3429 if (params.sta_flags_mask & BIT(NL80211_STA_FLAG_ASSOCIATED))
3430 return -EINVAL;
3407 /* Only TDLS peers can be added */ 3431 /* Only TDLS peers can be added */
3408 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) 3432 if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3409 return -EINVAL; 3433 return -EINVAL;