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.c61
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,
553EXPORT_SYMBOL(cfg80211_connect_result); 553EXPORT_SYMBOL(cfg80211_connect_result);
554 554
555void __cfg80211_roamed(struct wireless_dev *wdev, 555void __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;
612out:
613 cfg80211_put_bss(bss);
620} 614}
621 615
622void cfg80211_roamed(struct net_device *dev, 616void 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}
636EXPORT_SYMBOL(cfg80211_roamed);
637
638void 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}
654EXPORT_SYMBOL(cfg80211_roamed); 673EXPORT_SYMBOL(cfg80211_roamed_bss);
655 674
656void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, 675void __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)