Commit e7054989 authored by Kanchanapally, Vidyullatha's avatar Kanchanapally, Vidyullatha Committed by Johannes Berg

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: default avatarJouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: default avatarVidyullatha Kanchanapally <vkanchan@qti.qualcomm.com>
Signed-off-by: default avatarSunil Dutt <usdutt@qti.qualcomm.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 739960f1
......@@ -135,6 +135,7 @@
!Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt
!Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_connect_bss
!Finclude/net/cfg80211.h cfg80211_roamed
!Finclude/net/cfg80211.h cfg80211_disconnected
!Finclude/net/cfg80211.h cfg80211_ready_on_channel
......
......@@ -4651,6 +4651,32 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
#define CFG80211_TESTMODE_DUMP(cmd)
#endif
/**
* cfg80211_connect_bss - notify cfg80211 of connection result
*
* @dev: network device
* @bssid: the BSSID of the AP
* @bss: entry of bss to which STA got connected to, can be obtained
* through cfg80211_get_bss (may be %NULL)
* @req_ie: association request IEs (maybe be %NULL)
* @req_ie_len: association request IEs length
* @resp_ie: association response IEs (may be %NULL)
* @resp_ie_len: assoc response IEs length
* @status: status code, 0 for successful connection, use
* %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you
* the real status code for failures.
* @gfp: allocation flags
*
* It should be called by the underlying driver whenever connect() has
* succeeded. This is similar to cfg80211_connect_result(), but with the
* option of identifying the exact bss entry for the connection. Only one of
* these functions should be called.
*/
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp);
/**
* cfg80211_connect_result - notify cfg80211 of connection result
*
......@@ -4668,10 +4694,15 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
* It should be called by the underlying driver whenever connect() has
* succeeded.
*/
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
u16 status, gfp_t gfp);
static inline void
cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
u16 status, gfp_t gfp)
{
cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, resp_ie,
resp_ie_len, status, gfp);
}
/**
* cfg80211_roamed - notify cfg80211 of roaming
......
......@@ -214,6 +214,7 @@ struct cfg80211_event {
const u8 *resp_ie;
size_t req_ie_len;
size_t resp_ie_len;
struct cfg80211_bss *bss;
u16 status;
} cr;
struct {
......
......@@ -753,19 +753,32 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
kfree(country_ie);
}
void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
const u8 *req_ie, size_t req_ie_len,
const u8 *resp_ie, size_t resp_ie_len,
u16 status, gfp_t gfp)
/* Consumes bss object one way or another */
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
struct cfg80211_bss *bss, const u8 *req_ie,
size_t req_ie_len, const u8 *resp_ie,
size_t resp_ie_len, u16 status, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_event *ev;
unsigned long flags;
if (bss) {
/* Make sure the bss entry provided by the driver is valid. */
struct cfg80211_internal_bss *ibss = bss_from_pub(bss);
if (WARN_ON(list_empty(&ibss->list))) {
cfg80211_put_bss(wdev->wiphy, bss);
return;
}
}
ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp);
if (!ev)
if (!ev) {
cfg80211_put_bss(wdev->wiphy, bss);
return;
}
ev->type = EVENT_CONNECT_RESULT;
if (bssid)
......@@ -780,6 +793,9 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
ev->cr.resp_ie_len = resp_ie_len;
memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len);
}
if (bss)
cfg80211_hold_bss(bss_from_pub(bss));
ev->cr.bss = bss;
ev->cr.status = status;
spin_lock_irqsave(&wdev->event_lock, flags);
......@@ -787,7 +803,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
spin_unlock_irqrestore(&wdev->event_lock, flags);
queue_work(cfg80211_wq, &rdev->event_work);
}
EXPORT_SYMBOL(cfg80211_connect_result);
EXPORT_SYMBOL(cfg80211_connect_bss);
/* Consumes bss object one way or another */
void __cfg80211_roamed(struct wireless_dev *wdev,
......
......@@ -950,7 +950,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
ev->cr.resp_ie, ev->cr.resp_ie_len,
ev->cr.status,
ev->cr.status == WLAN_STATUS_SUCCESS,
NULL);
ev->cr.bss);
break;
case EVENT_ROAMED:
__cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment