diff options
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r-- | net/mac80211/cfg.c | 245 |
1 files changed, 117 insertions, 128 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 58693e52d458..e677b751d468 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -540,9 +540,6 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
540 | 540 | ||
541 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 541 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
542 | 542 | ||
543 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
544 | return -EINVAL; | ||
545 | |||
546 | old = sdata->u.ap.beacon; | 543 | old = sdata->u.ap.beacon; |
547 | 544 | ||
548 | if (old) | 545 | if (old) |
@@ -559,9 +556,6 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
559 | 556 | ||
560 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 557 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
561 | 558 | ||
562 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
563 | return -EINVAL; | ||
564 | |||
565 | old = sdata->u.ap.beacon; | 559 | old = sdata->u.ap.beacon; |
566 | 560 | ||
567 | if (!old) | 561 | if (!old) |
@@ -577,9 +571,6 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
577 | 571 | ||
578 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 572 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
579 | 573 | ||
580 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
581 | return -EINVAL; | ||
582 | |||
583 | old = sdata->u.ap.beacon; | 574 | old = sdata->u.ap.beacon; |
584 | 575 | ||
585 | if (!old) | 576 | if (!old) |
@@ -728,10 +719,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
728 | int err; | 719 | int err; |
729 | int layer2_update; | 720 | int layer2_update; |
730 | 721 | ||
731 | /* Prevent a race with changing the rate control algorithm */ | ||
732 | if (!netif_running(dev)) | ||
733 | return -ENETDOWN; | ||
734 | |||
735 | if (params->vlan) { | 722 | if (params->vlan) { |
736 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 723 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
737 | 724 | ||
@@ -860,14 +847,8 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
860 | struct sta_info *sta; | 847 | struct sta_info *sta; |
861 | int err; | 848 | int err; |
862 | 849 | ||
863 | if (!netif_running(dev)) | ||
864 | return -ENETDOWN; | ||
865 | |||
866 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 850 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
867 | 851 | ||
868 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
869 | return -ENOTSUPP; | ||
870 | |||
871 | rcu_read_lock(); | 852 | rcu_read_lock(); |
872 | sta = sta_info_get(local, next_hop); | 853 | sta = sta_info_get(local, next_hop); |
873 | if (!sta) { | 854 | if (!sta) { |
@@ -913,14 +894,8 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
913 | struct mesh_path *mpath; | 894 | struct mesh_path *mpath; |
914 | struct sta_info *sta; | 895 | struct sta_info *sta; |
915 | 896 | ||
916 | if (!netif_running(dev)) | ||
917 | return -ENETDOWN; | ||
918 | |||
919 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 897 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
920 | 898 | ||
921 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
922 | return -ENOTSUPP; | ||
923 | |||
924 | rcu_read_lock(); | 899 | rcu_read_lock(); |
925 | 900 | ||
926 | sta = sta_info_get(local, next_hop); | 901 | sta = sta_info_get(local, next_hop); |
@@ -989,9 +964,6 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
989 | 964 | ||
990 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 965 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
991 | 966 | ||
992 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
993 | return -ENOTSUPP; | ||
994 | |||
995 | rcu_read_lock(); | 967 | rcu_read_lock(); |
996 | mpath = mesh_path_lookup(dst, sdata); | 968 | mpath = mesh_path_lookup(dst, sdata); |
997 | if (!mpath) { | 969 | if (!mpath) { |
@@ -1013,9 +985,6 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1013 | 985 | ||
1014 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 986 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1015 | 987 | ||
1016 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
1017 | return -ENOTSUPP; | ||
1018 | |||
1019 | rcu_read_lock(); | 988 | rcu_read_lock(); |
1020 | mpath = mesh_path_lookup_by_idx(idx, sdata); | 989 | mpath = mesh_path_lookup_by_idx(idx, sdata); |
1021 | if (!mpath) { | 990 | if (!mpath) { |
@@ -1035,8 +1004,6 @@ static int ieee80211_get_mesh_params(struct wiphy *wiphy, | |||
1035 | struct ieee80211_sub_if_data *sdata; | 1004 | struct ieee80211_sub_if_data *sdata; |
1036 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1005 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1037 | 1006 | ||
1038 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
1039 | return -ENOTSUPP; | ||
1040 | memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); | 1007 | memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config)); |
1041 | return 0; | 1008 | return 0; |
1042 | } | 1009 | } |
@@ -1054,9 +1021,6 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy, | |||
1054 | struct ieee80211_sub_if_data *sdata; | 1021 | struct ieee80211_sub_if_data *sdata; |
1055 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1022 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1056 | 1023 | ||
1057 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) | ||
1058 | return -ENOTSUPP; | ||
1059 | |||
1060 | /* Set the config options which we are interested in setting */ | 1024 | /* Set the config options which we are interested in setting */ |
1061 | conf = &(sdata->u.mesh.mshcfg); | 1025 | conf = &(sdata->u.mesh.mshcfg); |
1062 | if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) | 1026 | if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask)) |
@@ -1104,9 +1068,6 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1104 | 1068 | ||
1105 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1069 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1106 | 1070 | ||
1107 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | if (params->use_cts_prot >= 0) { | 1071 | if (params->use_cts_prot >= 0) { |
1111 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; | 1072 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
1112 | changed |= BSS_CHANGED_ERP_CTS_PROT; | 1073 | changed |= BSS_CHANGED_ERP_CTS_PROT; |
@@ -1181,91 +1142,6 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1181 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1142 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1182 | } | 1143 | } |
1183 | 1144 | ||
1184 | static int set_mgmt_extra_ie_sta(struct ieee80211_sub_if_data *sdata, | ||
1185 | u8 subtype, u8 *ies, size_t ies_len) | ||
1186 | { | ||
1187 | struct ieee80211_local *local = sdata->local; | ||
1188 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1189 | |||
1190 | switch (subtype) { | ||
1191 | case IEEE80211_STYPE_PROBE_REQ >> 4: | ||
1192 | if (local->ops->hw_scan) | ||
1193 | break; | ||
1194 | kfree(ifmgd->ie_probereq); | ||
1195 | ifmgd->ie_probereq = ies; | ||
1196 | ifmgd->ie_probereq_len = ies_len; | ||
1197 | return 0; | ||
1198 | case IEEE80211_STYPE_PROBE_RESP >> 4: | ||
1199 | kfree(ifmgd->ie_proberesp); | ||
1200 | ifmgd->ie_proberesp = ies; | ||
1201 | ifmgd->ie_proberesp_len = ies_len; | ||
1202 | return 0; | ||
1203 | case IEEE80211_STYPE_AUTH >> 4: | ||
1204 | kfree(ifmgd->ie_auth); | ||
1205 | ifmgd->ie_auth = ies; | ||
1206 | ifmgd->ie_auth_len = ies_len; | ||
1207 | return 0; | ||
1208 | case IEEE80211_STYPE_ASSOC_REQ >> 4: | ||
1209 | kfree(ifmgd->ie_assocreq); | ||
1210 | ifmgd->ie_assocreq = ies; | ||
1211 | ifmgd->ie_assocreq_len = ies_len; | ||
1212 | return 0; | ||
1213 | case IEEE80211_STYPE_REASSOC_REQ >> 4: | ||
1214 | kfree(ifmgd->ie_reassocreq); | ||
1215 | ifmgd->ie_reassocreq = ies; | ||
1216 | ifmgd->ie_reassocreq_len = ies_len; | ||
1217 | return 0; | ||
1218 | case IEEE80211_STYPE_DEAUTH >> 4: | ||
1219 | kfree(ifmgd->ie_deauth); | ||
1220 | ifmgd->ie_deauth = ies; | ||
1221 | ifmgd->ie_deauth_len = ies_len; | ||
1222 | return 0; | ||
1223 | case IEEE80211_STYPE_DISASSOC >> 4: | ||
1224 | kfree(ifmgd->ie_disassoc); | ||
1225 | ifmgd->ie_disassoc = ies; | ||
1226 | ifmgd->ie_disassoc_len = ies_len; | ||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | return -EOPNOTSUPP; | ||
1231 | } | ||
1232 | |||
1233 | static int ieee80211_set_mgmt_extra_ie(struct wiphy *wiphy, | ||
1234 | struct net_device *dev, | ||
1235 | struct mgmt_extra_ie_params *params) | ||
1236 | { | ||
1237 | struct ieee80211_sub_if_data *sdata; | ||
1238 | u8 *ies; | ||
1239 | size_t ies_len; | ||
1240 | int ret = -EOPNOTSUPP; | ||
1241 | |||
1242 | if (params->ies) { | ||
1243 | ies = kmemdup(params->ies, params->ies_len, GFP_KERNEL); | ||
1244 | if (ies == NULL) | ||
1245 | return -ENOMEM; | ||
1246 | ies_len = params->ies_len; | ||
1247 | } else { | ||
1248 | ies = NULL; | ||
1249 | ies_len = 0; | ||
1250 | } | ||
1251 | |||
1252 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1253 | |||
1254 | switch (sdata->vif.type) { | ||
1255 | case NL80211_IFTYPE_STATION: | ||
1256 | ret = set_mgmt_extra_ie_sta(sdata, params->subtype, | ||
1257 | ies, ies_len); | ||
1258 | break; | ||
1259 | default: | ||
1260 | ret = -EOPNOTSUPP; | ||
1261 | break; | ||
1262 | } | ||
1263 | |||
1264 | if (ret) | ||
1265 | kfree(ies); | ||
1266 | return ret; | ||
1267 | } | ||
1268 | |||
1269 | #ifdef CONFIG_PM | 1145 | #ifdef CONFIG_PM |
1270 | static int ieee80211_suspend(struct wiphy *wiphy) | 1146 | static int ieee80211_suspend(struct wiphy *wiphy) |
1271 | { | 1147 | { |
@@ -1287,9 +1163,6 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1287 | { | 1163 | { |
1288 | struct ieee80211_sub_if_data *sdata; | 1164 | struct ieee80211_sub_if_data *sdata; |
1289 | 1165 | ||
1290 | if (!netif_running(dev)) | ||
1291 | return -ENETDOWN; | ||
1292 | |||
1293 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1166 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1294 | 1167 | ||
1295 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | 1168 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
@@ -1300,6 +1173,119 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1300 | return ieee80211_request_scan(sdata, req); | 1173 | return ieee80211_request_scan(sdata, req); |
1301 | } | 1174 | } |
1302 | 1175 | ||
1176 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | ||
1177 | struct cfg80211_auth_request *req) | ||
1178 | { | ||
1179 | struct ieee80211_sub_if_data *sdata; | ||
1180 | |||
1181 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1182 | |||
1183 | switch (req->auth_type) { | ||
1184 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
1185 | sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN; | ||
1186 | break; | ||
1187 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
1188 | sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY; | ||
1189 | break; | ||
1190 | case NL80211_AUTHTYPE_FT: | ||
1191 | sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT; | ||
1192 | break; | ||
1193 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
1194 | sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP; | ||
1195 | break; | ||
1196 | default: | ||
1197 | return -EOPNOTSUPP; | ||
1198 | } | ||
1199 | |||
1200 | memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN); | ||
1201 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | ||
1202 | sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET; | ||
1203 | |||
1204 | /* TODO: req->chan */ | ||
1205 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
1206 | |||
1207 | if (req->ssid) { | ||
1208 | sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET; | ||
1209 | memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len); | ||
1210 | sdata->u.mgd.ssid_len = req->ssid_len; | ||
1211 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | ||
1212 | } | ||
1213 | |||
1214 | kfree(sdata->u.mgd.sme_auth_ie); | ||
1215 | sdata->u.mgd.sme_auth_ie = NULL; | ||
1216 | sdata->u.mgd.sme_auth_ie_len = 0; | ||
1217 | if (req->ie) { | ||
1218 | sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL); | ||
1219 | if (sdata->u.mgd.sme_auth_ie == NULL) | ||
1220 | return -ENOMEM; | ||
1221 | memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len); | ||
1222 | sdata->u.mgd.sme_auth_ie_len = req->ie_len; | ||
1223 | } | ||
1224 | |||
1225 | sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; | ||
1226 | sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE; | ||
1227 | ieee80211_sta_req_auth(sdata); | ||
1228 | return 0; | ||
1229 | } | ||
1230 | |||
1231 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, | ||
1232 | struct cfg80211_assoc_request *req) | ||
1233 | { | ||
1234 | struct ieee80211_sub_if_data *sdata; | ||
1235 | int ret; | ||
1236 | |||
1237 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1238 | |||
1239 | if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 || | ||
1240 | !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED)) | ||
1241 | return -ENOLINK; /* not authenticated */ | ||
1242 | |||
1243 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | ||
1244 | sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET; | ||
1245 | |||
1246 | /* TODO: req->chan */ | ||
1247 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
1248 | |||
1249 | if (req->ssid) { | ||
1250 | sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET; | ||
1251 | memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len); | ||
1252 | sdata->u.mgd.ssid_len = req->ssid_len; | ||
1253 | sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | ||
1254 | } else | ||
1255 | sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL; | ||
1256 | |||
1257 | ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len); | ||
1258 | if (ret) | ||
1259 | return ret; | ||
1260 | |||
1261 | sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME; | ||
1262 | sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE; | ||
1263 | ieee80211_sta_req_auth(sdata); | ||
1264 | return 0; | ||
1265 | } | ||
1266 | |||
1267 | static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, | ||
1268 | struct cfg80211_deauth_request *req) | ||
1269 | { | ||
1270 | struct ieee80211_sub_if_data *sdata; | ||
1271 | |||
1272 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1273 | |||
1274 | /* TODO: req->ie */ | ||
1275 | return ieee80211_sta_deauthenticate(sdata, req->reason_code); | ||
1276 | } | ||
1277 | |||
1278 | static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, | ||
1279 | struct cfg80211_disassoc_request *req) | ||
1280 | { | ||
1281 | struct ieee80211_sub_if_data *sdata; | ||
1282 | |||
1283 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1284 | |||
1285 | /* TODO: req->ie */ | ||
1286 | return ieee80211_sta_disassociate(sdata, req->reason_code); | ||
1287 | } | ||
1288 | |||
1303 | struct cfg80211_ops mac80211_config_ops = { | 1289 | struct cfg80211_ops mac80211_config_ops = { |
1304 | .add_virtual_intf = ieee80211_add_iface, | 1290 | .add_virtual_intf = ieee80211_add_iface, |
1305 | .del_virtual_intf = ieee80211_del_iface, | 1291 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1329,8 +1315,11 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1329 | .change_bss = ieee80211_change_bss, | 1315 | .change_bss = ieee80211_change_bss, |
1330 | .set_txq_params = ieee80211_set_txq_params, | 1316 | .set_txq_params = ieee80211_set_txq_params, |
1331 | .set_channel = ieee80211_set_channel, | 1317 | .set_channel = ieee80211_set_channel, |
1332 | .set_mgmt_extra_ie = ieee80211_set_mgmt_extra_ie, | ||
1333 | .suspend = ieee80211_suspend, | 1318 | .suspend = ieee80211_suspend, |
1334 | .resume = ieee80211_resume, | 1319 | .resume = ieee80211_resume, |
1335 | .scan = ieee80211_scan, | 1320 | .scan = ieee80211_scan, |
1321 | .auth = ieee80211_auth, | ||
1322 | .assoc = ieee80211_assoc, | ||
1323 | .deauth = ieee80211_deauth, | ||
1324 | .disassoc = ieee80211_disassoc, | ||
1336 | }; | 1325 | }; |