diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 179 |
1 files changed, 122 insertions, 57 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 47e0aca614b7..661b878bd19c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -164,7 +164,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
164 | sta = sta_info_get(sdata, mac_addr); | 164 | sta = sta_info_get(sdata, mac_addr); |
165 | else | 165 | else |
166 | sta = sta_info_get_bss(sdata, mac_addr); | 166 | sta = sta_info_get_bss(sdata, mac_addr); |
167 | if (!sta) { | 167 | /* |
168 | * The ASSOC test makes sure the driver is ready to | ||
169 | * receive the key. When wpa_supplicant has roamed | ||
170 | * using FT, it attempts to set the key before | ||
171 | * association has completed, this rejects that attempt | ||
172 | * so it will set the key again after assocation. | ||
173 | * | ||
174 | * TODO: accept the key if we have a station entry and | ||
175 | * add it to the device after the station. | ||
176 | */ | ||
177 | if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
168 | ieee80211_key_free(sdata->local, key); | 178 | ieee80211_key_free(sdata->local, key); |
169 | err = -ENOENT; | 179 | err = -ENOENT; |
170 | goto out_unlock; | 180 | goto out_unlock; |
@@ -510,6 +520,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
510 | BIT(NL80211_STA_FLAG_WME) | | 520 | BIT(NL80211_STA_FLAG_WME) | |
511 | BIT(NL80211_STA_FLAG_MFP) | | 521 | BIT(NL80211_STA_FLAG_MFP) | |
512 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 522 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
523 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
513 | BIT(NL80211_STA_FLAG_TDLS_PEER); | 524 | BIT(NL80211_STA_FLAG_TDLS_PEER); |
514 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | 525 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) |
515 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | 526 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); |
@@ -521,6 +532,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
521 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | 532 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); |
522 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | 533 | if (test_sta_flag(sta, WLAN_STA_AUTH)) |
523 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | 534 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); |
535 | if (test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
536 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
524 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 537 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
525 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | 538 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
526 | } | 539 | } |
@@ -930,6 +943,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
930 | 943 | ||
931 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 944 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
932 | sdata->vif.bss_conf.dtim_period = params->dtim_period; | 945 | sdata->vif.bss_conf.dtim_period = params->dtim_period; |
946 | sdata->vif.bss_conf.enable_beacon = true; | ||
933 | 947 | ||
934 | sdata->vif.bss_conf.ssid_len = params->ssid_len; | 948 | sdata->vif.bss_conf.ssid_len = params->ssid_len; |
935 | if (params->ssid_len) | 949 | if (params->ssid_len) |
@@ -1010,8 +1024,15 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1010 | kfree_rcu(old_probe_resp, rcu_head); | 1024 | kfree_rcu(old_probe_resp, rcu_head); |
1011 | 1025 | ||
1012 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | 1026 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) |
1013 | sta_info_flush(local, vlan); | 1027 | sta_info_flush_defer(vlan); |
1014 | sta_info_flush(local, sdata); | 1028 | sta_info_flush_defer(sdata); |
1029 | rcu_barrier(); | ||
1030 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
1031 | sta_info_flush_cleanup(vlan); | ||
1032 | sta_info_flush_cleanup(sdata); | ||
1033 | |||
1034 | sdata->vif.bss_conf.enable_beacon = false; | ||
1035 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | ||
1015 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1036 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1016 | 1037 | ||
1017 | drv_stop_ap(sdata->local, sdata); | 1038 | drv_stop_ap(sdata->local, sdata); |
@@ -1069,6 +1090,58 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
1069 | netif_rx_ni(skb); | 1090 | netif_rx_ni(skb); |
1070 | } | 1091 | } |
1071 | 1092 | ||
1093 | static int sta_apply_auth_flags(struct ieee80211_local *local, | ||
1094 | struct sta_info *sta, | ||
1095 | u32 mask, u32 set) | ||
1096 | { | ||
1097 | int ret; | ||
1098 | |||
1099 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1100 | set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1101 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1102 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1103 | if (ret) | ||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1108 | set & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1109 | !test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
1110 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1111 | if (ret) | ||
1112 | return ret; | ||
1113 | } | ||
1114 | |||
1115 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1116 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1117 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1118 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1119 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1120 | else | ||
1121 | ret = 0; | ||
1122 | if (ret) | ||
1123 | return ret; | ||
1124 | } | ||
1125 | |||
1126 | if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) && | ||
1127 | !(set & BIT(NL80211_STA_FLAG_ASSOCIATED)) && | ||
1128 | test_sta_flag(sta, WLAN_STA_ASSOC)) { | ||
1129 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1130 | if (ret) | ||
1131 | return ret; | ||
1132 | } | ||
1133 | |||
1134 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1135 | !(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
1136 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1137 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); | ||
1138 | if (ret) | ||
1139 | return ret; | ||
1140 | } | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1072 | static int sta_apply_parameters(struct ieee80211_local *local, | 1145 | static int sta_apply_parameters(struct ieee80211_local *local, |
1073 | struct sta_info *sta, | 1146 | struct sta_info *sta, |
1074 | struct station_parameters *params) | 1147 | struct station_parameters *params) |
@@ -1086,52 +1159,20 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1086 | mask = params->sta_flags_mask; | 1159 | mask = params->sta_flags_mask; |
1087 | set = params->sta_flags_set; | 1160 | set = params->sta_flags_set; |
1088 | 1161 | ||
1089 | /* | 1162 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1090 | * In mesh mode, we can clear AUTHENTICATED flag but must | 1163 | /* |
1091 | * also make ASSOCIATED follow appropriately for the driver | 1164 | * In mesh mode, ASSOCIATED isn't part of the nl80211 |
1092 | * API. See also below, after AUTHORIZED changes. | 1165 | * API but must follow AUTHENTICATED for driver state. |
1093 | */ | 1166 | */ |
1094 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | 1167 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1095 | /* cfg80211 should not allow this in non-mesh modes */ | 1168 | mask |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1096 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | 1169 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) |
1097 | return -EINVAL; | 1170 | set |= BIT(NL80211_STA_FLAG_ASSOCIATED); |
1098 | |||
1099 | if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED) && | ||
1100 | !test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1101 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1102 | if (ret) | ||
1103 | return ret; | ||
1104 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1105 | if (ret) | ||
1106 | return ret; | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { | ||
1111 | if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) | ||
1112 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | ||
1113 | else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1114 | ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
1115 | if (ret) | ||
1116 | return ret; | ||
1117 | } | ||
1118 | |||
1119 | if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { | ||
1120 | /* cfg80211 should not allow this in non-mesh modes */ | ||
1121 | if (WARN_ON(!ieee80211_vif_is_mesh(&sdata->vif))) | ||
1122 | return -EINVAL; | ||
1123 | |||
1124 | if (!(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) && | ||
1125 | test_sta_flag(sta, WLAN_STA_AUTH)) { | ||
1126 | ret = sta_info_move_state(sta, IEEE80211_STA_AUTH); | ||
1127 | if (ret) | ||
1128 | return ret; | ||
1129 | ret = sta_info_move_state(sta, IEEE80211_STA_NONE); | ||
1130 | if (ret) | ||
1131 | return ret; | ||
1132 | } | ||
1133 | } | 1171 | } |
1134 | 1172 | ||
1173 | ret = sta_apply_auth_flags(local, sta, mask, set); | ||
1174 | if (ret) | ||
1175 | return ret; | ||
1135 | 1176 | ||
1136 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 1177 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
1137 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 1178 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
@@ -1177,10 +1218,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1177 | sta->sta.aid = params->aid; | 1218 | sta->sta.aid = params->aid; |
1178 | 1219 | ||
1179 | /* | 1220 | /* |
1180 | * FIXME: updating the following information is racy when this | 1221 | * Some of the following updates would be racy if called on an |
1181 | * function is called from ieee80211_change_station(). | 1222 | * existing station, via ieee80211_change_station(). However, |
1182 | * However, all this information should be static so | 1223 | * all such changes are rejected by cfg80211 except for updates |
1183 | * maybe we should just reject attemps to change it. | 1224 | * changing the supported rates on an existing but not yet used |
1225 | * TDLS peer. | ||
1184 | */ | 1226 | */ |
1185 | 1227 | ||
1186 | if (params->listen_interval >= 0) | 1228 | if (params->listen_interval >= 0) |
@@ -1211,18 +1253,33 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1211 | 1253 | ||
1212 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1254 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1213 | #ifdef CONFIG_MAC80211_MESH | 1255 | #ifdef CONFIG_MAC80211_MESH |
1214 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) | 1256 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) { |
1257 | u32 changed = 0; | ||
1258 | |||
1215 | switch (params->plink_state) { | 1259 | switch (params->plink_state) { |
1216 | case NL80211_PLINK_LISTEN: | ||
1217 | case NL80211_PLINK_ESTAB: | 1260 | case NL80211_PLINK_ESTAB: |
1261 | if (sta->plink_state != NL80211_PLINK_ESTAB) | ||
1262 | changed = mesh_plink_inc_estab_count( | ||
1263 | sdata); | ||
1264 | sta->plink_state = params->plink_state; | ||
1265 | break; | ||
1266 | case NL80211_PLINK_LISTEN: | ||
1218 | case NL80211_PLINK_BLOCKED: | 1267 | case NL80211_PLINK_BLOCKED: |
1268 | case NL80211_PLINK_OPN_SNT: | ||
1269 | case NL80211_PLINK_OPN_RCVD: | ||
1270 | case NL80211_PLINK_CNF_RCVD: | ||
1271 | case NL80211_PLINK_HOLDING: | ||
1272 | if (sta->plink_state == NL80211_PLINK_ESTAB) | ||
1273 | changed = mesh_plink_dec_estab_count( | ||
1274 | sdata); | ||
1219 | sta->plink_state = params->plink_state; | 1275 | sta->plink_state = params->plink_state; |
1220 | break; | 1276 | break; |
1221 | default: | 1277 | default: |
1222 | /* nothing */ | 1278 | /* nothing */ |
1223 | break; | 1279 | break; |
1224 | } | 1280 | } |
1225 | else | 1281 | ieee80211_bss_info_change_notify(sdata, changed); |
1282 | } else { | ||
1226 | switch (params->plink_action) { | 1283 | switch (params->plink_action) { |
1227 | case PLINK_ACTION_OPEN: | 1284 | case PLINK_ACTION_OPEN: |
1228 | mesh_plink_open(sta); | 1285 | mesh_plink_open(sta); |
@@ -1231,6 +1288,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1231 | mesh_plink_block(sta); | 1288 | mesh_plink_block(sta); |
1232 | break; | 1289 | break; |
1233 | } | 1290 | } |
1291 | } | ||
1234 | #endif | 1292 | #endif |
1235 | } | 1293 | } |
1236 | 1294 | ||
@@ -1265,6 +1323,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1265 | if (!sta) | 1323 | if (!sta) |
1266 | return -ENOMEM; | 1324 | return -ENOMEM; |
1267 | 1325 | ||
1326 | /* | ||
1327 | * defaults -- if userspace wants something else we'll | ||
1328 | * change it accordingly in sta_apply_parameters() | ||
1329 | */ | ||
1268 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 1330 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
1269 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 1331 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
1270 | 1332 | ||
@@ -1301,7 +1363,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
1301 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1363 | static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
1302 | u8 *mac) | 1364 | u8 *mac) |
1303 | { | 1365 | { |
1304 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1305 | struct ieee80211_sub_if_data *sdata; | 1366 | struct ieee80211_sub_if_data *sdata; |
1306 | 1367 | ||
1307 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1368 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -1309,7 +1370,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1309 | if (mac) | 1370 | if (mac) |
1310 | return sta_info_destroy_addr_bss(sdata, mac); | 1371 | return sta_info_destroy_addr_bss(sdata, mac); |
1311 | 1372 | ||
1312 | sta_info_flush(local, sdata); | 1373 | sta_info_flush(sdata); |
1313 | return 0; | 1374 | return 0; |
1314 | } | 1375 | } |
1315 | 1376 | ||
@@ -1615,6 +1676,9 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1615 | memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, | 1676 | memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate, |
1616 | sizeof(setup->mcast_rate)); | 1677 | sizeof(setup->mcast_rate)); |
1617 | 1678 | ||
1679 | sdata->vif.bss_conf.beacon_int = setup->beacon_interval; | ||
1680 | sdata->vif.bss_conf.dtim_period = setup->dtim_period; | ||
1681 | |||
1618 | return 0; | 1682 | return 0; |
1619 | } | 1683 | } |
1620 | 1684 | ||
@@ -2197,7 +2261,8 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2197 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2261 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2198 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2262 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
2199 | 2263 | ||
2200 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2264 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
2265 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
2201 | return -EOPNOTSUPP; | 2266 | return -EOPNOTSUPP; |
2202 | 2267 | ||
2203 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) | 2268 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) |