diff options
Diffstat (limited to 'net/wireless/wext-compat.c')
-rw-r--r-- | net/wireless/wext-compat.c | 98 |
1 files changed, 85 insertions, 13 deletions
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 561a45cf2a6a..54face3d4424 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -437,6 +437,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
437 | { | 437 | { |
438 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 438 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
439 | int err, i; | 439 | int err, i; |
440 | bool rejoin = false; | ||
440 | 441 | ||
441 | if (!wdev->wext.keys) { | 442 | if (!wdev->wext.keys) { |
442 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), | 443 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), |
@@ -466,8 +467,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
466 | 467 | ||
467 | if (remove) { | 468 | if (remove) { |
468 | err = 0; | 469 | err = 0; |
469 | if (wdev->current_bss) | 470 | if (wdev->current_bss) { |
471 | /* | ||
472 | * If removing the current TX key, we will need to | ||
473 | * join a new IBSS without the privacy bit clear. | ||
474 | */ | ||
475 | if (idx == wdev->wext.default_key && | ||
476 | wdev->iftype == NL80211_IFTYPE_ADHOC) { | ||
477 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | ||
478 | rejoin = true; | ||
479 | } | ||
470 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | 480 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); |
481 | } | ||
482 | wdev->wext.connect.privacy = false; | ||
483 | /* | ||
484 | * Applications using wireless extensions expect to be | ||
485 | * able to delete keys that don't exist, so allow that. | ||
486 | */ | ||
487 | if (err == -ENOENT) | ||
488 | err = 0; | ||
471 | if (!err) { | 489 | if (!err) { |
472 | if (!addr) { | 490 | if (!addr) { |
473 | wdev->wext.keys->params[idx].key_len = 0; | 491 | wdev->wext.keys->params[idx].key_len = 0; |
@@ -478,12 +496,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
478 | else if (idx == wdev->wext.default_mgmt_key) | 496 | else if (idx == wdev->wext.default_mgmt_key) |
479 | wdev->wext.default_mgmt_key = -1; | 497 | wdev->wext.default_mgmt_key = -1; |
480 | } | 498 | } |
481 | /* | 499 | |
482 | * Applications using wireless extensions expect to be | 500 | if (!err && rejoin) |
483 | * able to delete keys that don't exist, so allow that. | 501 | err = cfg80211_ibss_wext_join(rdev, wdev); |
484 | */ | ||
485 | if (err == -ENOENT) | ||
486 | return 0; | ||
487 | 502 | ||
488 | return err; | 503 | return err; |
489 | } | 504 | } |
@@ -511,11 +526,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
511 | if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || | 526 | if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || |
512 | params->cipher == WLAN_CIPHER_SUITE_WEP104) && | 527 | params->cipher == WLAN_CIPHER_SUITE_WEP104) && |
513 | (tx_key || (!addr && wdev->wext.default_key == -1))) { | 528 | (tx_key || (!addr && wdev->wext.default_key == -1))) { |
514 | if (wdev->current_bss) | 529 | if (wdev->current_bss) { |
530 | /* | ||
531 | * If we are getting a new TX key from not having | ||
532 | * had one before we need to join a new IBSS with | ||
533 | * the privacy bit set. | ||
534 | */ | ||
535 | if (wdev->iftype == NL80211_IFTYPE_ADHOC && | ||
536 | wdev->wext.default_key == -1) { | ||
537 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | ||
538 | rejoin = true; | ||
539 | } | ||
515 | err = rdev->ops->set_default_key(&rdev->wiphy, | 540 | err = rdev->ops->set_default_key(&rdev->wiphy, |
516 | dev, idx); | 541 | dev, idx); |
517 | if (!err) | 542 | } |
543 | if (!err) { | ||
518 | wdev->wext.default_key = idx; | 544 | wdev->wext.default_key = idx; |
545 | if (rejoin) | ||
546 | err = cfg80211_ibss_wext_join(rdev, wdev); | ||
547 | } | ||
519 | return err; | 548 | return err; |
520 | } | 549 | } |
521 | 550 | ||
@@ -539,10 +568,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
539 | { | 568 | { |
540 | int err; | 569 | int err; |
541 | 570 | ||
571 | /* devlist mutex needed for possible IBSS re-join */ | ||
572 | mutex_lock(&rdev->devlist_mtx); | ||
542 | wdev_lock(dev->ieee80211_ptr); | 573 | wdev_lock(dev->ieee80211_ptr); |
543 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, | 574 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, |
544 | tx_key, idx, params); | 575 | tx_key, idx, params); |
545 | wdev_unlock(dev->ieee80211_ptr); | 576 | wdev_unlock(dev->ieee80211_ptr); |
577 | mutex_unlock(&rdev->devlist_mtx); | ||
546 | 578 | ||
547 | return err; | 579 | return err; |
548 | } | 580 | } |
@@ -904,8 +936,6 @@ static int cfg80211_set_auth_alg(struct wireless_dev *wdev, | |||
904 | 936 | ||
905 | static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) | 937 | static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) |
906 | { | 938 | { |
907 | wdev->wext.connect.crypto.wpa_versions = 0; | ||
908 | |||
909 | if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | | 939 | if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA | |
910 | IW_AUTH_WPA_VERSION_WPA2| | 940 | IW_AUTH_WPA_VERSION_WPA2| |
911 | IW_AUTH_WPA_VERSION_DISABLED)) | 941 | IW_AUTH_WPA_VERSION_DISABLED)) |
@@ -933,8 +963,6 @@ static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions) | |||
933 | 963 | ||
934 | static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) | 964 | static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) |
935 | { | 965 | { |
936 | wdev->wext.connect.crypto.cipher_group = 0; | ||
937 | |||
938 | if (cipher & IW_AUTH_CIPHER_WEP40) | 966 | if (cipher & IW_AUTH_CIPHER_WEP40) |
939 | wdev->wext.connect.crypto.cipher_group = | 967 | wdev->wext.connect.crypto.cipher_group = |
940 | WLAN_CIPHER_SUITE_WEP40; | 968 | WLAN_CIPHER_SUITE_WEP40; |
@@ -950,6 +978,8 @@ static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher) | |||
950 | else if (cipher & IW_AUTH_CIPHER_AES_CMAC) | 978 | else if (cipher & IW_AUTH_CIPHER_AES_CMAC) |
951 | wdev->wext.connect.crypto.cipher_group = | 979 | wdev->wext.connect.crypto.cipher_group = |
952 | WLAN_CIPHER_SUITE_AES_CMAC; | 980 | WLAN_CIPHER_SUITE_AES_CMAC; |
981 | else if (cipher & IW_AUTH_CIPHER_NONE) | ||
982 | wdev->wext.connect.crypto.cipher_group = 0; | ||
953 | else | 983 | else |
954 | return -EINVAL; | 984 | return -EINVAL; |
955 | 985 | ||
@@ -1372,6 +1402,47 @@ int cfg80211_wext_giwessid(struct net_device *dev, | |||
1372 | } | 1402 | } |
1373 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); | 1403 | EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); |
1374 | 1404 | ||
1405 | int cfg80211_wext_siwpmksa(struct net_device *dev, | ||
1406 | struct iw_request_info *info, | ||
1407 | struct iw_point *data, char *extra) | ||
1408 | { | ||
1409 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1410 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
1411 | struct cfg80211_pmksa cfg_pmksa; | ||
1412 | struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; | ||
1413 | |||
1414 | memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa)); | ||
1415 | |||
1416 | if (wdev->iftype != NL80211_IFTYPE_STATION) | ||
1417 | return -EINVAL; | ||
1418 | |||
1419 | cfg_pmksa.bssid = pmksa->bssid.sa_data; | ||
1420 | cfg_pmksa.pmkid = pmksa->pmkid; | ||
1421 | |||
1422 | switch (pmksa->cmd) { | ||
1423 | case IW_PMKSA_ADD: | ||
1424 | if (!rdev->ops->set_pmksa) | ||
1425 | return -EOPNOTSUPP; | ||
1426 | |||
1427 | return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa); | ||
1428 | |||
1429 | case IW_PMKSA_REMOVE: | ||
1430 | if (!rdev->ops->del_pmksa) | ||
1431 | return -EOPNOTSUPP; | ||
1432 | |||
1433 | return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa); | ||
1434 | |||
1435 | case IW_PMKSA_FLUSH: | ||
1436 | if (!rdev->ops->flush_pmksa) | ||
1437 | return -EOPNOTSUPP; | ||
1438 | |||
1439 | return rdev->ops->flush_pmksa(&rdev->wiphy, dev); | ||
1440 | |||
1441 | default: | ||
1442 | return -EOPNOTSUPP; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1375 | static const iw_handler cfg80211_handlers[] = { | 1446 | static const iw_handler cfg80211_handlers[] = { |
1376 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, | 1447 | [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, |
1377 | [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, | 1448 | [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, |
@@ -1404,6 +1475,7 @@ static const iw_handler cfg80211_handlers[] = { | |||
1404 | [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, | 1475 | [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, |
1405 | [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, | 1476 | [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, |
1406 | [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, | 1477 | [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, |
1478 | [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa, | ||
1407 | }; | 1479 | }; |
1408 | 1480 | ||
1409 | const struct iw_handler_def cfg80211_wext_handler = { | 1481 | const struct iw_handler_def cfg80211_wext_handler = { |