aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKanchanapally, Vidyullatha <vkanchan@qti.qualcomm.com>2016-04-11 05:46:01 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-04-26 03:40:12 -0400
commite705498945ad3a3b945771c5d683df064bb9819c (patch)
tree299d884abfafbe1b4b8f37b55dfff6861932ce92
parent739960f128e5a1f251659a4430a8898087701099 (diff)
cfg80211: Add option to report the bss entry in connect result
Since cfg80211 maintains separate BSS table entries for APs if the same BSSID, SSID pair is seen on multiple channels, it is possible that it can map the current_bss to a BSS entry on the wrong channel. This current_bss will not get flushed unless disconnected and cfg80211 reports a wrong channel as the associated channel. Fix this by introducing a new cfg80211_connect_bss() function which is similar to cfg80211_connect_result(), but it includes an additional parameter: the bss the STA is connected to. This allows drivers to provide the exact bss entry that matches the BSS to which the connection was completed. Reviewed-by: Jouni Malinen <jouni@qca.qualcomm.com> Signed-off-by: Vidyullatha Kanchanapally <vkanchan@qti.qualcomm.com> Signed-off-by: Sunil Dutt <usdutt@qti.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--Documentation/DocBook/80211.tmpl1
-rw-r--r--include/net/cfg80211.h39
-rw-r--r--net/wireless/core.h1
-rw-r--r--net/wireless/sme.c28
-rw-r--r--net/wireless/util.c2
5 files changed, 60 insertions, 11 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index f2a312b35875..5f7c55999c77 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -135,6 +135,7 @@
135!Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt 135!Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt
136!Finclude/net/cfg80211.h cfg80211_ibss_joined 136!Finclude/net/cfg80211.h cfg80211_ibss_joined
137!Finclude/net/cfg80211.h cfg80211_connect_result 137!Finclude/net/cfg80211.h cfg80211_connect_result
138!Finclude/net/cfg80211.h cfg80211_connect_bss
138!Finclude/net/cfg80211.h cfg80211_roamed 139!Finclude/net/cfg80211.h cfg80211_roamed
139!Finclude/net/cfg80211.h cfg80211_disconnected 140!Finclude/net/cfg80211.h cfg80211_disconnected
140!Finclude/net/cfg80211.h cfg80211_ready_on_channel 141!Finclude/net/cfg80211.h cfg80211_ready_on_channel
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index c8414962683d..1e008cddd41d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4652,6 +4652,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
4652#endif 4652#endif
4653 4653
4654/** 4654/**
4655 * cfg80211_connect_bss - notify cfg80211 of connection result
4656 *
4657 * @dev: network device
4658 * @bssid: the BSSID of the AP
4659 * @bss: entry of bss to which STA got connected to, can be obtained
4660 * through cfg80211_get_bss (may be %NULL)
4661 * @req_ie: association request IEs (maybe be %NULL)
4662 * @req_ie_len: association request IEs length
4663 * @resp_ie: association response IEs (may be %NULL)
4664 * @resp_ie_len: assoc response IEs length
4665 * @status: status code, 0 for successful connection, use
4666 * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
4667 * the real status code for failures.
4668 * @gfp: allocation flags
4669 *
4670 * It should be called by the underlying driver whenever connect() has
4671 * succeeded. This is similar to cfg80211_connect_result(), but with the
4672 * option of identifying the exact bss entry for the connection. Only one of
4673 * these functions should be called.
4674 */
4675void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
4676 struct cfg80211_bss *bss, const u8 *req_ie,
4677 size_t req_ie_len, const u8 *resp_ie,
4678 size_t resp_ie_len, u16 status, gfp_t gfp);
4679
4680/**
4655 * cfg80211_connect_result - notify cfg80211 of connection result 4681 * cfg80211_connect_result - notify cfg80211 of connection result
4656 * 4682 *
4657 * @dev: network device 4683 * @dev: network device
@@ -4668,10 +4694,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
4668 * It should be called by the underlying driver whenever connect() has 4694 * It should be called by the underlying driver whenever connect() has
4669 * succeeded. 4695 * succeeded.
4670 */ 4696 */
4671void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 4697static inline void
4672 const u8 *req_ie, size_t req_ie_len, 4698cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
4673 const u8 *resp_ie, size_t resp_ie_len, 4699 const u8 *req_ie, size_t req_ie_len,
4674 u16 status, gfp_t gfp); 4700 const u8 *resp_ie, size_t resp_ie_len,
4701 u16 status, gfp_t gfp)
4702{
4703 cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie,
4704 resp_ie_len, status, gfp);
4705}
4675 4706
4676/** 4707/**
4677 * cfg80211_roamed - notify cfg80211 of roaming 4708 * cfg80211_roamed - notify cfg80211 of roaming
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 022ccad06cbe..ac44e77ac2f2 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -214,6 +214,7 @@ struct cfg80211_event {
214 const u8 *resp_ie; 214 const u8 *resp_ie;
215 size_t req_ie_len; 215 size_t req_ie_len;
216 size_t resp_ie_len; 216 size_t resp_ie_len;
217 struct cfg80211_bss *bss;
217 u16 status; 218 u16 status;
218 } cr; 219 } cr;
219 struct { 220 struct {
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index e22e5b83cfa9..d814279fb556 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -753,19 +753,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
753 kfree(country_ie); 753 kfree(country_ie);
754} 754}
755 755
756void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 756/* Consumes bss object one way or another */
757 const u8 *req_ie, size_t req_ie_len, 757void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
758 const u8 *resp_ie, size_t resp_ie_len, 758 struct cfg80211_bss *bss, const u8 *req_ie,
759 u16 status, gfp_t gfp) 759 size_t req_ie_len, const u8 *resp_ie,
760 size_t resp_ie_len, u16 status, gfp_t gfp)
760{ 761{
761 struct wireless_dev *wdev = dev->ieee80211_ptr; 762 struct wireless_dev *wdev = dev->ieee80211_ptr;
762 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 763 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
763 struct cfg80211_event *ev; 764 struct cfg80211_event *ev;
764 unsigned long flags; 765 unsigned long flags;
765 766
767 if (bss) {
768 /* Make sure the bss entry provided by the driver is valid. */
769 struct cfg80211_internal_bss *ibss = bss_from_pub(bss);
770
771 if (WARN_ON(list_empty(&ibss->list))) {
772 cfg80211_put_bss(wdev->wiphy, bss);
773 return;
774 }
775 }
776
766 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); 777 ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
767 if (!ev) 778 if (!ev) {
779 cfg80211_put_bss(wdev->wiphy, bss);
768 return; 780 return;
781 }
769 782
770 ev->type = EVENT_CONNECT_RESULT; 783 ev->type = EVENT_CONNECT_RESULT;
771 if (bssid) 784 if (bssid)
@@ -780,6 +793,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
780 ev->cr.resp_ie_len = resp_ie_len; 793 ev->cr.resp_ie_len = resp_ie_len;
781 memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); 794 memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
782 } 795 }
796 if (bss)
797 cfg80211_hold_bss(bss_from_pub(bss));
798 ev->cr.bss = bss;
783 ev->cr.status = status; 799 ev->cr.status = status;
784 800
785 spin_lock_irqsave(&wdev->event_lock, flags); 801 spin_lock_irqsave(&wdev->event_lock, flags);
@@ -787,7 +803,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
787 spin_unlock_irqrestore(&wdev->event_lock, flags); 803 spin_unlock_irqrestore(&wdev->event_lock, flags);
788 queue_work(cfg80211_wq, &rdev->event_work); 804 queue_work(cfg80211_wq, &rdev->event_work);
789} 805}
790EXPORT_SYMBOL(cfg80211_connect_result); 806EXPORT_SYMBOL(cfg80211_connect_bss);
791 807
792/* Consumes bss object one way or another */ 808/* Consumes bss object one way or another */
793void __cfg80211_roamed(struct wireless_dev *wdev, 809void __cfg80211_roamed(struct wireless_dev *wdev,
diff --git a/net/wireless/util.c b/net/wireless/util.c
index f36039888eb5..7cfabd6e83c6 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -950,7 +950,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
950 ev->cr.resp_ie, ev->cr.resp_ie_len, 950 ev->cr.resp_ie, ev->cr.resp_ie_len,
951 ev->cr.status, 951 ev->cr.status,
952 ev->cr.status == WLAN_STATUS_SUCCESS, 952 ev->cr.status == WLAN_STATUS_SUCCESS,
953 NULL); 953 ev->cr.bss);
954 break; 954 break;
955 case EVENT_ROAMED: 955 case EVENT_ROAMED:
956 __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, 956 __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,