aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c216
1 files changed, 105 insertions, 111 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3f47276caeb8..52928ad90570 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -74,19 +74,14 @@ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
74 return 0; 74 return 0;
75} 75}
76 76
77static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, 77static int ieee80211_change_iface(struct wiphy *wiphy,
78 struct net_device *dev,
78 enum nl80211_iftype type, u32 *flags, 79 enum nl80211_iftype type, u32 *flags,
79 struct vif_params *params) 80 struct vif_params *params)
80{ 81{
81 struct net_device *dev;
82 struct ieee80211_sub_if_data *sdata; 82 struct ieee80211_sub_if_data *sdata;
83 int ret; 83 int ret;
84 84
85 /* we're under RTNL */
86 dev = __dev_get_by_index(&init_net, ifindex);
87 if (!dev)
88 return -ENODEV;
89
90 if (!nl80211_type_check(type)) 85 if (!nl80211_type_check(type))
91 return -EINVAL; 86 return -EINVAL;
92 87
@@ -1177,123 +1172,29 @@ static int ieee80211_scan(struct wiphy *wiphy,
1177static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, 1172static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
1178 struct cfg80211_auth_request *req) 1173 struct cfg80211_auth_request *req)
1179{ 1174{
1180 struct ieee80211_sub_if_data *sdata; 1175 return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req);
1181
1182 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1183
1184 switch (req->auth_type) {
1185 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1186 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_OPEN;
1187 break;
1188 case NL80211_AUTHTYPE_SHARED_KEY:
1189 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_SHARED_KEY;
1190 break;
1191 case NL80211_AUTHTYPE_FT:
1192 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_FT;
1193 break;
1194 case NL80211_AUTHTYPE_NETWORK_EAP:
1195 sdata->u.mgd.auth_algs = IEEE80211_AUTH_ALG_LEAP;
1196 break;
1197 default:
1198 return -EOPNOTSUPP;
1199 }
1200
1201 memcpy(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN);
1202 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1203 sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1204
1205 /* TODO: req->chan */
1206 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1207
1208 if (req->ssid) {
1209 sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1210 memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1211 sdata->u.mgd.ssid_len = req->ssid_len;
1212 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1213 }
1214
1215 kfree(sdata->u.mgd.sme_auth_ie);
1216 sdata->u.mgd.sme_auth_ie = NULL;
1217 sdata->u.mgd.sme_auth_ie_len = 0;
1218 if (req->ie) {
1219 sdata->u.mgd.sme_auth_ie = kmalloc(req->ie_len, GFP_KERNEL);
1220 if (sdata->u.mgd.sme_auth_ie == NULL)
1221 return -ENOMEM;
1222 memcpy(sdata->u.mgd.sme_auth_ie, req->ie, req->ie_len);
1223 sdata->u.mgd.sme_auth_ie_len = req->ie_len;
1224 }
1225
1226 sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1227 sdata->u.mgd.state = IEEE80211_STA_MLME_DIRECT_PROBE;
1228 ieee80211_sta_req_auth(sdata);
1229 return 0;
1230} 1176}
1231 1177
1232static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, 1178static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
1233 struct cfg80211_assoc_request *req) 1179 struct cfg80211_assoc_request *req)
1234{ 1180{
1235 struct ieee80211_sub_if_data *sdata; 1181 return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
1236 int ret;
1237
1238 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1239
1240 if (memcmp(sdata->u.mgd.bssid, req->peer_addr, ETH_ALEN) != 0 ||
1241 !(sdata->u.mgd.flags & IEEE80211_STA_AUTHENTICATED))
1242 return -ENOLINK; /* not authenticated */
1243
1244 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
1245 sdata->u.mgd.flags |= IEEE80211_STA_BSSID_SET;
1246
1247 /* TODO: req->chan */
1248 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_CHANNEL_SEL;
1249
1250 if (req->ssid) {
1251 sdata->u.mgd.flags |= IEEE80211_STA_SSID_SET;
1252 memcpy(sdata->u.mgd.ssid, req->ssid, req->ssid_len);
1253 sdata->u.mgd.ssid_len = req->ssid_len;
1254 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_SSID_SEL;
1255 } else
1256 sdata->u.mgd.flags |= IEEE80211_STA_AUTO_SSID_SEL;
1257
1258 ret = ieee80211_sta_set_extra_ie(sdata, req->ie, req->ie_len);
1259 if (ret && ret != -EALREADY)
1260 return ret;
1261
1262 if (req->use_mfp) {
1263 sdata->u.mgd.mfp = IEEE80211_MFP_REQUIRED;
1264 sdata->u.mgd.flags |= IEEE80211_STA_MFP_ENABLED;
1265 } else {
1266 sdata->u.mgd.mfp = IEEE80211_MFP_DISABLED;
1267 sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
1268 }
1269
1270 if (req->control_port)
1271 sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
1272 else
1273 sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
1274
1275 sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
1276 sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
1277 ieee80211_sta_req_auth(sdata);
1278 return 0;
1279} 1182}
1280 1183
1281static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev, 1184static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
1282 struct cfg80211_deauth_request *req) 1185 struct cfg80211_deauth_request *req,
1186 void *cookie)
1283{ 1187{
1284 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1188 return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev),
1285 1189 req, cookie);
1286 /* TODO: req->ie, req->peer_addr */
1287 return ieee80211_sta_deauthenticate(sdata, req->reason_code);
1288} 1190}
1289 1191
1290static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, 1192static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
1291 struct cfg80211_disassoc_request *req) 1193 struct cfg80211_disassoc_request *req,
1194 void *cookie)
1292{ 1195{
1293 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1196 return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev),
1294 1197 req, cookie);
1295 /* TODO: req->ie, req->peer_addr */
1296 return ieee80211_sta_disassociate(sdata, req->reason_code);
1297} 1198}
1298 1199
1299static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, 1200static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
@@ -1374,6 +1275,16 @@ static int ieee80211_get_tx_power(struct wiphy *wiphy, int *dbm)
1374 return 0; 1275 return 0;
1375} 1276}
1376 1277
1278static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
1279 u8 *addr)
1280{
1281 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1282
1283 memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);
1284
1285 return 0;
1286}
1287
1377static void ieee80211_rfkill_poll(struct wiphy *wiphy) 1288static void ieee80211_rfkill_poll(struct wiphy *wiphy)
1378{ 1289{
1379 struct ieee80211_local *local = wiphy_priv(wiphy); 1290 struct ieee80211_local *local = wiphy_priv(wiphy);
@@ -1381,6 +1292,85 @@ static void ieee80211_rfkill_poll(struct wiphy *wiphy)
1381 drv_rfkill_poll(local); 1292 drv_rfkill_poll(local);
1382} 1293}
1383 1294
1295#ifdef CONFIG_NL80211_TESTMODE
1296static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
1297{
1298 struct ieee80211_local *local = wiphy_priv(wiphy);
1299
1300 if (!local->ops->testmode_cmd)
1301 return -EOPNOTSUPP;
1302
1303 return local->ops->testmode_cmd(&local->hw, data, len);
1304}
1305#endif
1306
1307static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1308 bool enabled, int timeout)
1309{
1310 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1311 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1312 struct ieee80211_conf *conf = &local->hw.conf;
1313
1314 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
1315 return -EOPNOTSUPP;
1316
1317 if (enabled == sdata->u.mgd.powersave &&
1318 timeout == conf->dynamic_ps_timeout)
1319 return 0;
1320
1321 sdata->u.mgd.powersave = enabled;
1322 conf->dynamic_ps_timeout = timeout;
1323
1324 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
1325 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
1326
1327 ieee80211_recalc_ps(local, -1);
1328
1329 return 0;
1330}
1331
1332static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
1333 struct net_device *dev,
1334 const u8 *addr,
1335 const struct cfg80211_bitrate_mask *mask)
1336{
1337 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1338 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1339 int i, err = -EINVAL;
1340 u32 target_rate;
1341 struct ieee80211_supported_band *sband;
1342
1343 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1344
1345 /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
1346 * target_rate = X, rate->fixed = 1 means only rate X
1347 * target_rate = X, rate->fixed = 0 means all rates <= X */
1348 sdata->max_ratectrl_rateidx = -1;
1349 sdata->force_unicast_rateidx = -1;
1350
1351 if (mask->fixed)
1352 target_rate = mask->fixed / 100;
1353 else if (mask->maxrate)
1354 target_rate = mask->maxrate / 100;
1355 else
1356 return 0;
1357
1358 for (i=0; i< sband->n_bitrates; i++) {
1359 struct ieee80211_rate *brate = &sband->bitrates[i];
1360 int this_rate = brate->bitrate;
1361
1362 if (target_rate == this_rate) {
1363 sdata->max_ratectrl_rateidx = i;
1364 if (mask->fixed)
1365 sdata->force_unicast_rateidx = i;
1366 err = 0;
1367 break;
1368 }
1369 }
1370
1371 return err;
1372}
1373
1384struct cfg80211_ops mac80211_config_ops = { 1374struct cfg80211_ops mac80211_config_ops = {
1385 .add_virtual_intf = ieee80211_add_iface, 1375 .add_virtual_intf = ieee80211_add_iface,
1386 .del_virtual_intf = ieee80211_del_iface, 1376 .del_virtual_intf = ieee80211_del_iface,
@@ -1422,5 +1412,9 @@ struct cfg80211_ops mac80211_config_ops = {
1422 .set_wiphy_params = ieee80211_set_wiphy_params, 1412 .set_wiphy_params = ieee80211_set_wiphy_params,
1423 .set_tx_power = ieee80211_set_tx_power, 1413 .set_tx_power = ieee80211_set_tx_power,
1424 .get_tx_power = ieee80211_get_tx_power, 1414 .get_tx_power = ieee80211_get_tx_power,
1415 .set_wds_peer = ieee80211_set_wds_peer,
1425 .rfkill_poll = ieee80211_rfkill_poll, 1416 .rfkill_poll = ieee80211_rfkill_poll,
1417 CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
1418 .set_power_mgmt = ieee80211_set_power_mgmt,
1419 .set_bitrate_mask = ieee80211_set_bitrate_mask,
1426}; 1420};