diff options
Diffstat (limited to 'net/wireless/sme.c')
-rw-r--r-- | net/wireless/sme.c | 61 |
1 files changed, 40 insertions, 21 deletions
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f0c900ce2fb9..7b9ecaed96be 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -553,45 +553,35 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
553 | EXPORT_SYMBOL(cfg80211_connect_result); | 553 | EXPORT_SYMBOL(cfg80211_connect_result); |
554 | 554 | ||
555 | void __cfg80211_roamed(struct wireless_dev *wdev, | 555 | void __cfg80211_roamed(struct wireless_dev *wdev, |
556 | struct ieee80211_channel *channel, | 556 | struct cfg80211_bss *bss, |
557 | const u8 *bssid, | ||
558 | const u8 *req_ie, size_t req_ie_len, | 557 | const u8 *req_ie, size_t req_ie_len, |
559 | const u8 *resp_ie, size_t resp_ie_len) | 558 | const u8 *resp_ie, size_t resp_ie_len) |
560 | { | 559 | { |
561 | struct cfg80211_bss *bss; | ||
562 | #ifdef CONFIG_CFG80211_WEXT | 560 | #ifdef CONFIG_CFG80211_WEXT |
563 | union iwreq_data wrqu; | 561 | union iwreq_data wrqu; |
564 | #endif | 562 | #endif |
565 | |||
566 | ASSERT_WDEV_LOCK(wdev); | 563 | ASSERT_WDEV_LOCK(wdev); |
567 | 564 | ||
568 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && | 565 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
569 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) | 566 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) |
570 | return; | 567 | goto out; |
571 | 568 | ||
572 | if (wdev->sme_state != CFG80211_SME_CONNECTED) | 569 | if (wdev->sme_state != CFG80211_SME_CONNECTED) |
573 | return; | 570 | goto out; |
574 | 571 | ||
575 | /* internal error -- how did we get to CONNECTED w/o BSS? */ | 572 | /* internal error -- how did we get to CONNECTED w/o BSS? */ |
576 | if (WARN_ON(!wdev->current_bss)) { | 573 | if (WARN_ON(!wdev->current_bss)) { |
577 | return; | 574 | goto out; |
578 | } | 575 | } |
579 | 576 | ||
580 | cfg80211_unhold_bss(wdev->current_bss); | 577 | cfg80211_unhold_bss(wdev->current_bss); |
581 | cfg80211_put_bss(&wdev->current_bss->pub); | 578 | cfg80211_put_bss(&wdev->current_bss->pub); |
582 | wdev->current_bss = NULL; | 579 | wdev->current_bss = NULL; |
583 | 580 | ||
584 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, | ||
585 | wdev->ssid, wdev->ssid_len, | ||
586 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
587 | |||
588 | if (WARN_ON(!bss)) | ||
589 | return; | ||
590 | |||
591 | cfg80211_hold_bss(bss_from_pub(bss)); | 581 | cfg80211_hold_bss(bss_from_pub(bss)); |
592 | wdev->current_bss = bss_from_pub(bss); | 582 | wdev->current_bss = bss_from_pub(bss); |
593 | 583 | ||
594 | nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bssid, | 584 | nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), wdev->netdev, bss->bssid, |
595 | req_ie, req_ie_len, resp_ie, resp_ie_len, | 585 | req_ie, req_ie_len, resp_ie, resp_ie_len, |
596 | GFP_KERNEL); | 586 | GFP_KERNEL); |
597 | 587 | ||
@@ -612,11 +602,15 @@ void __cfg80211_roamed(struct wireless_dev *wdev, | |||
612 | 602 | ||
613 | memset(&wrqu, 0, sizeof(wrqu)); | 603 | memset(&wrqu, 0, sizeof(wrqu)); |
614 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 604 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
615 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | 605 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
616 | memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN); | 606 | memcpy(wdev->wext.prev_bssid, bss->bssid, ETH_ALEN); |
617 | wdev->wext.prev_bssid_valid = true; | 607 | wdev->wext.prev_bssid_valid = true; |
618 | wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); | 608 | wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); |
619 | #endif | 609 | #endif |
610 | |||
611 | return; | ||
612 | out: | ||
613 | cfg80211_put_bss(bss); | ||
620 | } | 614 | } |
621 | 615 | ||
622 | void cfg80211_roamed(struct net_device *dev, | 616 | void cfg80211_roamed(struct net_device *dev, |
@@ -626,32 +620,57 @@ void cfg80211_roamed(struct net_device *dev, | |||
626 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) | 620 | const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) |
627 | { | 621 | { |
628 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 622 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
623 | struct cfg80211_bss *bss; | ||
624 | |||
625 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); | ||
626 | |||
627 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, wdev->ssid, | ||
628 | wdev->ssid_len, WLAN_CAPABILITY_ESS, | ||
629 | WLAN_CAPABILITY_ESS); | ||
630 | if (WARN_ON(!bss)) | ||
631 | return; | ||
632 | |||
633 | cfg80211_roamed_bss(dev, bss, req_ie, req_ie_len, resp_ie, | ||
634 | resp_ie_len, gfp); | ||
635 | } | ||
636 | EXPORT_SYMBOL(cfg80211_roamed); | ||
637 | |||
638 | void cfg80211_roamed_bss(struct net_device *dev, | ||
639 | struct cfg80211_bss *bss, const u8 *req_ie, | ||
640 | size_t req_ie_len, const u8 *resp_ie, | ||
641 | size_t resp_ie_len, gfp_t gfp) | ||
642 | { | ||
643 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
629 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 644 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
630 | struct cfg80211_event *ev; | 645 | struct cfg80211_event *ev; |
631 | unsigned long flags; | 646 | unsigned long flags; |
632 | 647 | ||
633 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); | 648 | CFG80211_DEV_WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTED); |
634 | 649 | ||
650 | if (WARN_ON(!bss)) | ||
651 | return; | ||
652 | |||
635 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); | 653 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); |
636 | if (!ev) | 654 | if (!ev) { |
655 | cfg80211_put_bss(bss); | ||
637 | return; | 656 | return; |
657 | } | ||
638 | 658 | ||
639 | ev->type = EVENT_ROAMED; | 659 | ev->type = EVENT_ROAMED; |
640 | ev->rm.channel = channel; | ||
641 | memcpy(ev->rm.bssid, bssid, ETH_ALEN); | ||
642 | ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); | 660 | ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); |
643 | ev->rm.req_ie_len = req_ie_len; | 661 | ev->rm.req_ie_len = req_ie_len; |
644 | memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len); | 662 | memcpy((void *)ev->rm.req_ie, req_ie, req_ie_len); |
645 | ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | 663 | ev->rm.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; |
646 | ev->rm.resp_ie_len = resp_ie_len; | 664 | ev->rm.resp_ie_len = resp_ie_len; |
647 | memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len); | 665 | memcpy((void *)ev->rm.resp_ie, resp_ie, resp_ie_len); |
666 | ev->rm.bss = bss; | ||
648 | 667 | ||
649 | spin_lock_irqsave(&wdev->event_lock, flags); | 668 | spin_lock_irqsave(&wdev->event_lock, flags); |
650 | list_add_tail(&ev->list, &wdev->event_list); | 669 | list_add_tail(&ev->list, &wdev->event_list); |
651 | spin_unlock_irqrestore(&wdev->event_lock, flags); | 670 | spin_unlock_irqrestore(&wdev->event_lock, flags); |
652 | queue_work(cfg80211_wq, &rdev->event_work); | 671 | queue_work(cfg80211_wq, &rdev->event_work); |
653 | } | 672 | } |
654 | EXPORT_SYMBOL(cfg80211_roamed); | 673 | EXPORT_SYMBOL(cfg80211_roamed_bss); |
655 | 674 | ||
656 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 675 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
657 | size_t ie_len, u16 reason, bool from_ap) | 676 | size_t ie_len, u16 reason, bool from_ap) |