diff options
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 209 |
1 files changed, 146 insertions, 63 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index e5872ff2c27c..728f1c0dc70d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -476,7 +476,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
476 | EXPORT_SYMBOL(ieee80211_data_to_8023); | 476 | EXPORT_SYMBOL(ieee80211_data_to_8023); |
477 | 477 | ||
478 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | 478 | int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, |
479 | enum nl80211_iftype iftype, u8 *bssid, bool qos) | 479 | enum nl80211_iftype iftype, |
480 | const u8 *bssid, bool qos) | ||
480 | { | 481 | { |
481 | struct ieee80211_hdr hdr; | 482 | struct ieee80211_hdr hdr; |
482 | u16 hdrlen, ethertype; | 483 | u16 hdrlen, ethertype; |
@@ -770,7 +771,7 @@ EXPORT_SYMBOL(ieee80211_bss_get_ie); | |||
770 | 771 | ||
771 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | 772 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev) |
772 | { | 773 | { |
773 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 774 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
774 | struct net_device *dev = wdev->netdev; | 775 | struct net_device *dev = wdev->netdev; |
775 | int i; | 776 | int i; |
776 | 777 | ||
@@ -839,6 +840,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) | |||
839 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, | 840 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, |
840 | ev->ij.channel); | 841 | ev->ij.channel); |
841 | break; | 842 | break; |
843 | case EVENT_STOPPED: | ||
844 | __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev); | ||
845 | break; | ||
842 | } | 846 | } |
843 | wdev_unlock(wdev); | 847 | wdev_unlock(wdev); |
844 | 848 | ||
@@ -888,11 +892,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
888 | return -EBUSY; | 892 | return -EBUSY; |
889 | 893 | ||
890 | if (ntype != otype && netif_running(dev)) { | 894 | if (ntype != otype && netif_running(dev)) { |
891 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, | ||
892 | ntype); | ||
893 | if (err) | ||
894 | return err; | ||
895 | |||
896 | dev->ieee80211_ptr->use_4addr = false; | 895 | dev->ieee80211_ptr->use_4addr = false; |
897 | dev->ieee80211_ptr->mesh_id_up_len = 0; | 896 | dev->ieee80211_ptr->mesh_id_up_len = 0; |
898 | wdev_lock(dev->ieee80211_ptr); | 897 | wdev_lock(dev->ieee80211_ptr); |
@@ -1268,6 +1267,120 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | |||
1268 | return res; | 1267 | return res; |
1269 | } | 1268 | } |
1270 | 1269 | ||
1270 | int cfg80211_iter_combinations(struct wiphy *wiphy, | ||
1271 | const int num_different_channels, | ||
1272 | const u8 radar_detect, | ||
1273 | const int iftype_num[NUM_NL80211_IFTYPES], | ||
1274 | void (*iter)(const struct ieee80211_iface_combination *c, | ||
1275 | void *data), | ||
1276 | void *data) | ||
1277 | { | ||
1278 | const struct ieee80211_regdomain *regdom; | ||
1279 | enum nl80211_dfs_regions region = 0; | ||
1280 | int i, j, iftype; | ||
1281 | int num_interfaces = 0; | ||
1282 | u32 used_iftypes = 0; | ||
1283 | |||
1284 | if (radar_detect) { | ||
1285 | rcu_read_lock(); | ||
1286 | regdom = rcu_dereference(cfg80211_regdomain); | ||
1287 | if (regdom) | ||
1288 | region = regdom->dfs_region; | ||
1289 | rcu_read_unlock(); | ||
1290 | } | ||
1291 | |||
1292 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | ||
1293 | num_interfaces += iftype_num[iftype]; | ||
1294 | if (iftype_num[iftype] > 0 && | ||
1295 | !(wiphy->software_iftypes & BIT(iftype))) | ||
1296 | used_iftypes |= BIT(iftype); | ||
1297 | } | ||
1298 | |||
1299 | for (i = 0; i < wiphy->n_iface_combinations; i++) { | ||
1300 | const struct ieee80211_iface_combination *c; | ||
1301 | struct ieee80211_iface_limit *limits; | ||
1302 | u32 all_iftypes = 0; | ||
1303 | |||
1304 | c = &wiphy->iface_combinations[i]; | ||
1305 | |||
1306 | if (num_interfaces > c->max_interfaces) | ||
1307 | continue; | ||
1308 | if (num_different_channels > c->num_different_channels) | ||
1309 | continue; | ||
1310 | |||
1311 | limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, | ||
1312 | GFP_KERNEL); | ||
1313 | if (!limits) | ||
1314 | return -ENOMEM; | ||
1315 | |||
1316 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | ||
1317 | if (wiphy->software_iftypes & BIT(iftype)) | ||
1318 | continue; | ||
1319 | for (j = 0; j < c->n_limits; j++) { | ||
1320 | all_iftypes |= limits[j].types; | ||
1321 | if (!(limits[j].types & BIT(iftype))) | ||
1322 | continue; | ||
1323 | if (limits[j].max < iftype_num[iftype]) | ||
1324 | goto cont; | ||
1325 | limits[j].max -= iftype_num[iftype]; | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | if (radar_detect != (c->radar_detect_widths & radar_detect)) | ||
1330 | goto cont; | ||
1331 | |||
1332 | if (radar_detect && c->radar_detect_regions && | ||
1333 | !(c->radar_detect_regions & BIT(region))) | ||
1334 | goto cont; | ||
1335 | |||
1336 | /* Finally check that all iftypes that we're currently | ||
1337 | * using are actually part of this combination. If they | ||
1338 | * aren't then we can't use this combination and have | ||
1339 | * to continue to the next. | ||
1340 | */ | ||
1341 | if ((all_iftypes & used_iftypes) != used_iftypes) | ||
1342 | goto cont; | ||
1343 | |||
1344 | /* This combination covered all interface types and | ||
1345 | * supported the requested numbers, so we're good. | ||
1346 | */ | ||
1347 | |||
1348 | (*iter)(c, data); | ||
1349 | cont: | ||
1350 | kfree(limits); | ||
1351 | } | ||
1352 | |||
1353 | return 0; | ||
1354 | } | ||
1355 | EXPORT_SYMBOL(cfg80211_iter_combinations); | ||
1356 | |||
1357 | static void | ||
1358 | cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c, | ||
1359 | void *data) | ||
1360 | { | ||
1361 | int *num = data; | ||
1362 | (*num)++; | ||
1363 | } | ||
1364 | |||
1365 | int cfg80211_check_combinations(struct wiphy *wiphy, | ||
1366 | const int num_different_channels, | ||
1367 | const u8 radar_detect, | ||
1368 | const int iftype_num[NUM_NL80211_IFTYPES]) | ||
1369 | { | ||
1370 | int err, num = 0; | ||
1371 | |||
1372 | err = cfg80211_iter_combinations(wiphy, num_different_channels, | ||
1373 | radar_detect, iftype_num, | ||
1374 | cfg80211_iter_sum_ifcombs, &num); | ||
1375 | if (err) | ||
1376 | return err; | ||
1377 | if (num == 0) | ||
1378 | return -EBUSY; | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | EXPORT_SYMBOL(cfg80211_check_combinations); | ||
1383 | |||
1271 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | 1384 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, |
1272 | struct wireless_dev *wdev, | 1385 | struct wireless_dev *wdev, |
1273 | enum nl80211_iftype iftype, | 1386 | enum nl80211_iftype iftype, |
@@ -1276,7 +1389,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1276 | u8 radar_detect) | 1389 | u8 radar_detect) |
1277 | { | 1390 | { |
1278 | struct wireless_dev *wdev_iter; | 1391 | struct wireless_dev *wdev_iter; |
1279 | u32 used_iftypes = BIT(iftype); | ||
1280 | int num[NUM_NL80211_IFTYPES]; | 1392 | int num[NUM_NL80211_IFTYPES]; |
1281 | struct ieee80211_channel | 1393 | struct ieee80211_channel |
1282 | *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS]; | 1394 | *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS]; |
@@ -1284,7 +1396,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1284 | enum cfg80211_chan_mode chmode; | 1396 | enum cfg80211_chan_mode chmode; |
1285 | int num_different_channels = 0; | 1397 | int num_different_channels = 0; |
1286 | int total = 1; | 1398 | int total = 1; |
1287 | int i, j; | 1399 | int i; |
1288 | 1400 | ||
1289 | ASSERT_RTNL(); | 1401 | ASSERT_RTNL(); |
1290 | 1402 | ||
@@ -1306,6 +1418,11 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1306 | 1418 | ||
1307 | num[iftype] = 1; | 1419 | num[iftype] = 1; |
1308 | 1420 | ||
1421 | /* TODO: We'll probably not need this anymore, since this | ||
1422 | * should only be called with CHAN_MODE_UNDEFINED. There are | ||
1423 | * still a couple of pending calls where other chanmodes are | ||
1424 | * used, but we should get rid of them. | ||
1425 | */ | ||
1309 | switch (chanmode) { | 1426 | switch (chanmode) { |
1310 | case CHAN_MODE_UNDEFINED: | 1427 | case CHAN_MODE_UNDEFINED: |
1311 | break; | 1428 | break; |
@@ -1369,65 +1486,13 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1369 | 1486 | ||
1370 | num[wdev_iter->iftype]++; | 1487 | num[wdev_iter->iftype]++; |
1371 | total++; | 1488 | total++; |
1372 | used_iftypes |= BIT(wdev_iter->iftype); | ||
1373 | } | 1489 | } |
1374 | 1490 | ||
1375 | if (total == 1 && !radar_detect) | 1491 | if (total == 1 && !radar_detect) |
1376 | return 0; | 1492 | return 0; |
1377 | 1493 | ||
1378 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | 1494 | return cfg80211_check_combinations(&rdev->wiphy, num_different_channels, |
1379 | const struct ieee80211_iface_combination *c; | 1495 | radar_detect, num); |
1380 | struct ieee80211_iface_limit *limits; | ||
1381 | u32 all_iftypes = 0; | ||
1382 | |||
1383 | c = &rdev->wiphy.iface_combinations[i]; | ||
1384 | |||
1385 | if (total > c->max_interfaces) | ||
1386 | continue; | ||
1387 | if (num_different_channels > c->num_different_channels) | ||
1388 | continue; | ||
1389 | |||
1390 | limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, | ||
1391 | GFP_KERNEL); | ||
1392 | if (!limits) | ||
1393 | return -ENOMEM; | ||
1394 | |||
1395 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | ||
1396 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | ||
1397 | continue; | ||
1398 | for (j = 0; j < c->n_limits; j++) { | ||
1399 | all_iftypes |= limits[j].types; | ||
1400 | if (!(limits[j].types & BIT(iftype))) | ||
1401 | continue; | ||
1402 | if (limits[j].max < num[iftype]) | ||
1403 | goto cont; | ||
1404 | limits[j].max -= num[iftype]; | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | if (radar_detect && !(c->radar_detect_widths & radar_detect)) | ||
1409 | goto cont; | ||
1410 | |||
1411 | /* | ||
1412 | * Finally check that all iftypes that we're currently | ||
1413 | * using are actually part of this combination. If they | ||
1414 | * aren't then we can't use this combination and have | ||
1415 | * to continue to the next. | ||
1416 | */ | ||
1417 | if ((all_iftypes & used_iftypes) != used_iftypes) | ||
1418 | goto cont; | ||
1419 | |||
1420 | /* | ||
1421 | * This combination covered all interface types and | ||
1422 | * supported the requested numbers, so we're good. | ||
1423 | */ | ||
1424 | kfree(limits); | ||
1425 | return 0; | ||
1426 | cont: | ||
1427 | kfree(limits); | ||
1428 | } | ||
1429 | |||
1430 | return -EBUSY; | ||
1431 | } | 1496 | } |
1432 | 1497 | ||
1433 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, | 1498 | int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, |
@@ -1481,6 +1546,24 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy) | |||
1481 | } | 1546 | } |
1482 | EXPORT_SYMBOL(ieee80211_get_num_supported_channels); | 1547 | EXPORT_SYMBOL(ieee80211_get_num_supported_channels); |
1483 | 1548 | ||
1549 | int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, | ||
1550 | struct station_info *sinfo) | ||
1551 | { | ||
1552 | struct cfg80211_registered_device *rdev; | ||
1553 | struct wireless_dev *wdev; | ||
1554 | |||
1555 | wdev = dev->ieee80211_ptr; | ||
1556 | if (!wdev) | ||
1557 | return -EOPNOTSUPP; | ||
1558 | |||
1559 | rdev = wiphy_to_rdev(wdev->wiphy); | ||
1560 | if (!rdev->ops->get_station) | ||
1561 | return -EOPNOTSUPP; | ||
1562 | |||
1563 | return rdev_get_station(rdev, dev, mac_addr, sinfo); | ||
1564 | } | ||
1565 | EXPORT_SYMBOL(cfg80211_get_station); | ||
1566 | |||
1484 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ | 1567 | /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ |
1485 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ | 1568 | /* Ethernet-II snap header (RFC1042 for most EtherTypes) */ |
1486 | const unsigned char rfc1042_header[] __aligned(2) = | 1569 | const unsigned char rfc1042_header[] __aligned(2) = |