blob: de81060fb962b62173a4edc058822669dab1adda [file] [log] [blame]
/*
* Copyright (c) 2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "aniGlobal.h"
#include "smeInside.h"
#include "csrInsideApi.h"
#include "smsDebug.h"
#include "macTrace.h"
#include "csrNeighborRoam.h"
#include "csr_roam_mbb.h"
#include "csrInternal.h"
#include "wlan_qct_wda.h"
eHalStatus csr_register_roaming_mbb_callback(tpAniSirGlobal mac);
#define PREAUTH_REASSOC_MBB_TIMER_VALUE 60
#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState)\
{\
mac->roam.neighborRoamInfo.prevNeighborRoamState = mac->roam.neighborRoamInfo.neighborRoamState;\
mac->roam.neighborRoamInfo.neighborRoamState = newState;\
VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, \
FL("Neighbor Roam Transition from state %s ==> %s"), \
csrNeighborRoamStateToString (mac->roam.neighborRoamInfo.prevNeighborRoamState), \
csrNeighborRoamStateToString (newState));\
}
/**
* csr_roam_issue_preauth_reassoc_req() -Prepares preauth request
* @hal: HAL context
* @session_id: session id
* @bss_description: BSS description
*
* This function prepares preauth request and sends request to PE
*
* Return: eHAL_STATUS_SUCCESS on success,
* : eHAL_STATUS_RESOURCES when resource allocation is failure
* : eHAL_STATUS_FAILURE otherwise
*/
eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal,
tANI_U32 session_id, tpSirBssDescription bss_description)
{
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tpSirFTPreAuthReq pre_auth_req;
tANI_U16 auth_req_len = 0;
tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id);
tpCsrNeighborRoamControlInfo neighbor_roam_info =
&mac->roam.neighborRoamInfo;
eHalStatus status;
if (session == NULL) {
smsLog(mac, LOGE, FL("Invalid Session ID %d"), session_id);
return eHAL_STATUS_FAILURE;
}
auth_req_len = sizeof(tSirFTPreAuthReq);
pre_auth_req = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len);
if (NULL == pre_auth_req) {
smsLog(mac, LOGE,
FL("Memory allocation for Preauth request failed"));
return eHAL_STATUS_RESOURCES;
}
/*
* If neighborRoamState is eCSR_NEIGHBOR_ROAM_STATE_INIT
* by the time this API is invoked, disconnect would have happened.
* So, need to proceed further.
*/
if (mac->roam.neighborRoamInfo.neighborRoamState ==
eCSR_NEIGHBOR_ROAM_STATE_INIT) {
smsLog(mac, LOGE, FL("neighborRoamState %d"),
mac->roam.neighborRoamInfo.neighborRoamState);
return eHAL_STATUS_FAILURE;
}
/*
* Save the SME Session ID here. We need it while processing
* the preauth response.
*/
mac->ft.ftSmeContext.smeSessionId = session_id;
vos_mem_zero(pre_auth_req, auth_req_len);
pre_auth_req->pbssDescription = (tpSirBssDescription)vos_mem_malloc(
sizeof(bss_description->length) + bss_description->length);
if (NULL == pre_auth_req->pbssDescription) {
smsLog(mac, LOGE,
FL("Unable to allocate memory for preauth bss description"));
return eHAL_STATUS_RESOURCES;
}
pre_auth_req->messageType =
pal_cpu_to_be16(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ);
pre_auth_req->preAuthchannelNum = bss_description->channelId;
vos_mem_copy((void *)&pre_auth_req->currbssId,
(void *)session->connectedProfile.bssid, sizeof(tSirMacAddr));
vos_mem_copy((void *)&pre_auth_req->preAuthbssId,
(void *)bss_description->bssId, sizeof(tSirMacAddr));
vos_mem_copy(pre_auth_req->pbssDescription, bss_description,
sizeof(bss_description->length) + bss_description->length);
pre_auth_req->length = pal_cpu_to_be16(auth_req_len);
/* Register mbb callback */
smsLog(mac, LOG1, FL("Registering mbb callback"));
csr_register_roaming_mbb_callback(mac);
csrReleaseProfile(mac, &neighbor_roam_info->csrNeighborRoamProfile);
/* Copy current profile to be used in csr_update_roamed_info_mbb */
status = csrRoamCopyProfile(mac,
&neighbor_roam_info->csrNeighborRoamProfile,
session->pCurRoamProfile);
if(!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE, FL("Profile copy failed"));
return status;
}
return palSendMBMessage(mac->hHdd, pre_auth_req);
}
/**
* csr_neighbor_roam_issue_preauth_reassoc() -issues preauth_reassoc request
* @mac: MAC context
*
* This function issues preauth_reassoc request to PE with the 1st AP
* entry in the roamable AP list
*
* Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
*/
eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac)
{
tpCsrNeighborRoamControlInfo neighbor_roam_info =
&mac->roam.neighborRoamInfo;
eHalStatus status = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamBSSInfo neighbor_bss_node;
tCsrRoamInfo roam_info;
VOS_ASSERT(neighbor_roam_info->FTRoamInfo.preauthRspPending ==
eANI_BOOLEAN_FALSE);
neighbor_bss_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
&neighbor_roam_info->roamableAPList, NULL);
if (neighbor_bss_node == NULL)
{
smsLog(mac, LOGE, FL("Roamable AP list is empty"));
csrRoamOffloadScan(mac, ROAM_SCAN_OFFLOAD_RESTART,
REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW);
return eHAL_STATUS_FAILURE;
}
else
{
/*
* Set is_preauth_lfr_mbb which will be checked in
* different API's.
*/
mac->ft.ftSmeContext.is_preauth_lfr_mbb = true;
smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
mac->ft.ftSmeContext.is_preauth_lfr_mbb);
status = csrRoamEnqueuePreauth(mac,
neighbor_roam_info->csrSessionId,
neighbor_bss_node->pBssDescription,
ecsr_mbb_perform_preauth_reassoc,
eANI_BOOLEAN_TRUE);
smsLog(mac, LOG1, FL("Before Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"),
MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId),
neighbor_bss_node->pBssDescription->channelId);
if (eHAL_STATUS_SUCCESS != status)
{
smsLog(mac, LOGE,
FL("Send Preauth request to PE failed with status %d"),
status);
return status;
}
}
neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE;
CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)
if (csrRoamIsFastRoamEnabled(mac, CSR_SESSION_ID_INVALID))
{
smsLog(mac, LOG1, FL("Invoking eCSR_ROAM_PMK_NOTIFY"));
vos_mem_copy((void *)&roam_info.bssid,
(void *)neighbor_bss_node->pBssDescription->bssId,
sizeof(tCsrBssid));
csrRoamCallCallback(mac, neighbor_roam_info->csrSessionId, &roam_info,
0, eCSR_ROAM_PMK_NOTIFY, 0);
}
return status;
}
/**
* csr_stop_preauth_reassoc_mbb_timer() -stops preauth_reassoc timer
* @mac: MAC context
*
* This function stops preauth_reassoc timer
*
*/
void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac)
{
VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
if (mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started) {
vos_status =
vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer);
mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started =
false;
}
}
/**
* csr_preauth_reassoc_mbb_timer_callback() -preauth_reassoc timer callback
* @mac: MAC context
*
* This function issues preauth_reassoc with another roamable entry
*
*/
void csr_preauth_reassoc_mbb_timer_callback(void *context)
{
tpAniSirGlobal mac = (tpAniSirGlobal)context;
mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = 0;
smsLog(mac, LOG1, FL("is_pre_auth_reassoc_mbb_timer_started %d"),
mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started);
csr_neighbor_roam_issue_preauth_reassoc(mac);
}
/**
* csr_roam_dequeue_preauth_reassoc() -Dequeues
* ecsr_mbb_perform_preauth_reassoc
* @mac: MAC context
*
* This function dequeues ecsr_mbb_perform_preauth_reassoc
*
*/
eHalStatus csr_roam_dequeue_preauth_reassoc(tpAniSirGlobal mac)
{
tListElem *entry;
tSmeCmd *command;
entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
if (entry) {
command = GET_BASE_ADDR(entry, tSmeCmd, Link);
if ((eSmeCommandRoam == command->command) &&
(ecsr_mbb_perform_preauth_reassoc ==
command->u.roamCmd.roamReason)) {
smsLog(mac, LOG1, FL("DQ-Command = %d, Reason = %d"),
command->command, command->u.roamCmd.roamReason);
if (csrLLRemoveEntry( &mac->sme.smeCmdActiveList,
entry, LL_ACCESS_LOCK)) {
csrReleaseCommandPreauth( mac, command );
}
} else {
smsLog(mac, LOGE, FL("Command = %d, Reason = %d "),
command->command, command->u.roamCmd.roamReason);
}
}
else {
smsLog(mac, LOGE,
FL("pEntry NULL for eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP"));
}
smeProcessPendingQueue( mac );
return eHAL_STATUS_SUCCESS;
}
/**
* csr_neighbor_roam_preauth_reassoc_rsp_handler() -handles preauth
* reassoc response
* @mac: MAC context
* @lim_status: status of preauth reassoc response from lim
* @bss_description: bss description pointer
*
* This function handles preauth_reassoc response from PE. When
* preauth_reassoc response failure is received, preauth reassoc
* with new candidate will be attempted. In success case, candidate will be
* removed from roamable entry.
*
*/
eHalStatus
csr_neighbor_roam_preauth_reassoc_rsp_handler(tpAniSirGlobal mac,
tSirRetStatus lim_status, tSirBssDescription **bss_description)
{
tpCsrNeighborRoamControlInfo neighbor_roam_info =
&mac->roam.neighborRoamInfo;
eHalStatus status = eHAL_STATUS_SUCCESS;
eHalStatus preauth_processed = eHAL_STATUS_SUCCESS;
tpCsrNeighborRoamBSSInfo preauth_rsp_node = NULL;
if (eANI_BOOLEAN_FALSE ==
neighbor_roam_info->FTRoamInfo.preauthRspPending) {
/*
* This can happen when we disconnect immediately after sending
* a pre-auth request. During processing of the disconnect command,
* we would have reset preauthRspPending and transitioned to INIT state.
*/
smsLog(mac, LOGE,
FL("Unexpected pre-auth response in state %d"),
neighbor_roam_info->neighborRoamState);
preauth_processed = eHAL_STATUS_FAILURE;
goto DEQ_PREAUTH;
}
if ((neighbor_roam_info->neighborRoamState !=
eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)) {
smsLog(mac, LOGE,
FL("Preauth response received in state %s"),
macTraceGetNeighbourRoamState(
neighbor_roam_info->neighborRoamState));
preauth_processed = eHAL_STATUS_FAILURE;
goto DEQ_PREAUTH;
}
neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE;
if (eSIR_SUCCESS == lim_status)
preauth_rsp_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
&neighbor_roam_info->roamableAPList, NULL);
if ((eSIR_SUCCESS == lim_status) && (NULL != preauth_rsp_node)) {
smsLog(mac, LOG1, FL("MBB Reassoc completed successfully"));
smsLog(mac, LOG1, FL("After MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"),
MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId),
preauth_rsp_node->pBssDescription->channelId);
/* Memory will be freed in caller of this */
*bss_description = (tpSirBssDescription)vos_mem_malloc(
sizeof(preauth_rsp_node->pBssDescription->length) +
preauth_rsp_node->pBssDescription->length);
if (NULL == *bss_description) {
smsLog(mac, LOGE,
FL("Unable to allocate memory for preauth bss description"));
preauth_processed = eHAL_STATUS_RESOURCES;
goto DEQ_PREAUTH;
}
vos_mem_copy(*bss_description, preauth_rsp_node->pBssDescription,
sizeof(preauth_rsp_node->pBssDescription->length) +
preauth_rsp_node->pBssDescription->length);
/*
* MBB Reassoc competer successfully. Insert the preauthenticated
* node to tail of preAuthDoneList
*/
csrNeighborRoamRemoveRoamableAPListEntry(mac,
&neighbor_roam_info->roamableAPList, preauth_rsp_node);
csrLLInsertTail(&neighbor_roam_info->FTRoamInfo.preAuthDoneList,
&preauth_rsp_node->List, LL_ACCESS_LOCK);
return eHAL_STATUS_SUCCESS;
} else {
tpCsrNeighborRoamBSSInfo neighbor_bss_node = NULL;
tListElem *entry;
/*
* Pre-auth failed. Add the bssId to the preAuth failed list MAC Address.
* Also remove the AP from roamable AP list. The one in the head of the
* list should be one with which we issued pre-auth and failed.
*/
entry = csrLLRemoveHead(&neighbor_roam_info->roamableAPList,
LL_ACCESS_LOCK);
if(entry) {
neighbor_bss_node = GET_BASE_ADDR(entry,
tCsrNeighborRoamBSSInfo, List);
/*
* Add the BSSID to pre-auth fail list if it is
* not requested by HDD
*/
status = csrNeighborRoamAddBssIdToPreauthFailList(mac,
neighbor_bss_node->pBssDescription->bssId);
smsLog(mac, LOG1,
FL("MBB reassoc failed BSSID "MAC_ADDRESS_STR" Ch:%d status %d"),
MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId),
neighbor_bss_node->pBssDescription->channelId, lim_status);
/* Now we can free this node */
csrNeighborRoamFreeNeighborRoamBSSNode(mac, neighbor_bss_node);
}
/*
* Move state to Connected. Connected state here signifies connection
* with current AP as preauth failed with roamable AP. Still driver has
* connection with current AP.
*/
CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
/* Start a timer to issue preauth_reassoc request for the next entry*/
status = vos_timer_start(&mac->ft.ftSmeContext.
pre_auth_reassoc_mbb_timer, PREAUTH_REASSOC_MBB_TIMER_VALUE);
if (eHAL_STATUS_SUCCESS != status) {
smsLog(mac, LOGE,
FL("pre_auth_reassoc_mbb_timer start failed status %d"),
status);
preauth_processed = eHAL_STATUS_FAILURE;
goto DEQ_PREAUTH;
}
mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = true;
smsLog(mac, LOG1, FL("is_pre_auth_reassoc_mbb_timer_started %d"),
mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started);
preauth_processed = eHAL_STATUS_SUCCESS;
}
DEQ_PREAUTH:
csr_roam_dequeue_preauth_reassoc(mac);
return preauth_processed;
}
eHalStatus csr_update_roamed_info_mbb(tHalHandle hal,
tpSirBssDescription bss_description, tpSirFTPreAuthRsp pre_auth_rsp)
{
eHalStatus status;
tpAniSirGlobal mac = PMAC_STRUCT(hal);
tDot11fBeaconIEs *ies_local = NULL;
tCsrRoamSession *session = NULL;
tCsrRoamProfile *profile;
tSirMacAddr broadcast_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
tANI_U32 key_timeout_interval;
tCsrRoamInfo roam_info;
sme_QosAssocInfo assoc_info;
tANI_U32 len;
tANI_U8 sme_session_id = pre_auth_rsp->smeSessionId;
tANI_U8 acm_mask = 0;
/* Get profile */
session = CSR_GET_SESSION(mac, sme_session_id);
if (session == NULL) {
smsLog(mac, LOGE,
FL("Invalid Session ID %d"), sme_session_id);
return eHAL_STATUS_FAILURE;
}
profile = vos_mem_malloc(sizeof(*profile));
if (NULL == profile) {
smsLog(mac, LOGE, FL("Memory allocation failure for profile"));
return eHAL_STATUS_FAILURE;
}
/*
* session->pCurRoamProfile is copied into csrNeighborRoamProfile
* in csr_roam_issue_preauth_reassoc_req as there is a chance of
* session->pCurRoamProfile getting freed when disconnect is issued
* from upper layer.
*/
status = csrRoamCopyProfile(mac, profile,
&mac->roam.neighborRoamInfo.csrNeighborRoamProfile);
if(!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE, FL("Profile copy failed"));
vos_mem_free(profile);
return status;
}
profile->negotiatedAuthType =
mac->roam.roamSession[sme_session_id].connectedProfile.AuthType;
profile->negotiatedUCEncryptionType =
mac->roam.roamSession[sme_session_id].connectedProfile.EncryptionType;
profile->mcEncryptionType =
mac->roam.roamSession[sme_session_id].connectedProfile.mcEncryptionInfo;
profile->negotiatedMCEncryptionType =
mac->roam.roamSession[sme_session_id].connectedProfile.mcEncryptionType;
smsLog(mac, LOG1,
FL("AuthType %d UCEType %d Entries %d encryptionType %d MCEType %d"),
profile->negotiatedAuthType,
profile->negotiatedUCEncryptionType,
profile->mcEncryptionType.numEntries,
profile->mcEncryptionType.encryptionType[0],
profile->negotiatedMCEncryptionType);
/* Get IE's */
status = csrGetParsedBssDescriptionIEs(mac, bss_description, &ies_local);
if (!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE,
FL("csrGetParsedBssDescriptionIEs failed"));
vos_mem_free(profile);
return status;
}
if(ies_local == NULL) {
smsLog(mac, LOGE,
FL("ies_local is NULL "));
vos_mem_free(profile);
return eHAL_STATUS_FAILURE;
}
vos_mem_set(&roam_info, sizeof(roam_info), 0);
csrRoamStopNetwork(mac, sme_session_id, profile,
bss_description, ies_local);
session->connectState = eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED;
csrRoamSaveConnectedInfomation(mac, sme_session_id, profile,
bss_description, ies_local);
csrRoamSaveSecurityRspIE(mac, sme_session_id,
profile->negotiatedAuthType, bss_description,
ies_local);
csrRoamStateChange(mac, eCSR_ROAMING_STATE_JOINED, sme_session_id);
/*
* If abortConnection is set, it implies that disconnect in progress
* from upper layer. So there is no point in proceeding further.
* By this point, pConnectBssDesc is updated in
* csrRoamSaveConnectedInfomation. This pConnectBssDesc is used
* during processing of disconnect in CSR and this has new BSSID info.
* By this time, original AP related info was cleaned up in LIM. So,
* disconnect queued while roaming in progress will take care of
* cleaning up roamed AP related info in LIM.
*/
if (session->abortConnection) {
smsLog(mac, LOGE, FL("Disconnect in progress"));
smsLog(mac, LOGE, FL("MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"),
MAC_ADDR_ARRAY(bss_description->bssId),
bss_description->channelId);
vos_mem_free(profile);
return eHAL_STATUS_FAILURE;
}
if(CSR_IS_ENC_TYPE_STATIC(profile->negotiatedUCEncryptionType) &&
!profile->bWPSAssociation) {
/*
* Issue the set Context request to LIM to establish the
* Unicast STA context
*/
if(!HAL_STATUS_SUCCESS(csrRoamIssueSetContextReq(mac,
sme_session_id,
profile->negotiatedUCEncryptionType,
bss_description, &(bss_description->bssId), FALSE, TRUE,
eSIR_TX_RX, 0, 0, NULL, 0))) {
smsLog(mac, LOGE, FL("Set context for unicast fail"));
csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_NONE,
sme_session_id);
}
/*
* Issue the set Context request to LIM to establish the
* Broadcast STA context
*/
csrRoamIssueSetContextReq(mac, sme_session_id,
profile->negotiatedMCEncryptionType,
bss_description, &broadcast_mac,
FALSE, FALSE, eSIR_TX_RX, 0, 0, NULL, 0);
} else if (!session->abortConnection) {
/* Need to wait for supplicant authtication */
roam_info.fAuthRequired = eANI_BOOLEAN_TRUE;
/* Set the subestate to WaitForKey in case authentiation is needed */
csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_WAIT_FOR_KEY,
sme_session_id);
if(profile->bWPSAssociation)
key_timeout_interval = CSR_WAIT_FOR_WPS_KEY_TIMEOUT_PERIOD;
else
key_timeout_interval = CSR_WAIT_FOR_KEY_TIMEOUT_PERIOD;
/* Save sessionId in case of timeout */
mac->roam.WaitForKeyTimerInfo.sessionId = sme_session_id;
/*
* This time should be long enough for the rest of the
* process plus setting key
*/
if(!HAL_STATUS_SUCCESS(csrRoamStartWaitForKeyTimer(mac,
key_timeout_interval))) {
/* Reset our state so nothting is blocked */
smsLog(mac, LOGE, FL("Failed to start pre-auth timer"));
csrRoamSubstateChange(mac, eCSR_ROAM_SUBSTATE_NONE,
sme_session_id);
}
}
csrRoamFreeConnectedInfo(mac, &session->connectedInfo);
assoc_info.pBssDesc = bss_description;
assoc_info.pProfile = profile;
len = pre_auth_rsp->roam_info->nBeaconLength +
pre_auth_rsp->roam_info->nAssocReqLength +
pre_auth_rsp->roam_info->nAssocRspLength;
if(len) {
session->connectedInfo.pbFrames = vos_mem_malloc(len);
if (session->connectedInfo.pbFrames != NULL ) {
vos_mem_copy(session->connectedInfo.pbFrames,
pre_auth_rsp->roam_info->pbFrames, len);
session->connectedInfo.nAssocReqLength =
pre_auth_rsp->roam_info->nAssocReqLength;
session->connectedInfo.nAssocRspLength =
pre_auth_rsp->roam_info->nAssocRspLength;
session->connectedInfo.nBeaconLength =
pre_auth_rsp->roam_info->nBeaconLength;
roam_info.nAssocReqLength = pre_auth_rsp->roam_info->nAssocReqLength;
roam_info.nAssocRspLength = pre_auth_rsp->roam_info->nAssocRspLength;
roam_info.nBeaconLength = pre_auth_rsp->roam_info->nBeaconLength;
roam_info.pbFrames = session->connectedInfo.pbFrames;
}
session->connectedInfo.staId = pre_auth_rsp->roam_info->staId;
roam_info.staId = pre_auth_rsp->roam_info->staId;
roam_info.ucastSig = pre_auth_rsp->roam_info->ucastSig;
roam_info.bcastSig = pre_auth_rsp->roam_info->bcastSig;
roam_info.maxRateFlags = pre_auth_rsp->roam_info->maxRateFlags;
}
roam_info.statusCode = eSIR_SME_SUCCESS;
roam_info.reasonCode = eSIR_SME_SUCCESS;
roam_info.pBssDesc = bss_description;
vos_mem_copy(&roam_info.bssid, &bss_description->bssId,
sizeof(tCsrBssid));
mac->roam.roamSession[sme_session_id].connectState =
eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED;
sme_QosCsrEventInd(mac, sme_session_id,
SME_QOS_CSR_HANDOFF_ASSOC_REQ, NULL);
sme_QosCsrEventInd(mac, sme_session_id, SME_QOS_CSR_REASSOC_REQ, NULL);
sme_QosCsrEventInd(mac, sme_session_id, SME_QOS_CSR_HANDOFF_COMPLETE, NULL);
mac->roam.roamSession[sme_session_id].connectState =
eCSR_ASSOC_STATE_TYPE_INFRA_ASSOCIATED;
sme_QosCsrEventInd(mac, sme_session_id,
SME_QOS_CSR_REASSOC_COMPLETE, &assoc_info);
acm_mask = sme_QosGetACMMask(mac, bss_description, NULL);
session->connectedProfile.acm_mask = acm_mask;
if(session->connectedProfile.modifyProfileFields.uapsd_mask) {
smsLog(mac, LOGE, "uapsd_mask (0x%X) set, request UAPSD now",
session->connectedProfile.modifyProfileFields.uapsd_mask);
pmcStartUapsd(mac, NULL, NULL);
}
session->connectedProfile.dot11Mode = session->bssParams.uCfgDot11Mode;
roam_info.u.pConnectedProfile = &session->connectedProfile;
if(!IS_FEATURE_SUPPORTED_BY_FW(SLM_SESSIONIZATION) &&
(csrIsConcurrentSessionRunning(mac)))
mac->roam.configParam.doBMPSWorkaround = 1;
csr_roam_dequeue_preauth_reassoc(mac);
csrRoamCallCallback(mac, sme_session_id, &roam_info, 0,
eCSR_ROAM_ASSOCIATION_COMPLETION, eCSR_ROAM_RESULT_ASSOCIATED);
csrResetPMKIDCandidateList(mac, sme_session_id);
#ifdef FEATURE_WLAN_WAPI
csrResetBKIDCandidateList(mac, sme_session_id);
#endif
if(!CSR_IS_WAIT_FOR_KEY(mac, sme_session_id)) {
smsLog(mac, LOG1, "NO CSR_IS_WAIT_FOR_KEY -> csr_roam_link_up");
csrRoamLinkUp(mac, session->connectedProfile.bssid);
}
if (pmcShouldBmpsTimerRun(mac)) {
if(eANI_BOOLEAN_TRUE == roam_info.fAuthRequired) {
mac->pmc.full_power_till_set_key = true;
smsLog(mac, LOG1,
FL("full_power_till_set_key is made true"));
}
if (pmcStartTrafficTimer(mac, BMPS_TRAFFIC_TIMER_ALLOW_SECURITY_DHCP)
!= eHAL_STATUS_SUCCESS)
smsLog(mac, LOGE, FL("Cannot start BMPS Retry timer"));
smsLog(mac, LOG1, FL("BMPS Retry Timer already running or started"));
}
vos_mem_free(pre_auth_rsp->roam_info->pbFrames);
vos_mem_free(pre_auth_rsp->roam_info);
vos_mem_free(profile);
vos_mem_free(ies_local);
return eHAL_STATUS_SUCCESS;
}
/**
* csr_roam_preauth_rsp_mbb_processor() -handles
* eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP
* @hal: HAL context
*
* This function invokes preauth reassoc response handler and
* updates CSR with new connection information.
*
*/
void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal,
tpSirFTPreAuthRsp pre_auth_rsp)
{
tpAniSirGlobal mac = PMAC_STRUCT(hal);
eHalStatus status;
tCsrRoamInfo roam_info;
tpSirBssDescription bss_description = NULL;
tCsrRoamSession *session = NULL;
mac->ft.ftSmeContext.is_preauth_lfr_mbb = false;
smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
mac->ft.ftSmeContext.is_preauth_lfr_mbb);
/*
* When reason is SIR_MBB_DISCONNECTED, cleanup CSR info
* of connected AP.
*/
if (pre_auth_rsp->reason == SIR_MBB_DISCONNECTED) {
/* Dequeue ecsr_perform_preauth_reassoc */
csr_roam_dequeue_preauth_reassoc(mac);
vos_mem_zero(&roam_info, sizeof(tCsrRoamInfo));
csrRoamCallCallback(mac, pre_auth_rsp->smeSessionId, &roam_info, 0,
eCSR_ROAM_FT_REASSOC_FAILED, eSIR_SME_SUCCESS);
csrRoamComplete(mac, eCsrJoinFailure, NULL);
}
status = csr_neighbor_roam_preauth_reassoc_rsp_handler(mac,
pre_auth_rsp->status, &bss_description);
if (status != eHAL_STATUS_SUCCESS) {
smsLog(mac, LOGE,FL("Preauth was not processed: %d SessionID: %d"),
status, pre_auth_rsp->smeSessionId);
/*
* Preauth_reassoc is dequeued already in
* csr_neighbor_roam_preauth_reassoc_rsp_handler for error cases.
*/
return;
}
session = CSR_GET_SESSION(mac, pre_auth_rsp->smeSessionId);
if (session == NULL) {
smsLog(mac, LOGE,
FL("Invalid Session ID %d"), pre_auth_rsp->smeSessionId);
return;
}
if (session->abortConnection) {
smsLog(mac, LOGE,
FL("Disconnect in progress, stop preauth/reassoc timer"));
vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer);
}
/*
* The below function calls/timers should be invoked only
* if the pre-auth is successful. Also, Preauth_reassoc is dequeued
* already in csr_neighbor_roam_preauth_reassoc_rsp_handler.
*/
if (VOS_STATUS_SUCCESS != (VOS_STATUS)pre_auth_rsp->status)
return;
mac->ft.ftSmeContext.FTState = eFT_AUTH_COMPLETE;
/* Save the received response */
vos_mem_copy((void *)&mac->ft.ftSmeContext.preAuthbssId,
(void *)pre_auth_rsp->preAuthbssId, sizeof(tCsrBssid));
/*
* bss_description is updated in
* csr_neighbor_roam_preauth_reassoc_rsp_handler
*/
if (NULL == bss_description) {
smsLog(mac, LOGE,
FL("bss description is NULL"));
goto DEQ_PREAUTH;
}
/* Update CSR for new connection */
status = csr_update_roamed_info_mbb(hal, bss_description, pre_auth_rsp);
/* In success case preauth reassoc is dequeued in
* csr_update_roamed_info_mbb before updating HDD.
*/
if(HAL_STATUS_SUCCESS(status))
return;
DEQ_PREAUTH:
csr_roam_dequeue_preauth_reassoc(mac);
}
/**
* csr_prepare_reassoc_req () - Prepares reassoc request
* @pmac: MAC context
* @session_id: session id
* @pbss_description: bss description
* @preassoc_req: pointer to reassociation request
*
*Return: None
*/
static void csr_prepare_reassoc_req(void* pmac, tANI_U32 session_id,
void* pbss_description, void *preassoc_req)
{
tDot11fBeaconIEs *ies_local = NULL;
eHalStatus status;
tpAniSirGlobal mac = (tpAniSirGlobal)pmac;
tpSirBssDescription bss_description = (tpSirBssDescription)pbss_description;
tSirSmeJoinReq **reassoc_req = (tSirSmeJoinReq **)preassoc_req;
/* Get IE's */
status = csrGetParsedBssDescriptionIEs(mac, bss_description, &ies_local);
if (!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE,
FL("csrGetParsedBssDescriptionIEs failed"));
return;
}
if(ies_local == NULL) {
smsLog(mac, LOGE,
FL("ies_local is NULL"));
return;
}
smsLog(mac, LOG1, FL("session_id %d"), session_id);
status = csr_fill_reassoc_req(mac, session_id, bss_description,
ies_local, reassoc_req);
if (!HAL_STATUS_SUCCESS(status)) {
smsLog(mac, LOGE,
FL("Reassociation request filling failed"));
return;
}
vos_mem_free(ies_local);
smsLog(mac, LOG1, FL("status %d"), status);
}
/**
* csr_roaming_mbb_callback () - handles mbb callback
* @pmac: MAC context
* @session_id: session id
* @pbss_description: bss description
* @preassoc_req: pointer to reassociation request
* @csr_roam_op_code: callback opcode
*
*Return: None
*/
static void csr_roaming_mbb_callback(void* pmac, tANI_U32 session_id,
void* pbss_description, void *preassoc_req, tANI_U32 csr_roam_op_code)
{
tpAniSirGlobal mac = (tpAniSirGlobal)pmac;
smsLog(mac, LOG1,
FL("csr_roam_op_code %d"), csr_roam_op_code);
switch(csr_roam_op_code) {
case SIR_ROAMING_DEREGISTER_STA:
csrRoamCallCallback(mac, session_id, NULL, 0,
eCSR_ROAM_FT_START, eSIR_SME_SUCCESS);
break;
case SIR_STOP_ROAM_OFFLOAD_SCAN:
csrRoamOffloadScan(mac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED);
break;
case SIR_PREPARE_REASSOC_REQ:
csr_prepare_reassoc_req(pmac, session_id, pbss_description,
preassoc_req);
break;
}
}
/**
* csr_register_roaming_mbb_callback () - registers roaming callback
* @mac: MAC context
*
*Return: eHAL_STATUS_SUCCESS on success, otherwise failure
*/
eHalStatus csr_register_roaming_mbb_callback(tpAniSirGlobal mac)
{
eHalStatus status;
status = sme_AcquireGlobalLock(&mac->sme);
if (eHAL_STATUS_SUCCESS == status) {
mac->sme.roaming_mbb_callback = csr_roaming_mbb_callback;
sme_ReleaseGlobalLock(&mac->sme);
} else
smsLog(mac, LOGE,
FL("sme_AcquireGlobalLock error"));
return status;
}