aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/sme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r--net/wireless/sme.c97
1 files changed, 71 insertions, 26 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 79ca56cbfd36..d635a99dba51 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -125,7 +125,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
125 params->channel, params->auth_type, 125 params->channel, params->auth_type,
126 params->bssid, 126 params->bssid,
127 params->ssid, params->ssid_len, 127 params->ssid, params->ssid_len,
128 NULL, 0); 128 NULL, 0,
129 params->key, params->key_len,
130 params->key_idx);
129 case CFG80211_CONN_ASSOCIATE_NEXT: 131 case CFG80211_CONN_ASSOCIATE_NEXT:
130 BUG_ON(!rdev->ops->assoc); 132 BUG_ON(!rdev->ops->assoc);
131 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 133 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -279,8 +281,12 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
279 /* select automatically between only open, shared, leap */ 281 /* select automatically between only open, shared, leap */
280 switch (wdev->conn->params.auth_type) { 282 switch (wdev->conn->params.auth_type) {
281 case NL80211_AUTHTYPE_OPEN_SYSTEM: 283 case NL80211_AUTHTYPE_OPEN_SYSTEM:
282 wdev->conn->params.auth_type = 284 if (wdev->connect_keys)
283 NL80211_AUTHTYPE_SHARED_KEY; 285 wdev->conn->params.auth_type =
286 NL80211_AUTHTYPE_SHARED_KEY;
287 else
288 wdev->conn->params.auth_type =
289 NL80211_AUTHTYPE_NETWORK_EAP;
284 break; 290 break;
285 case NL80211_AUTHTYPE_SHARED_KEY: 291 case NL80211_AUTHTYPE_SHARED_KEY:
286 wdev->conn->params.auth_type = 292 wdev->conn->params.auth_type =
@@ -353,10 +359,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
353#endif 359#endif
354 360
355 if (status == WLAN_STATUS_SUCCESS && 361 if (status == WLAN_STATUS_SUCCESS &&
356 wdev->sme_state == CFG80211_SME_IDLE) { 362 wdev->sme_state == CFG80211_SME_IDLE)
357 wdev->sme_state = CFG80211_SME_CONNECTED; 363 goto success;
358 return;
359 }
360 364
361 if (wdev->sme_state != CFG80211_SME_CONNECTING) 365 if (wdev->sme_state != CFG80211_SME_CONNECTING)
362 return; 366 return;
@@ -370,24 +374,29 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
370 if (wdev->conn) 374 if (wdev->conn)
371 wdev->conn->state = CFG80211_CONN_IDLE; 375 wdev->conn->state = CFG80211_CONN_IDLE;
372 376
373 if (status == WLAN_STATUS_SUCCESS) { 377 if (status != WLAN_STATUS_SUCCESS) {
374 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
375 wdev->ssid, wdev->ssid_len,
376 WLAN_CAPABILITY_ESS,
377 WLAN_CAPABILITY_ESS);
378
379 if (WARN_ON(!bss))
380 return;
381
382 cfg80211_hold_bss(bss_from_pub(bss));
383 wdev->current_bss = bss_from_pub(bss);
384
385 wdev->sme_state = CFG80211_SME_CONNECTED;
386 } else {
387 wdev->sme_state = CFG80211_SME_IDLE; 378 wdev->sme_state = CFG80211_SME_IDLE;
388 kfree(wdev->conn); 379 kfree(wdev->conn);
389 wdev->conn = NULL; 380 wdev->conn = NULL;
381 kfree(wdev->connect_keys);
382 wdev->connect_keys = NULL;
383 return;
390 } 384 }
385
386 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
387 wdev->ssid, wdev->ssid_len,
388 WLAN_CAPABILITY_ESS,
389 WLAN_CAPABILITY_ESS);
390
391 if (WARN_ON(!bss))
392 return;
393
394 cfg80211_hold_bss(bss_from_pub(bss));
395 wdev->current_bss = bss_from_pub(bss);
396
397 success:
398 wdev->sme_state = CFG80211_SME_CONNECTED;
399 cfg80211_upload_connect_keys(wdev);
391} 400}
392 401
393void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 402void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
@@ -516,6 +525,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
516 size_t ie_len, u16 reason, bool from_ap) 525 size_t ie_len, u16 reason, bool from_ap)
517{ 526{
518 struct wireless_dev *wdev = dev->ieee80211_ptr; 527 struct wireless_dev *wdev = dev->ieee80211_ptr;
528 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
529 int i;
519#ifdef CONFIG_WIRELESS_EXT 530#ifdef CONFIG_WIRELESS_EXT
520 union iwreq_data wrqu; 531 union iwreq_data wrqu;
521#endif 532#endif
@@ -543,8 +554,15 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
543 wdev->conn = NULL; 554 wdev->conn = NULL;
544 } 555 }
545 556
546 nl80211_send_disconnected(wiphy_to_dev(wdev->wiphy), dev, 557 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
547 reason, ie, ie_len, from_ap); 558
559 /*
560 * Delete all the keys ... pairwise keys can't really
561 * exist any more anyway, but default keys might.
562 */
563 if (rdev->ops->del_key)
564 for (i = 0; i < 6; i++)
565 rdev->ops->del_key(wdev->wiphy, dev, i, NULL);
548 566
549#ifdef CONFIG_WIRELESS_EXT 567#ifdef CONFIG_WIRELESS_EXT
550 memset(&wrqu, 0, sizeof(wrqu)); 568 memset(&wrqu, 0, sizeof(wrqu));
@@ -580,7 +598,8 @@ EXPORT_SYMBOL(cfg80211_disconnected);
580 598
581int __cfg80211_connect(struct cfg80211_registered_device *rdev, 599int __cfg80211_connect(struct cfg80211_registered_device *rdev,
582 struct net_device *dev, 600 struct net_device *dev,
583 struct cfg80211_connect_params *connect) 601 struct cfg80211_connect_params *connect,
602 struct cfg80211_cached_keys *connkeys)
584{ 603{
585 struct wireless_dev *wdev = dev->ieee80211_ptr; 604 struct wireless_dev *wdev = dev->ieee80211_ptr;
586 int err; 605 int err;
@@ -590,6 +609,24 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
590 if (wdev->sme_state != CFG80211_SME_IDLE) 609 if (wdev->sme_state != CFG80211_SME_IDLE)
591 return -EALREADY; 610 return -EALREADY;
592 611
612 if (WARN_ON(wdev->connect_keys)) {
613 kfree(wdev->connect_keys);
614 wdev->connect_keys = NULL;
615 }
616
617 if (connkeys && connkeys->def >= 0) {
618 int idx;
619
620 idx = connkeys->def;
621 /* If given a WEP key we may need it for shared key auth */
622 if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 ||
623 connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) {
624 connect->key_idx = idx;
625 connect->key = connkeys->params[idx].key;
626 connect->key_len = connkeys->params[idx].key_len;
627 }
628 }
629
593 if (!rdev->ops->connect) { 630 if (!rdev->ops->connect) {
594 if (!rdev->ops->auth || !rdev->ops->assoc) 631 if (!rdev->ops->auth || !rdev->ops->assoc)
595 return -EOPNOTSUPP; 632 return -EOPNOTSUPP;
@@ -640,6 +677,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
640 cfg80211_get_conn_bss(wdev); 677 cfg80211_get_conn_bss(wdev);
641 678
642 wdev->sme_state = CFG80211_SME_CONNECTING; 679 wdev->sme_state = CFG80211_SME_CONNECTING;
680 wdev->connect_keys = connkeys;
643 681
644 /* we're good if we have both BSSID and channel */ 682 /* we're good if we have both BSSID and channel */
645 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 683 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
@@ -662,13 +700,16 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
662 kfree(wdev->conn); 700 kfree(wdev->conn);
663 wdev->conn = NULL; 701 wdev->conn = NULL;
664 wdev->sme_state = CFG80211_SME_IDLE; 702 wdev->sme_state = CFG80211_SME_IDLE;
703 wdev->connect_keys = NULL;
665 } 704 }
666 705
667 return err; 706 return err;
668 } else { 707 } else {
669 wdev->sme_state = CFG80211_SME_CONNECTING; 708 wdev->sme_state = CFG80211_SME_CONNECTING;
709 wdev->connect_keys = connkeys;
670 err = rdev->ops->connect(&rdev->wiphy, dev, connect); 710 err = rdev->ops->connect(&rdev->wiphy, dev, connect);
671 if (err) { 711 if (err) {
712 wdev->connect_keys = NULL;
672 wdev->sme_state = CFG80211_SME_IDLE; 713 wdev->sme_state = CFG80211_SME_IDLE;
673 return err; 714 return err;
674 } 715 }
@@ -682,12 +723,13 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
682 723
683int cfg80211_connect(struct cfg80211_registered_device *rdev, 724int cfg80211_connect(struct cfg80211_registered_device *rdev,
684 struct net_device *dev, 725 struct net_device *dev,
685 struct cfg80211_connect_params *connect) 726 struct cfg80211_connect_params *connect,
727 struct cfg80211_cached_keys *connkeys)
686{ 728{
687 int err; 729 int err;
688 730
689 wdev_lock(dev->ieee80211_ptr); 731 wdev_lock(dev->ieee80211_ptr);
690 err = __cfg80211_connect(rdev, dev, connect); 732 err = __cfg80211_connect(rdev, dev, connect, connkeys);
691 wdev_unlock(dev->ieee80211_ptr); 733 wdev_unlock(dev->ieee80211_ptr);
692 734
693 return err; 735 return err;
@@ -704,6 +746,9 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,
704 if (wdev->sme_state == CFG80211_SME_IDLE) 746 if (wdev->sme_state == CFG80211_SME_IDLE)
705 return -EINVAL; 747 return -EINVAL;
706 748
749 kfree(wdev->connect_keys);
750 wdev->connect_keys = NULL;
751
707 if (!rdev->ops->disconnect) { 752 if (!rdev->ops->disconnect) {
708 if (!rdev->ops->deauth) 753 if (!rdev->ops->deauth)
709 return -EOPNOTSUPP; 754 return -EOPNOTSUPP;