diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index 9d891537ef6a..0ed453133650 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -5125,6 +5125,74 @@ QDF_STATUS csr_roam_set_bss_config_cfg(struct mac_context *mac, uint32_t session return QDF_STATUS_SUCCESS; } +/** + * csr_check_for_hidden_ssid_match() - Check if the current connected SSID + * is hidden ssid and if it matches with the roamed AP ssid. + * @mac: Global mac context pointer + * @session: csr session pointer + * @roamed_bss_desc: pointer to bss descriptor of roamed bss + * @roamed_bss_ies: Roamed AP beacon/probe IEs pointer + * + * Return: True if the SSID is hidden and matches with roamed SSID else false + */ +static bool +csr_check_for_hidden_ssid_match(struct mac_context *mac, + struct csr_roam_session *session, + struct bss_description *roamed_bss_desc, + tDot11fBeaconIEs *roamed_bss_ies) +{ + QDF_STATUS status; + bool is_null_ssid_match = false; + tDot11fBeaconIEs *connected_profile_ies = NULL; + + if (!session || !roamed_bss_ies) + return false; + + status = csr_get_parsed_bss_description_ies(mac, + session->pConnectBssDesc, + &connected_profile_ies); + if (QDF_IS_STATUS_ERROR(status)) { + sme_err("Unable to get IES"); + goto error; + } + + if (!csr_is_nullssid(connected_profile_ies->SSID.ssid, + connected_profile_ies->SSID.num_ssid)) + goto error; + + /* + * After roam synch indication is received, the driver compares + * the SSID of the current AP and SSID of the roamed AP. If + * there is a mismatch, driver issues disassociate to current + * connected AP. This causes data path queues to be stopped and + * M2 to the roamed AP from userspace will fail if EAPOL is + * offloaded to userspace. The SSID of the current AP is + * parsed from the beacon IEs stored in the connected bss + * description. In hidden ssid case the SSID IE has 0 length + * and the host receives unicast probe with SSID of the + * AP in the roam synch indication. So SSID mismatch happens + * and validation fails. So fetch if the connected bss + * description has hidden ssid, fill the ssid from the + * csr_session connected_profile structure which will + * have the SSID. + */ + if (!roamed_bss_ies->SSID.present) + goto error; + + if (roamed_bss_ies->SSID.num_ssid != + session->connectedProfile.SSID.length) + goto error; + + is_null_ssid_match = !qdf_mem_cmp(session->connectedProfile.SSID.ssId, + roamed_bss_ies->SSID.ssid, + roamed_bss_ies->SSID.num_ssid); +error: + if (connected_profile_ies) + qdf_mem_free(connected_profile_ies); + + return is_null_ssid_match; +} + static QDF_STATUS csr_roam_stop_network(struct mac_context *mac, uint32_t sessionId, struct csr_roam_profile *roam_profile, @@ -5134,6 +5202,7 @@ QDF_STATUS csr_roam_stop_network(struct mac_context *mac, uint32_t sessionId, QDF_STATUS status; struct bss_config_param *pBssConfig; struct csr_roam_session *pSession = CSR_GET_SESSION(mac, sessionId); + bool ssid_match; if (!pSession) { sme_err("session %d not found", sessionId); @@ -5175,10 +5244,16 @@ QDF_STATUS csr_roam_stop_network(struct mac_context *mac, uint32_t sessionId, * (roaming to a new SSID)... * Not worry about WDS connection for now */ + ssid_match = + csr_check_for_hidden_ssid_match(mac, pSession, + bss_desc, pIes); + if (!ssid_match) + ssid_match = csr_is_ssid_equal( + mac, pSession->pConnectBssDesc, + bss_desc, pIes); + if (bss_desc && - (csr_is_ibss_bss_desc(bss_desc) || - !csr_is_ssid_equal(mac, pSession->pConnectBssDesc, - bss_desc, pIes))) + (csr_is_ibss_bss_desc(bss_desc) || !ssid_match)) status = csr_roam_issue_disassociate(mac, sessionId, substate, false); else if (bss_desc)