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