aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext-compat.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r--net/wireless/wext-compat.c148
1 files changed, 122 insertions, 26 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 561a45cf2a6a..a60a2773b497 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -12,6 +12,7 @@
12#include <linux/nl80211.h> 12#include <linux/nl80211.h>
13#include <linux/if_arp.h> 13#include <linux/if_arp.h>
14#include <linux/etherdevice.h> 14#include <linux/etherdevice.h>
15#include <linux/slab.h>
15#include <net/iw_handler.h> 16#include <net/iw_handler.h>
16#include <net/cfg80211.h> 17#include <net/cfg80211.h>
17#include "wext-compat.h" 18#include "wext-compat.h"
@@ -437,6 +438,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
437{ 438{
438 struct wireless_dev *wdev = dev->ieee80211_ptr; 439 struct wireless_dev *wdev = dev->ieee80211_ptr;
439 int err, i; 440 int err, i;
441 bool rejoin = false;
440 442
441 if (!wdev->wext.keys) { 443 if (!wdev->wext.keys) {
442 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), 444 wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys),
@@ -466,8 +468,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
466 468
467 if (remove) { 469 if (remove) {
468 err = 0; 470 err = 0;
469 if (wdev->current_bss) 471 if (wdev->current_bss) {
472 /*
473 * If removing the current TX key, we will need to
474 * join a new IBSS without the privacy bit clear.
475 */
476 if (idx == wdev->wext.default_key &&
477 wdev->iftype == NL80211_IFTYPE_ADHOC) {
478 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
479 rejoin = true;
480 }
470 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); 481 err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr);
482 }
483 wdev->wext.connect.privacy = false;
484 /*
485 * Applications using wireless extensions expect to be
486 * able to delete keys that don't exist, so allow that.
487 */
488 if (err == -ENOENT)
489 err = 0;
471 if (!err) { 490 if (!err) {
472 if (!addr) { 491 if (!addr) {
473 wdev->wext.keys->params[idx].key_len = 0; 492 wdev->wext.keys->params[idx].key_len = 0;
@@ -478,12 +497,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
478 else if (idx == wdev->wext.default_mgmt_key) 497 else if (idx == wdev->wext.default_mgmt_key)
479 wdev->wext.default_mgmt_key = -1; 498 wdev->wext.default_mgmt_key = -1;
480 } 499 }
481 /* 500
482 * Applications using wireless extensions expect to be 501 if (!err && rejoin)
483 * able to delete keys that don't exist, so allow that. 502 err = cfg80211_ibss_wext_join(rdev, wdev);
484 */
485 if (err == -ENOENT)
486 return 0;
487 503
488 return err; 504 return err;
489 } 505 }
@@ -511,11 +527,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
511 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || 527 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
512 params->cipher == WLAN_CIPHER_SUITE_WEP104) && 528 params->cipher == WLAN_CIPHER_SUITE_WEP104) &&
513 (tx_key || (!addr && wdev->wext.default_key == -1))) { 529 (tx_key || (!addr && wdev->wext.default_key == -1))) {
514 if (wdev->current_bss) 530 if (wdev->current_bss) {
531 /*
532 * If we are getting a new TX key from not having
533 * had one before we need to join a new IBSS with
534 * the privacy bit set.
535 */
536 if (wdev->iftype == NL80211_IFTYPE_ADHOC &&
537 wdev->wext.default_key == -1) {
538 __cfg80211_leave_ibss(rdev, wdev->netdev, true);
539 rejoin = true;
540 }
515 err = rdev->ops->set_default_key(&rdev->wiphy, 541 err = rdev->ops->set_default_key(&rdev->wiphy,
516 dev, idx); 542 dev, idx);
517 if (!err) 543 }
544 if (!err) {
518 wdev->wext.default_key = idx; 545 wdev->wext.default_key = idx;
546 if (rejoin)
547 err = cfg80211_ibss_wext_join(rdev, wdev);
548 }
519 return err; 549 return err;
520 } 550 }
521 551
@@ -539,10 +569,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
539{ 569{
540 int err; 570 int err;
541 571
572 /* devlist mutex needed for possible IBSS re-join */
573 mutex_lock(&rdev->devlist_mtx);
542 wdev_lock(dev->ieee80211_ptr); 574 wdev_lock(dev->ieee80211_ptr);
543 err = __cfg80211_set_encryption(rdev, dev, addr, remove, 575 err = __cfg80211_set_encryption(rdev, dev, addr, remove,
544 tx_key, idx, params); 576 tx_key, idx, params);
545 wdev_unlock(dev->ieee80211_ptr); 577 wdev_unlock(dev->ieee80211_ptr);
578 mutex_unlock(&rdev->devlist_mtx);
546 579
547 return err; 580 return err;
548} 581}
@@ -904,8 +937,6 @@ static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
904 937
905static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) 938static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
906{ 939{
907 wdev->wext.connect.crypto.wpa_versions = 0;
908
909 if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | 940 if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
910 IW_AUTH_WPA_VERSION_WPA2| 941 IW_AUTH_WPA_VERSION_WPA2|
911 IW_AUTH_WPA_VERSION_DISABLED)) 942 IW_AUTH_WPA_VERSION_DISABLED))
@@ -933,8 +964,6 @@ static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
933 964
934static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) 965static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
935{ 966{
936 wdev->wext.connect.crypto.cipher_group = 0;
937
938 if (cipher & IW_AUTH_CIPHER_WEP40) 967 if (cipher & IW_AUTH_CIPHER_WEP40)
939 wdev->wext.connect.crypto.cipher_group = 968 wdev->wext.connect.crypto.cipher_group =
940 WLAN_CIPHER_SUITE_WEP40; 969 WLAN_CIPHER_SUITE_WEP40;
@@ -950,6 +979,8 @@ static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
950 else if (cipher & IW_AUTH_CIPHER_AES_CMAC) 979 else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
951 wdev->wext.connect.crypto.cipher_group = 980 wdev->wext.connect.crypto.cipher_group =
952 WLAN_CIPHER_SUITE_AES_CMAC; 981 WLAN_CIPHER_SUITE_AES_CMAC;
982 else if (cipher & IW_AUTH_CIPHER_NONE)
983 wdev->wext.connect.crypto.cipher_group = 0;
953 else 984 else
954 return -EINVAL; 985 return -EINVAL;
955 986
@@ -1069,8 +1100,8 @@ int cfg80211_wext_siwpower(struct net_device *dev,
1069{ 1100{
1070 struct wireless_dev *wdev = dev->ieee80211_ptr; 1101 struct wireless_dev *wdev = dev->ieee80211_ptr;
1071 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 1102 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1072 bool ps = wdev->wext.ps; 1103 bool ps = wdev->ps;
1073 int timeout = wdev->wext.ps_timeout; 1104 int timeout = wdev->ps_timeout;
1074 int err; 1105 int err;
1075 1106
1076 if (wdev->iftype != NL80211_IFTYPE_STATION) 1107 if (wdev->iftype != NL80211_IFTYPE_STATION)
@@ -1103,8 +1134,8 @@ int cfg80211_wext_siwpower(struct net_device *dev,
1103 if (err) 1134 if (err)
1104 return err; 1135 return err;
1105 1136
1106 wdev->wext.ps = ps; 1137 wdev->ps = ps;
1107 wdev->wext.ps_timeout = timeout; 1138 wdev->ps_timeout = timeout;
1108 1139
1109 return 0; 1140 return 0;
1110 1141
@@ -1117,7 +1148,7 @@ int cfg80211_wext_giwpower(struct net_device *dev,
1117{ 1148{
1118 struct wireless_dev *wdev = dev->ieee80211_ptr; 1149 struct wireless_dev *wdev = dev->ieee80211_ptr;
1119 1150
1120 wrq->disabled = !wdev->wext.ps; 1151 wrq->disabled = !wdev->ps;
1121 1152
1122 return 0; 1153 return 0;
1123} 1154}
@@ -1174,21 +1205,47 @@ int cfg80211_wext_siwrate(struct net_device *dev,
1174 struct wireless_dev *wdev = dev->ieee80211_ptr; 1205 struct wireless_dev *wdev = dev->ieee80211_ptr;
1175 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 1206 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1176 struct cfg80211_bitrate_mask mask; 1207 struct cfg80211_bitrate_mask mask;
1208 u32 fixed, maxrate;
1209 struct ieee80211_supported_band *sband;
1210 int band, ridx;
1211 bool match = false;
1177 1212
1178 if (!rdev->ops->set_bitrate_mask) 1213 if (!rdev->ops->set_bitrate_mask)
1179 return -EOPNOTSUPP; 1214 return -EOPNOTSUPP;
1180 1215
1181 mask.fixed = 0; 1216 memset(&mask, 0, sizeof(mask));
1182 mask.maxrate = 0; 1217 fixed = 0;
1218 maxrate = (u32)-1;
1183 1219
1184 if (rate->value < 0) { 1220 if (rate->value < 0) {
1185 /* nothing */ 1221 /* nothing */
1186 } else if (rate->fixed) { 1222 } else if (rate->fixed) {
1187 mask.fixed = rate->value / 1000; /* kbps */ 1223 fixed = rate->value / 100000;
1188 } else { 1224 } else {
1189 mask.maxrate = rate->value / 1000; /* kbps */ 1225 maxrate = rate->value / 100000;
1190 } 1226 }
1191 1227
1228 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1229 sband = wdev->wiphy->bands[band];
1230 if (sband == NULL)
1231 continue;
1232 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
1233 struct ieee80211_rate *srate = &sband->bitrates[ridx];
1234 if (fixed == srate->bitrate) {
1235 mask.control[band].legacy = 1 << ridx;
1236 match = true;
1237 break;
1238 }
1239 if (srate->bitrate <= maxrate) {
1240 mask.control[band].legacy |= 1 << ridx;
1241 match = true;
1242 }
1243 }
1244 }
1245
1246 if (!match)
1247 return -EINVAL;
1248
1192 return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); 1249 return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1193} 1250}
1194EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); 1251EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);
@@ -1227,10 +1284,7 @@ int cfg80211_wext_giwrate(struct net_device *dev,
1227 if (!(sinfo.filled & STATION_INFO_TX_BITRATE)) 1284 if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
1228 return -EOPNOTSUPP; 1285 return -EOPNOTSUPP;
1229 1286
1230 rate->value = 0; 1287 rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
1231
1232 if (!(sinfo.txrate.flags & RATE_INFO_FLAGS_MCS))
1233 rate->value = 100000 * sinfo.txrate.legacy;
1234 1288
1235 return 0; 1289 return 0;
1236} 1290}
@@ -1372,6 +1426,47 @@ int cfg80211_wext_giwessid(struct net_device *dev,
1372} 1426}
1373EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); 1427EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1374 1428
1429int cfg80211_wext_siwpmksa(struct net_device *dev,
1430 struct iw_request_info *info,
1431 struct iw_point *data, char *extra)
1432{
1433 struct wireless_dev *wdev = dev->ieee80211_ptr;
1434 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1435 struct cfg80211_pmksa cfg_pmksa;
1436 struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
1437
1438 memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
1439
1440 if (wdev->iftype != NL80211_IFTYPE_STATION)
1441 return -EINVAL;
1442
1443 cfg_pmksa.bssid = pmksa->bssid.sa_data;
1444 cfg_pmksa.pmkid = pmksa->pmkid;
1445
1446 switch (pmksa->cmd) {
1447 case IW_PMKSA_ADD:
1448 if (!rdev->ops->set_pmksa)
1449 return -EOPNOTSUPP;
1450
1451 return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1452
1453 case IW_PMKSA_REMOVE:
1454 if (!rdev->ops->del_pmksa)
1455 return -EOPNOTSUPP;
1456
1457 return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1458
1459 case IW_PMKSA_FLUSH:
1460 if (!rdev->ops->flush_pmksa)
1461 return -EOPNOTSUPP;
1462
1463 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
1464
1465 default:
1466 return -EOPNOTSUPP;
1467 }
1468}
1469
1375static const iw_handler cfg80211_handlers[] = { 1470static const iw_handler cfg80211_handlers[] = {
1376 [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, 1471 [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
1377 [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, 1472 [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
@@ -1404,6 +1499,7 @@ static const iw_handler cfg80211_handlers[] = {
1404 [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, 1499 [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
1405 [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, 1500 [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
1406 [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, 1501 [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1502 [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,
1407}; 1503};
1408 1504
1409const struct iw_handler_def cfg80211_wext_handler = { 1505const struct iw_handler_def cfg80211_wext_handler = {