From dbbb9919e9ae7d1043ef8205b28f55e37a3a7a54 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Wed, 10 Feb 2016 14:32:50 -0800 Subject: [PATCH] qcacld-3.0: Isolate the pre-authentication code into a new file Move all the pre-authentication related code in LIM to a separate file so that it is feature specific and easy to maintain across different projects CRs-Fixed: 978905 Change-Id: I3ca443139b974b25be8121fd6df040d858693708 --- Kbuild | 1 + core/mac/src/pe/lim/lim_ft.c | 724 +------------------------ core/mac/src/pe/lim/lim_ft_preauth.c | 782 +++++++++++++++++++++++++++ 3 files changed, 785 insertions(+), 722 deletions(-) create mode 100644 core/mac/src/pe/lim/lim_ft_preauth.c diff --git a/Kbuild b/Kbuild index d4ac68b346..7b13789bb1 100755 --- a/Kbuild +++ b/Kbuild @@ -403,6 +403,7 @@ MAC_LIM_OBJS := $(MAC_SRC_DIR)/pe/lim/lim_aid_mgmt.o \ $(MAC_SRC_DIR)/pe/lim/lim_assoc_utils.o \ $(MAC_SRC_DIR)/pe/lim/lim_debug.o \ $(MAC_SRC_DIR)/pe/lim/lim_ft.o \ + $(MAC_SRC_DIR)/pe/lim/lim_ft_preauth.o \ $(MAC_SRC_DIR)/pe/lim/lim_ibss_peer_mgmt.o \ $(MAC_SRC_DIR)/pe/lim/lim_link_monitoring_algo.o \ $(MAC_SRC_DIR)/pe/lim/lim_p2p.o \ diff --git a/core/mac/src/pe/lim/lim_ft.c b/core/mac/src/pe/lim/lim_ft.c index 82f2498359..ad918d2375 100644 --- a/core/mac/src/pe/lim/lim_ft.c +++ b/core/mac/src/pe/lim/lim_ft.c @@ -64,75 +64,6 @@ void lim_ft_open(tpAniSirGlobal pMac, tpPESession psessionEntry) 0); } -/*-------------------------------------------------------------------------- - Cleanup FT variables. - ------------------------------------------------------------------------*/ -void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, tpPESession psessionEntry) -{ - tpPESession pReAssocSessionEntry = NULL; - uint8_t sessionId = 0; - - if (!psessionEntry) { - lim_log(pMac, LOGE, FL("psessionEntry is NULL")); - return; - } - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(psessionEntry)) { - lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); - return; - } - - if (psessionEntry->ftPEContext.pFTPreAuthReq) { - pReAssocSessionEntry = - pe_find_session_by_bssid(pMac, - psessionEntry->ftPEContext. - pFTPreAuthReq->preAuthbssId, - &sessionId); - - lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), - psessionEntry->ftPEContext.pFTPreAuthReq); - if (psessionEntry->ftPEContext.pFTPreAuthReq-> - pbssDescription) { - qdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq-> - pbssDescription); - psessionEntry->ftPEContext.pFTPreAuthReq-> - pbssDescription = NULL; - } - qdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); - psessionEntry->ftPEContext.pFTPreAuthReq = NULL; - } - - if (psessionEntry->ftPEContext.pAddBssReq) { - qdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); - psessionEntry->ftPEContext.pAddBssReq = NULL; - } - - if (psessionEntry->ftPEContext.pAddStaReq) { - qdf_mem_free(psessionEntry->ftPEContext.pAddStaReq); - psessionEntry->ftPEContext.pAddStaReq = NULL; - } - - /* The session is being deleted, cleanup the contents */ - qdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); - - /* Delete the session created while handling pre-auth response */ - if (pReAssocSessionEntry) { - /* If we have successful pre-auth response, then we would have - * created a session on which reassoc request will be sent - */ - if (pReAssocSessionEntry->valid && - pReAssocSessionEntry->limSmeState == - eLIM_SME_WT_REASSOC_STATE) { - QDF_TRACE(QDF_MODULE_ID_PE, - QDF_TRACE_LEVEL_DEBUG, - FL("Deleting Preauth session(%d)"), - pReAssocSessionEntry->peSessionId); - pe_delete_session(pMac, pReAssocSessionEntry); - } - } -} - void lim_ft_cleanup_all_ft_sessions(tpAniSirGlobal pMac) { /* Wrapper function to cleanup all FT sessions */ @@ -188,186 +119,6 @@ void lim_ft_cleanup(tpAniSirGlobal pMac, tpPESession psessionEntry) qdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); } -/* - * lim_process_ft_pre_auth_req() - process ft pre auth req - * - * @mac_ctx: global mac ctx - * @msg: pointer to message - * - * In this function, we process the FT Pre Auth Req: - * We receive Pre-Auth, suspend link, register a call back. In the call back, - * we will need to accept frames from the new bssid. Send out the auth req to - * new AP. Start timer and when the timer is done or if we receive the Auth - * response. We change channel. Resume link - * - * Return: value to indicate if buffer was consumed - */ -int lim_process_ft_pre_auth_req(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) -{ - int buf_consumed = false; - tpPESession session; - uint8_t session_id; - tpSirFTPreAuthReq ft_pre_auth_req = (tSirFTPreAuthReq *) msg->bodyptr; - - if (NULL == ft_pre_auth_req) { - lim_log(mac_ctx, LOGE, FL("tSirFTPreAuthReq is NULL")); - return buf_consumed; - } - - /* Get the current session entry */ - session = pe_find_session_by_bssid(mac_ctx, - ft_pre_auth_req->currbssId, - &session_id); - if (session == NULL) { - lim_log(mac_ctx, LOGE, - FL("Unable to find session for the bssid" - MAC_ADDRESS_STR), - MAC_ADDR_ARRAY(ft_pre_auth_req->currbssId)); - /* Post the FT Pre Auth Response to SME */ - lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, - session); - /* - * return FALSE, since the Pre-Auth Req will be freed in - * limPostFTPreAuthRsp on failure - */ - return buf_consumed; - } - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(session)) { - lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); - buf_consumed = true; - return buf_consumed; - } - - /* Can set it only after sending auth */ - session->ftPEContext.ftPreAuthStatus = eSIR_FAILURE; - session->ftPEContext.ftPreAuthSession = true; - - /* Indicate that this is the session on which preauth is being done */ - if (session->ftPEContext.pFTPreAuthReq) { - if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { - qdf_mem_free( - session->ftPEContext.pFTPreAuthReq->pbssDescription); - session->ftPEContext.pFTPreAuthReq->pbssDescription = - NULL; - } - qdf_mem_free(session->ftPEContext.pFTPreAuthReq); - session->ftPEContext.pFTPreAuthReq = NULL; - } - - /* We need information from the Pre-Auth Req. Lets save that */ - session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req; - - lim_log(mac_ctx, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"), - session->ftPEContext.pFTPreAuthReq->ft_ies[0], - session->ftPEContext.pFTPreAuthReq->ft_ies[1], - session->ftPEContext.pFTPreAuthReq->ft_ies[2]); -#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ - lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, - session, 0, 0); -#endif - - /* Dont need to suspend if APs are in same channel */ - if (session->currentOperChannel != - session->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { - /* Need to suspend link only if the channels are different */ - lim_log(mac_ctx, LOG2, - FL("Performing pre-auth on diff channel(session %p)"), - session); - lim_send_preauth_scan_offload(mac_ctx, session->peSessionId, - session->ftPEContext.pFTPreAuthReq); - } else { - lim_log(mac_ctx, LOG2, - FL("Performing pre-auth on same channel (session %p)"), - session); - /* We are in the same channel. Perform pre-auth */ - lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, - session); - } - - return buf_consumed; -} - -/*------------------------------------------------------------------ - * Send the Auth1 - * Receive back Auth2 - *------------------------------------------------------------------*/ -void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, QDF_STATUS status, - uint32_t *data, tpPESession psessionEntry) -{ - tSirMacAuthFrameBody authFrame; - - if (NULL == psessionEntry) { - PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL"));) - return; - } - - if (psessionEntry->is11Rconnection && - psessionEntry->ftPEContext.pFTPreAuthReq) { - /* Only 11r assoc has FT IEs */ - if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies == NULL) { - lim_log(pMac, LOGE, - FL("FTIEs for Auth Req Seq 1 is absent")); - goto preauth_fail; - } - } - - if (status != QDF_STATUS_SUCCESS) { - lim_log(pMac, LOGE, - FL(" Change channel not successful for FT pre-auth")); - goto preauth_fail; - } - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(psessionEntry)) { - lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); - return; - } - lim_log(pMac, LOG2, "Entered wait auth2 state for FT (old session %p)", - psessionEntry); - if (psessionEntry->is11Rconnection) { - /* Now we are on the right channel and need to send out Auth1 and - * receive Auth2 - */ - authFrame.authAlgoNumber = eSIR_FT_AUTH; - } else { - /* Will need to make isESEconnection a enum may be for further - * improvements to this to match this algorithm number - */ - authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM; - } - authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; - authFrame.authStatusCode = 0; - - /* Start timer here to come back to operating channel */ - pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId = - psessionEntry->peSessionId; - if (TX_SUCCESS != - tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) { - lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed")); - goto preauth_fail; - } - MTRACE(mac_trace(pMac, TRACE_CODE_TIMER_ACTIVATE, - psessionEntry->peSessionId, eLIM_FT_PREAUTH_RSP_TIMER)); - - lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started")); -#ifdef FEATURE_WLAN_DIAG_SUPPORT - lim_diag_event_report(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, - pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); -#endif - - lim_send_auth_mgmt_frame(pMac, &authFrame, - psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, - LIM_NO_WEP_IN_FC, psessionEntry, false); - - return; - -preauth_fail: - lim_handle_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); - return; -} - /*------------------------------------------------------------------ * * Create the new Add Bss Req to the new AP. @@ -942,272 +693,6 @@ void lim_fill_ft_session(tpAniSirGlobal pMac, qdf_mem_free(pBeaconStruct); } -/*------------------------------------------------------------------ - * - * Setup the session and the add bss req for the pre-auth AP. - * - *------------------------------------------------------------------*/ -tSirRetStatus lim_ft_setup_auth_session(tpAniSirGlobal pMac, - tpPESession psessionEntry) -{ - tpPESession pftSessionEntry = NULL; - uint8_t sessionId = 0; - - pftSessionEntry = - pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId, - &sessionId); - if (pftSessionEntry == NULL) { - PELOGE(lim_log(pMac, LOGE, - FL - ("Unable to find session for the following bssid")); - ) - lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOGE); - return eSIR_FAILURE; - } - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(psessionEntry)) { - lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); - return eSIR_FAILURE; - } - - if (psessionEntry->ftPEContext.pFTPreAuthReq && - psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { - lim_fill_ft_session(pMac, - psessionEntry->ftPEContext.pFTPreAuthReq-> - pbssDescription, pftSessionEntry, - psessionEntry); - - lim_ft_prepare_add_bss_req(pMac, false, pftSessionEntry, - psessionEntry->ftPEContext.pFTPreAuthReq-> - pbssDescription); - } - - return eSIR_SUCCESS; -} - -/*------------------------------------------------------------------ - * Resume Link Call Back - *------------------------------------------------------------------*/ -void lim_ft_process_pre_auth_result(tpAniSirGlobal pMac, QDF_STATUS status, - tpPESession psessionEntry) -{ - if (NULL == psessionEntry || - NULL == psessionEntry->ftPEContext.pFTPreAuthReq) - return; - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(psessionEntry)) { - lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); - return; - } - - if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { - psessionEntry->ftPEContext.ftPreAuthStatus = - lim_ft_setup_auth_session(pMac, psessionEntry); - } - /* Post the FT Pre Auth Response to SME */ - lim_post_ft_pre_auth_rsp(pMac, psessionEntry->ftPEContext.ftPreAuthStatus, - psessionEntry->ftPEContext.saved_auth_rsp, - psessionEntry->ftPEContext.saved_auth_rsp_length, - psessionEntry); -} - -/* - * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME. - * - * @mac_ctx: global mac ctx - * @status: status code to post in auth rsp - * @auth_rsp: pointer to auth rsp FT ie - * @auth_rsp_length: len of the IE field - * @session: pe session - * - * post pre auth response to SME. - * - * Return: void - */ -void lim_post_ft_pre_auth_rsp(tpAniSirGlobal mac_ctx, - tSirRetStatus status, - uint8_t *auth_rsp, - uint16_t auth_rsp_length, - tpPESession session) -{ - tpSirFTPreAuthRsp ft_pre_auth_rsp; - tSirMsgQ mmh_msg; - uint16_t rsp_len = sizeof(tSirFTPreAuthRsp); - - ft_pre_auth_rsp = (tpSirFTPreAuthRsp) qdf_mem_malloc(rsp_len); - if (NULL == ft_pre_auth_rsp) { - lim_log(mac_ctx, LOGE, "Failed to allocate memory"); - QDF_ASSERT(ft_pre_auth_rsp != NULL); - return; - } - qdf_mem_zero(ft_pre_auth_rsp, rsp_len); - - lim_log(mac_ctx, LOG1, FL("Auth Rsp = %p"), ft_pre_auth_rsp); - if (session) { - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(session)) { - lim_log(mac_ctx, LOGE, - FL("session is not in STA mode")); - qdf_mem_free(ft_pre_auth_rsp); - return; - } - ft_pre_auth_rsp->smeSessionId = session->smeSessionId; - /* The bssid of the AP we are sending Auth1 to. */ - if (session->ftPEContext.pFTPreAuthReq) - sir_copy_mac_addr(ft_pre_auth_rsp->preAuthbssId, - session->ftPEContext.pFTPreAuthReq->preAuthbssId); - } - - ft_pre_auth_rsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP; - ft_pre_auth_rsp->length = (uint16_t) rsp_len; - ft_pre_auth_rsp->status = status; - - /* Attach the auth response now back to SME */ - ft_pre_auth_rsp->ft_ies_length = 0; - if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { - /* Only 11r assoc has FT IEs */ - qdf_mem_copy(ft_pre_auth_rsp->ft_ies, - auth_rsp, auth_rsp_length); - ft_pre_auth_rsp->ft_ies_length = auth_rsp_length; - } - - if (status != eSIR_SUCCESS) { - /* - * Ensure that on Pre-Auth failure the cached Pre-Auth Req and - * other allocated memory is freed up before returning. - */ - lim_log(mac_ctx, LOG1, "Pre-Auth Failed, Cleanup!"); - lim_ft_cleanup(mac_ctx, session); - } - - mmh_msg.type = ft_pre_auth_rsp->messageType; - mmh_msg.bodyptr = ft_pre_auth_rsp; - mmh_msg.bodyval = 0; - - lim_log(mac_ctx, LOG1, FL("Posted Auth Rsp to SME with status of 0x%x"), - status); -#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ - if (status == eSIR_SUCCESS) - lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE, - session, status, 0); -#endif - lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); -} - -/*------------------------------------------------------------------ - * - * Send the FT Pre Auth Response to SME whenever we have a status - * ready to be sent to SME - * - * SME will be the one to send it up to the supplicant to receive - * FTIEs which will be required for Reassoc Req. - * - *------------------------------------------------------------------*/ -void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, - uint8_t *auth_rsp, uint16_t auth_rsp_length, - tpPESession psessionEntry) -{ - tpPESession pftSessionEntry = NULL; - uint8_t sessionId = 0; - tpSirBssDescription pbssDescription = NULL; -#ifdef FEATURE_WLAN_DIAG_SUPPORT - lim_diag_event_report(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, - psessionEntry, (uint16_t) status, 0); -#endif - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(psessionEntry)) { - lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); - return; - } - - /* Save the status of pre-auth */ - psessionEntry->ftPEContext.ftPreAuthStatus = status; - - /* Save the auth rsp, so we can send it to - * SME once we resume link - */ - psessionEntry->ftPEContext.saved_auth_rsp_length = 0; - if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { - qdf_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp, - auth_rsp, auth_rsp_length); - psessionEntry->ftPEContext.saved_auth_rsp_length = - auth_rsp_length; - } - - if (!psessionEntry->ftPEContext.pFTPreAuthReq || - !psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { - lim_log(pMac, LOGE, - FL("pFTPreAuthReq or pbssDescription is NULL")); - return; - } - - /* Create FT session for the re-association at this point */ - if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { - pbssDescription = - psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription; - lim_print_mac_addr(pMac, pbssDescription->bssId, LOG1); - pftSessionEntry = - pe_create_session(pMac, pbssDescription->bssId, - &sessionId, pMac->lim.maxStation, - psessionEntry->bssType); - if (pftSessionEntry == NULL) { - lim_log(pMac, LOGE, FL( - "Session not created for pre-auth 11R AP")); - status = eSIR_FAILURE; - psessionEntry->ftPEContext.ftPreAuthStatus = status; - goto send_rsp; - } - pftSessionEntry->peSessionId = sessionId; - pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; - sir_copy_mac_addr(pftSessionEntry->selfMacAddr, - psessionEntry->selfMacAddr); - sir_copy_mac_addr(pftSessionEntry->limReAssocbssId, - pbssDescription->bssId); - pftSessionEntry->bssType = psessionEntry->bssType; - - if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) { - pftSessionEntry->limSystemRole = eLIM_STA_ROLE; - } else if (pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) { - pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; - } else { - lim_log(pMac, LOGE, FL("Invalid bss type")); - } - pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; - qdf_mem_copy(&(pftSessionEntry->htConfig), - &(psessionEntry->htConfig), - sizeof(psessionEntry->htConfig)); - pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; - - PELOGE(lim_log - (pMac, LOG1, "%s:created session (%p) with id = %d", - __func__, pftSessionEntry, - pftSessionEntry->peSessionId); - ) - - /* Update the ReAssoc BSSID of the current session */ - sir_copy_mac_addr(psessionEntry->limReAssocbssId, - pbssDescription->bssId); - lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOG1); - } -send_rsp: - if (psessionEntry->currentOperChannel != - psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { - /* Need to move to the original AP channel */ - lim_process_abort_scan_ind(pMac, psessionEntry->peSessionId, - psessionEntry->ftPEContext.pFTPreAuthReq->scan_id, - PREAUTH_REQUESTOR_ID); - } else { - lim_log(pMac, LOG1, - "Pre auth on same channel as connected AP channel %d", - psessionEntry->ftPEContext.pFTPreAuthReq-> - preAuthchannelNum); - lim_ft_process_pre_auth_result(pMac, status, psessionEntry); - } -} - /*------------------------------------------------------------------ * * This function handles the 11R Reassoc Req from SME @@ -1352,81 +837,6 @@ void lim_process_mlm_ft_reassoc_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf, return; } -/* - * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout - * - * @mac_ctx: global mac ctx - * - * This function is called if preauth response is not received from the AP - * within this timeout while FT in progress - * - * Return: void - */ -void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal mac_ctx) -{ - tpPESession session; - - /* - * We have failed pre auth. We need to resume link and get back on - * home channel - */ - lim_log(mac_ctx, LOGE, FL("FT Pre-Auth Time Out!!!!")); - session = pe_find_session_by_session_id(mac_ctx, - mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); - if (NULL == session) { - lim_log(mac_ctx, LOGE, - FL("Session Does not exist for given sessionID")); - return; - } - - /* Nothing to be done if the session is not in STA mode */ - if (!LIM_IS_STA_ROLE(session)) { - lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); - return; - } - - /* Reset the flag to indicate preauth request session */ - session->ftPEContext.ftPreAuthSession = false; - - if (NULL == session->ftPEContext.pFTPreAuthReq) { - lim_log(mac_ctx, LOGE, - FL("pFTPreAuthReq is NULL. Auth Rsp might already be posted to SME and ftcleanup done! sessionId:%d"), - mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); - return; - } - - /* - * To handle the race condition where we recieve preauth rsp after - * timer has expired. - */ - if (true == - session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { - lim_log(mac_ctx, LOGE, - FL("Auth rsp already posted to SME (session %p)"), - session); - return; - } else { - /* - * Here we are sending preauth rsp with failure state - * and which is forwarded to SME. Now, if we receive an preauth - * resp from AP with success it would create a FT pesession, but - * will be dropped in SME leaving behind the pesession. Mark - * Preauth rsp processed so that any rsp from AP is dropped in - * lim_process_auth_frame_no_session. - */ - lim_log(mac_ctx, LOG1, - FL("Auth rsp not yet posted to SME (session %p)"), - session); - session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true; - } - - /* - * Attempted at Pre-Auth and failed. If we are off channel. We need - * to get back to home channel - */ - lim_handle_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, session); -} - /*------------------------------------------------------------------ * * This function is called to process the update key request from SME @@ -1599,6 +1009,7 @@ lim_ft_send_aggr_qos_rsp(tpAniSirGlobal pMac, uint8_t rspReqd, lim_send_sme_aggr_qos_rsp(pMac, rsp, smesessionId); return; } + void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { tpAggrAddTsParams pAggrQosRspMsg = NULL; @@ -1662,6 +1073,7 @@ void lim_process_ft_aggr_qo_s_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) } return; } + tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf) { tSirMsgQ msg; @@ -1843,135 +1255,3 @@ tSirRetStatus lim_process_ft_aggr_qos_req(tpAniSirGlobal pMac, uint32_t *pMsgBuf return eSIR_SUCCESS; } -/** - * lim_send_preauth_scan_offload() - Send scan command to handle preauth. - * - * @mac_ctx: Pointer to Global MAC structure - * @session_id: pe session id - * @ft_preauth_req: Preauth request with parameters - * - * Builds a single channel scan request and sends it to WMA. - * Scan dwell time is the time allocated to go to preauth candidate - * channel for auth frame exchange. - * - * Return: Status of sending message to WMA. - */ -QDF_STATUS lim_send_preauth_scan_offload(tpAniSirGlobal mac_ctx, - uint8_t session_id, - tSirFTPreAuthReq *ft_preauth_req) -{ - tSirScanOffloadReq *scan_offload_req; - tSirRetStatus rc = eSIR_SUCCESS; - tSirMsgQ msg; - - scan_offload_req = qdf_mem_malloc(sizeof(tSirScanOffloadReq)); - if (NULL == scan_offload_req) { - lim_log(mac_ctx, LOGE, - FL("Memory allocation failed for pScanOffloadReq")); - return QDF_STATUS_E_NOMEM; - } - - qdf_mem_zero(scan_offload_req, sizeof(tSirScanOffloadReq)); - - msg.type = WMA_START_SCAN_OFFLOAD_REQ; - msg.bodyptr = scan_offload_req; - msg.bodyval = 0; - - qdf_mem_copy((uint8_t *) &scan_offload_req->selfMacAddr.bytes, - (uint8_t *) ft_preauth_req->self_mac_addr, - sizeof(tSirMacAddr)); - - qdf_mem_copy((uint8_t *) &scan_offload_req->bssId.bytes, - (uint8_t *) ft_preauth_req->currbssId, - sizeof(tSirMacAddr)); - scan_offload_req->scanType = eSIR_PASSIVE_SCAN; - /* - * P2P_SCAN_TYPE_LISTEN tells firmware to allow mgt frames to/from - * mac address that is not of connected AP. - */ - scan_offload_req->p2pScanType = P2P_SCAN_TYPE_LISTEN; - scan_offload_req->restTime = 0; - scan_offload_req->minChannelTime = LIM_FT_PREAUTH_SCAN_TIME; - scan_offload_req->maxChannelTime = LIM_FT_PREAUTH_SCAN_TIME; - scan_offload_req->sessionId = session_id; - scan_offload_req->channelList.numChannels = 1; - scan_offload_req->channelList.channelNumber[0] = - ft_preauth_req->preAuthchannelNum; - wma_get_scan_id(&ft_preauth_req->scan_id); - scan_offload_req->scan_id = ft_preauth_req->scan_id; - scan_offload_req->scan_requestor_id = PREAUTH_REQUESTOR_ID; - - lim_log(mac_ctx, LOG1, - FL("Scan request: duration %u, session %hu, chan %hu"), - scan_offload_req->maxChannelTime, session_id, - ft_preauth_req->preAuthchannelNum); - - rc = wma_post_ctrl_msg(mac_ctx, &msg); - if (rc != eSIR_SUCCESS) { - lim_log(mac_ctx, LOGE, FL("START_SCAN_OFFLOAD failed %u"), rc); - qdf_mem_free(scan_offload_req); - return QDF_STATUS_E_FAILURE; - } - - return QDF_STATUS_SUCCESS; -} - - -/** - * lim_preauth_scan_event_handler() - Process firmware preauth scan events - * - * @mac_ctx:Pointer to global MAC structure - * @event: Scan event - * @session_id: session entry - * @scan_id: scan id from WMA scan event. - * - * If scan event signifies failure or successful completion, operation - * is complete. - * If scan event signifies that STA is on foreign channel, send auth frame - * - * Return: void - */ - -void lim_preauth_scan_event_handler(tpAniSirGlobal mac_ctx, - enum lim_scan_event_type event, - uint8_t session_id, - uint32_t scan_id) -{ - tpPESession session_entry; - - session_entry = pe_find_session_by_session_id(mac_ctx, session_id); - if (session_entry == NULL) { - lim_log(mac_ctx, LOGE, - FL("SessionId:%d Session Does not exist"), session_id); - return; - } - - switch (event) { - case LIM_SCAN_EVENT_START_FAILED: - /* Scan command is rejected by firmware */ - lim_log(mac_ctx, LOGE, FL("Failed to start preauth scan")); - lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, - session_entry); - return; - - case LIM_SCAN_EVENT_COMPLETED: - /* - * Scan either completed succesfully or or got terminated - * after successful auth, or timed out. Either way, STA - * is back to home channel. Data traffic can continue. - */ - lim_ft_process_pre_auth_result(mac_ctx, QDF_STATUS_SUCCESS, - session_entry); - break; - - case LIM_SCAN_EVENT_FOREIGN_CHANNEL: - /* Sta is on candidate channel. Send auth */ - lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, - session_entry); - break; - default: - /* Don't print message for scan events that are ignored */ - break; - } -} - diff --git a/core/mac/src/pe/lim/lim_ft_preauth.c b/core/mac/src/pe/lim/lim_ft_preauth.c new file mode 100644 index 0000000000..0bc94f9c1f --- /dev/null +++ b/core/mac/src/pe/lim/lim_ft_preauth.c @@ -0,0 +1,782 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: lim_ft_preauth.c + * + * Pre-Authentication implementation for host based roaming + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wma.h" + +/** + * lim_ft_cleanup_pre_auth_info() - Cleanup preauth related information + * @pMac: Global MAC Context + * @psessionEntry: PE Session + * + * This routine is called to free the FT context, session and other + * information used during preauth operation. + * + * Return: None + */ +void lim_ft_cleanup_pre_auth_info(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tpPESession pReAssocSessionEntry = NULL; + uint8_t sessionId = 0; + + if (!psessionEntry) { + lim_log(pMac, LOGE, FL("psessionEntry is NULL")); + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); + return; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq) { + pReAssocSessionEntry = + pe_find_session_by_bssid(pMac, + psessionEntry->ftPEContext. + pFTPreAuthReq->preAuthbssId, + &sessionId); + + lim_log(pMac, LOG1, FL("Freeing pFTPreAuthReq= %p"), + psessionEntry->ftPEContext.pFTPreAuthReq); + if (psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription) { + qdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription); + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription = NULL; + } + qdf_mem_free(psessionEntry->ftPEContext.pFTPreAuthReq); + psessionEntry->ftPEContext.pFTPreAuthReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddBssReq) { + qdf_mem_free(psessionEntry->ftPEContext.pAddBssReq); + psessionEntry->ftPEContext.pAddBssReq = NULL; + } + + if (psessionEntry->ftPEContext.pAddStaReq) { + qdf_mem_free(psessionEntry->ftPEContext.pAddStaReq); + psessionEntry->ftPEContext.pAddStaReq = NULL; + } + + /* The session is being deleted, cleanup the contents */ + qdf_mem_set(&psessionEntry->ftPEContext, sizeof(tftPEContext), 0); + + /* Delete the session created while handling pre-auth response */ + if (pReAssocSessionEntry) { + /* If we have successful pre-auth response, then we would have + * created a session on which reassoc request will be sent + */ + if (pReAssocSessionEntry->valid && + pReAssocSessionEntry->limSmeState == + eLIM_SME_WT_REASSOC_STATE) { + QDF_TRACE(QDF_MODULE_ID_PE, + QDF_TRACE_LEVEL_DEBUG, + FL("Deleting Preauth session(%d)"), + pReAssocSessionEntry->peSessionId); + pe_delete_session(pMac, pReAssocSessionEntry); + } + } +} + +/* + * lim_process_ft_pre_auth_req() - process ft pre auth req + * + * @mac_ctx: global mac ctx + * @msg: pointer to message + * + * In this function, we process the FT Pre Auth Req: + * We receive Pre-Auth, suspend link, register a call back. In the call back, + * we will need to accept frames from the new bssid. Send out the auth req to + * new AP. Start timer and when the timer is done or if we receive the Auth + * response. We change channel. Resume link + * + * Return: value to indicate if buffer was consumed + */ +int lim_process_ft_pre_auth_req(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) +{ + int buf_consumed = false; + tpPESession session; + uint8_t session_id; + tpSirFTPreAuthReq ft_pre_auth_req = (tSirFTPreAuthReq *) msg->bodyptr; + + if (NULL == ft_pre_auth_req) { + lim_log(mac_ctx, LOGE, FL("tSirFTPreAuthReq is NULL")); + return buf_consumed; + } + + /* Get the current session entry */ + session = pe_find_session_by_bssid(mac_ctx, + ft_pre_auth_req->currbssId, + &session_id); + if (session == NULL) { + lim_log(mac_ctx, LOGE, + FL("Unable to find session for the bssid" + MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(ft_pre_auth_req->currbssId)); + /* Post the FT Pre Auth Response to SME */ + lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, + session); + /* + * return FALSE, since the Pre-Auth Req will be freed in + * limPostFTPreAuthRsp on failure + */ + return buf_consumed; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(session)) { + lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); + buf_consumed = true; + return buf_consumed; + } + + /* Can set it only after sending auth */ + session->ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + session->ftPEContext.ftPreAuthSession = true; + + /* Indicate that this is the session on which preauth is being done */ + if (session->ftPEContext.pFTPreAuthReq) { + if (session->ftPEContext.pFTPreAuthReq->pbssDescription) { + qdf_mem_free( + session->ftPEContext.pFTPreAuthReq->pbssDescription); + session->ftPEContext.pFTPreAuthReq->pbssDescription = + NULL; + } + qdf_mem_free(session->ftPEContext.pFTPreAuthReq); + session->ftPEContext.pFTPreAuthReq = NULL; + } + + /* We need information from the Pre-Auth Req. Lets save that */ + session->ftPEContext.pFTPreAuthReq = ft_pre_auth_req; + + lim_log(mac_ctx, LOG1, FL("PRE Auth ft_ies_length=%02x%02x%02x"), + session->ftPEContext.pFTPreAuthReq->ft_ies[0], + session->ftPEContext.pFTPreAuthReq->ft_ies[1], + session->ftPEContext.pFTPreAuthReq->ft_ies[2]); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PRE_AUTH_REQ_EVENT, + session, 0, 0); +#endif + + /* Dont need to suspend if APs are in same channel */ + if (session->currentOperChannel != + session->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to suspend link only if the channels are different */ + lim_log(mac_ctx, LOG2, + FL("Performing pre-auth on diff channel(session %p)"), + session); + lim_send_preauth_scan_offload(mac_ctx, session->peSessionId, + session->ftPEContext.pFTPreAuthReq); + } else { + lim_log(mac_ctx, LOG2, + FL("Performing pre-auth on same channel (session %p)"), + session); + /* We are in the same channel. Perform pre-auth */ + lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, + session); + } + + return buf_consumed; +} + +/** + * lim_perform_ft_pre_auth() - Perform preauthentication + * @pMac: Global MAC Context + * @status: Status Code + * @data: pre-auth data + * @psessionEntry: PE Session + * + * This routine will trigger the sending of authentication frame + * to the peer. + * + * Return: None + */ +void lim_perform_ft_pre_auth(tpAniSirGlobal pMac, QDF_STATUS status, + uint32_t *data, tpPESession psessionEntry) +{ + tSirMacAuthFrameBody authFrame; + + if (NULL == psessionEntry) { + PELOGE(lim_log(pMac, LOGE, FL("psessionEntry is NULL"));) + return; + } + + if (psessionEntry->is11Rconnection && + psessionEntry->ftPEContext.pFTPreAuthReq) { + /* Only 11r assoc has FT IEs */ + if (psessionEntry->ftPEContext.pFTPreAuthReq->ft_ies == NULL) { + lim_log(pMac, LOGE, + FL("FTIEs for Auth Req Seq 1 is absent")); + goto preauth_fail; + } + } + + if (status != QDF_STATUS_SUCCESS) { + lim_log(pMac, LOGE, + FL(" Change channel not successful for FT pre-auth")); + goto preauth_fail; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); + return; + } + lim_log(pMac, LOG2, "Entered wait auth2 state for FT (old session %p)", + psessionEntry); + if (psessionEntry->is11Rconnection) { + /* Now we are on the right channel and need to send out Auth1 + * and receive Auth2 + */ + authFrame.authAlgoNumber = eSIR_FT_AUTH; + } else { + /* Will need to make isESEconnection a enum may be for further + * improvements to this to match this algorithm number + */ + authFrame.authAlgoNumber = eSIR_OPEN_SYSTEM; + } + authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_1; + authFrame.authStatusCode = 0; + + /* Start timer here to come back to operating channel */ + pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId = + psessionEntry->peSessionId; + if (TX_SUCCESS != + tx_timer_activate(&pMac->lim.limTimers.gLimFTPreAuthRspTimer)) { + lim_log(pMac, LOGE, FL("FT Auth Rsp Timer Start Failed")); + goto preauth_fail; + } + MTRACE(mac_trace(pMac, TRACE_CODE_TIMER_ACTIVATE, + psessionEntry->peSessionId, eLIM_FT_PREAUTH_RSP_TIMER)); + + lim_log(pMac, LOG1, FL("FT Auth Rsp Timer Started")); +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_ROAM_AUTH_START_EVENT, + pMac->lim.pSessionEntry, eSIR_SUCCESS, eSIR_SUCCESS); +#endif + + lim_send_auth_mgmt_frame(pMac, &authFrame, + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, + LIM_NO_WEP_IN_FC, psessionEntry, false); + + return; + +preauth_fail: + lim_handle_ft_pre_auth_rsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); + return; +} + +/** + * lim_ft_setup_auth_session() - Fill the FT Session + * @pMac: Global MAC Context + * @psessionEntry: PE Session + * + * Setup the session and the add bss req for the pre-auth AP. + * + * Return: Success or Failure Status + */ +tSirRetStatus lim_ft_setup_auth_session(tpAniSirGlobal pMac, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + uint8_t sessionId = 0; + + pftSessionEntry = + pe_find_session_by_bssid(pMac, psessionEntry->limReAssocbssId, + &sessionId); + if (pftSessionEntry == NULL) { + lim_log(pMac, LOGE, FL("No session found for bssid")); + lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOGE); + return eSIR_FAILURE; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); + return eSIR_FAILURE; + } + + if (psessionEntry->ftPEContext.pFTPreAuthReq && + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + lim_fill_ft_session(pMac, + psessionEntry->ftPEContext.pFTPreAuthReq-> + pbssDescription, pftSessionEntry, + psessionEntry); + + lim_ft_prepare_add_bss_req(pMac, false, pftSessionEntry, + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription); + } + + return eSIR_SUCCESS; +} + +/** + * lim_ft_process_pre_auth_result() - Process the Auth frame + * @pMac: Global MAC context + * @status: Status code + * psessionEntry: PE Session + * + * Return: None + */ +void lim_ft_process_pre_auth_result(tpAniSirGlobal pMac, QDF_STATUS status, + tpPESession psessionEntry) +{ + if (NULL == psessionEntry || + NULL == psessionEntry->ftPEContext.pFTPreAuthReq) + return; + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); + return; + } + + if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + psessionEntry->ftPEContext.ftPreAuthStatus = + lim_ft_setup_auth_session(pMac, psessionEntry); + } + /* Post the FT Pre Auth Response to SME */ + lim_post_ft_pre_auth_rsp(pMac, + psessionEntry->ftPEContext.ftPreAuthStatus, + psessionEntry->ftPEContext.saved_auth_rsp, + psessionEntry->ftPEContext.saved_auth_rsp_length, + psessionEntry); +} + +/** + * lim_handle_ft_pre_auth_rsp() - Handle the Auth response + * @pMac: Global MAC Context + * @status: Status Code + * @auth_rsp: Auth Response + * @auth_rsp_length: Auth response length + * @psessionEntry: PE Session + * + * Send the FT Pre Auth Response to SME whenever we have a status + * ready to be sent to SME + * + * SME will be the one to send it up to the supplicant to receive + * FTIEs which will be required for Reassoc Req. + * + * @Return: None + */ +void lim_handle_ft_pre_auth_rsp(tpAniSirGlobal pMac, tSirRetStatus status, + uint8_t *auth_rsp, uint16_t auth_rsp_length, + tpPESession psessionEntry) +{ + tpPESession pftSessionEntry = NULL; + uint8_t sessionId = 0; + tpSirBssDescription pbssDescription = NULL; +#ifdef FEATURE_WLAN_DIAG_SUPPORT + lim_diag_event_report(pMac, WLAN_PE_DIAG_PRE_AUTH_RSP_EVENT, + psessionEntry, (uint16_t) status, 0); +#endif + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(psessionEntry)) { + lim_log(pMac, LOGE, FL("psessionEntry is not in STA mode")); + return; + } + + /* Save the status of pre-auth */ + psessionEntry->ftPEContext.ftPreAuthStatus = status; + + /* Save the auth rsp, so we can send it to + * SME once we resume link + */ + psessionEntry->ftPEContext.saved_auth_rsp_length = 0; + if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { + qdf_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp, + auth_rsp, auth_rsp_length); + psessionEntry->ftPEContext.saved_auth_rsp_length = + auth_rsp_length; + } + + if (!psessionEntry->ftPEContext.pFTPreAuthReq || + !psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription) { + lim_log(pMac, LOGE, + FL("pFTPreAuthReq or pbssDescription is NULL")); + return; + } + + /* Create FT session for the re-association at this point */ + if (psessionEntry->ftPEContext.ftPreAuthStatus == eSIR_SUCCESS) { + pbssDescription = + psessionEntry->ftPEContext.pFTPreAuthReq->pbssDescription; + lim_print_mac_addr(pMac, pbssDescription->bssId, LOG1); + pftSessionEntry = + pe_create_session(pMac, pbssDescription->bssId, + &sessionId, pMac->lim.maxStation, + psessionEntry->bssType); + if (pftSessionEntry == NULL) { + lim_log(pMac, LOGE, FL( + "Session not created for pre-auth 11R AP")); + status = eSIR_FAILURE; + psessionEntry->ftPEContext.ftPreAuthStatus = status; + goto send_rsp; + } + pftSessionEntry->peSessionId = sessionId; + pftSessionEntry->smeSessionId = psessionEntry->smeSessionId; + sir_copy_mac_addr(pftSessionEntry->selfMacAddr, + psessionEntry->selfMacAddr); + sir_copy_mac_addr(pftSessionEntry->limReAssocbssId, + pbssDescription->bssId); + pftSessionEntry->bssType = psessionEntry->bssType; + + if (pftSessionEntry->bssType == eSIR_INFRASTRUCTURE_MODE) + pftSessionEntry->limSystemRole = eLIM_STA_ROLE; + else if (pftSessionEntry->bssType == eSIR_BTAMP_AP_MODE) + pftSessionEntry->limSystemRole = eLIM_BT_AMP_STA_ROLE; + else + lim_log(pMac, LOGE, FL("Invalid bss type")); + pftSessionEntry->limPrevSmeState = pftSessionEntry->limSmeState; + qdf_mem_copy(&(pftSessionEntry->htConfig), + &(psessionEntry->htConfig), + sizeof(psessionEntry->htConfig)); + pftSessionEntry->limSmeState = eLIM_SME_WT_REASSOC_STATE; + + lim_log(pMac, LOG1, FL("created session (%p) with id = %d"), + pftSessionEntry, pftSessionEntry->peSessionId); + + /* Update the ReAssoc BSSID of the current session */ + sir_copy_mac_addr(psessionEntry->limReAssocbssId, + pbssDescription->bssId); + lim_print_mac_addr(pMac, psessionEntry->limReAssocbssId, LOG1); + } +send_rsp: + if (psessionEntry->currentOperChannel != + psessionEntry->ftPEContext.pFTPreAuthReq->preAuthchannelNum) { + /* Need to move to the original AP channel */ + lim_process_abort_scan_ind(pMac, psessionEntry->peSessionId, + psessionEntry->ftPEContext.pFTPreAuthReq->scan_id, + PREAUTH_REQUESTOR_ID); + } else { + lim_log(pMac, LOG1, + "Pre auth on same channel as connected AP channel %d", + psessionEntry->ftPEContext.pFTPreAuthReq-> + preAuthchannelNum); + lim_ft_process_pre_auth_result(pMac, status, psessionEntry); + } +} + +/* + * lim_process_ft_preauth_rsp_timeout() - process ft preauth rsp timeout + * + * @mac_ctx: global mac ctx + * + * This function is called if preauth response is not received from the AP + * within this timeout while FT in progress + * + * Return: void + */ +void lim_process_ft_preauth_rsp_timeout(tpAniSirGlobal mac_ctx) +{ + tpPESession session; + + /* + * We have failed pre auth. We need to resume link and get back on + * home channel + */ + lim_log(mac_ctx, LOGE, FL("FT Pre-Auth Time Out!!!!")); + session = pe_find_session_by_session_id(mac_ctx, + mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); + if (NULL == session) { + lim_log(mac_ctx, LOGE, + FL("Session Does not exist for given sessionID")); + return; + } + + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(session)) { + lim_log(mac_ctx, LOGE, FL("session is not in STA mode")); + return; + } + + /* Reset the flag to indicate preauth request session */ + session->ftPEContext.ftPreAuthSession = false; + + if (NULL == session->ftPEContext.pFTPreAuthReq) { + /* Auth Rsp might already be posted to SME and ftcleanup done */ + lim_log(mac_ctx, LOGE, FL("pFTPreAuthReq is NULL sessionId:%d"), + mac_ctx->lim.limTimers.gLimFTPreAuthRspTimer.sessionId); + return; + } + + /* + * To handle the race condition where we recieve preauth rsp after + * timer has expired. + */ + if (true == + session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) { + lim_log(mac_ctx, LOGE, + FL("Auth rsp already posted to SME (session %p)"), + session); + return; + } else { + /* + * Here we are sending preauth rsp with failure state + * and which is forwarded to SME. Now, if we receive an preauth + * resp from AP with success it would create a FT pesession, but + * will be dropped in SME leaving behind the pesession. Mark + * Preauth rsp processed so that any rsp from AP is dropped in + * lim_process_auth_frame_no_session. + */ + lim_log(mac_ctx, LOG1, + FL("Auth rsp not yet posted to SME (session %p)"), + session); + session->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = true; + } + + /* + * Attempted at Pre-Auth and failed. If we are off channel. We need + * to get back to home channel + */ + lim_handle_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, session); +} + +/* + * lim_post_ft_pre_auth_rsp() - post ft pre auth response to SME. + * + * @mac_ctx: global mac ctx + * @status: status code to post in auth rsp + * @auth_rsp: pointer to auth rsp FT ie + * @auth_rsp_length: len of the IE field + * @session: pe session + * + * post pre auth response to SME. + * + * Return: void + */ +void lim_post_ft_pre_auth_rsp(tpAniSirGlobal mac_ctx, + tSirRetStatus status, + uint8_t *auth_rsp, + uint16_t auth_rsp_length, + tpPESession session) +{ + tpSirFTPreAuthRsp ft_pre_auth_rsp; + tSirMsgQ mmh_msg; + uint16_t rsp_len = sizeof(tSirFTPreAuthRsp); + + ft_pre_auth_rsp = (tpSirFTPreAuthRsp) qdf_mem_malloc(rsp_len); + if (NULL == ft_pre_auth_rsp) { + lim_log(mac_ctx, LOGE, "Failed to allocate memory"); + QDF_ASSERT(ft_pre_auth_rsp != NULL); + return; + } + qdf_mem_zero(ft_pre_auth_rsp, rsp_len); + + lim_log(mac_ctx, LOG1, FL("Auth Rsp = %p"), ft_pre_auth_rsp); + if (session) { + /* Nothing to be done if the session is not in STA mode */ + if (!LIM_IS_STA_ROLE(session)) { + lim_log(mac_ctx, LOGE, + FL("session is not in STA mode")); + qdf_mem_free(ft_pre_auth_rsp); + return; + } + ft_pre_auth_rsp->smeSessionId = session->smeSessionId; + /* The bssid of the AP we are sending Auth1 to. */ + if (session->ftPEContext.pFTPreAuthReq) + sir_copy_mac_addr(ft_pre_auth_rsp->preAuthbssId, + session->ftPEContext.pFTPreAuthReq->preAuthbssId); + } + + ft_pre_auth_rsp->messageType = eWNI_SME_FT_PRE_AUTH_RSP; + ft_pre_auth_rsp->length = (uint16_t) rsp_len; + ft_pre_auth_rsp->status = status; + + /* Attach the auth response now back to SME */ + ft_pre_auth_rsp->ft_ies_length = 0; + if ((auth_rsp != NULL) && (auth_rsp_length < MAX_FTIE_SIZE)) { + /* Only 11r assoc has FT IEs */ + qdf_mem_copy(ft_pre_auth_rsp->ft_ies, + auth_rsp, auth_rsp_length); + ft_pre_auth_rsp->ft_ies_length = auth_rsp_length; + } + + if (status != eSIR_SUCCESS) { + /* + * Ensure that on Pre-Auth failure the cached Pre-Auth Req and + * other allocated memory is freed up before returning. + */ + lim_log(mac_ctx, LOG1, "Pre-Auth Failed, Cleanup!"); + lim_ft_cleanup(mac_ctx, session); + } + + mmh_msg.type = ft_pre_auth_rsp->messageType; + mmh_msg.bodyptr = ft_pre_auth_rsp; + mmh_msg.bodyval = 0; + + lim_log(mac_ctx, LOG1, FL("Posted Auth Rsp to SME with status of 0x%x"), + status); +#ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ + if (status == eSIR_SUCCESS) + lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_PREAUTH_DONE, + session, status, 0); +#endif + lim_sys_process_mmh_msg_api(mac_ctx, &mmh_msg, ePROT); +} + +/** + * lim_send_preauth_scan_offload() - Send scan command to handle preauth. + * + * @mac_ctx: Pointer to Global MAC structure + * @session_id: pe session id + * @ft_preauth_req: Preauth request with parameters + * + * Builds a single channel scan request and sends it to WMA. + * Scan dwell time is the time allocated to go to preauth candidate + * channel for auth frame exchange. + * + * Return: Status of sending message to WMA. + */ +QDF_STATUS lim_send_preauth_scan_offload(tpAniSirGlobal mac_ctx, + uint8_t session_id, + tSirFTPreAuthReq *ft_preauth_req) +{ + tSirScanOffloadReq *scan_offload_req; + tSirRetStatus rc = eSIR_SUCCESS; + tSirMsgQ msg; + + scan_offload_req = qdf_mem_malloc(sizeof(tSirScanOffloadReq)); + if (NULL == scan_offload_req) { + lim_log(mac_ctx, LOGE, + FL("Memory allocation failed for pScanOffloadReq")); + return QDF_STATUS_E_NOMEM; + } + + qdf_mem_zero(scan_offload_req, sizeof(tSirScanOffloadReq)); + + msg.type = WMA_START_SCAN_OFFLOAD_REQ; + msg.bodyptr = scan_offload_req; + msg.bodyval = 0; + + qdf_mem_copy((uint8_t *) &scan_offload_req->selfMacAddr.bytes, + (uint8_t *) ft_preauth_req->self_mac_addr, + sizeof(tSirMacAddr)); + + qdf_mem_copy((uint8_t *) &scan_offload_req->bssId.bytes, + (uint8_t *) ft_preauth_req->currbssId, + sizeof(tSirMacAddr)); + scan_offload_req->scanType = eSIR_PASSIVE_SCAN; + /* + * P2P_SCAN_TYPE_LISTEN tells firmware to allow mgt frames to/from + * mac address that is not of connected AP. + */ + scan_offload_req->p2pScanType = P2P_SCAN_TYPE_LISTEN; + scan_offload_req->restTime = 0; + scan_offload_req->minChannelTime = LIM_FT_PREAUTH_SCAN_TIME; + scan_offload_req->maxChannelTime = LIM_FT_PREAUTH_SCAN_TIME; + scan_offload_req->sessionId = session_id; + scan_offload_req->channelList.numChannels = 1; + scan_offload_req->channelList.channelNumber[0] = + ft_preauth_req->preAuthchannelNum; + wma_get_scan_id(&ft_preauth_req->scan_id); + scan_offload_req->scan_id = ft_preauth_req->scan_id; + scan_offload_req->scan_requestor_id = PREAUTH_REQUESTOR_ID; + + lim_log(mac_ctx, LOG1, + FL("Scan request: duration %u, session %hu, chan %hu"), + scan_offload_req->maxChannelTime, session_id, + ft_preauth_req->preAuthchannelNum); + + rc = wma_post_ctrl_msg(mac_ctx, &msg); + if (rc != eSIR_SUCCESS) { + lim_log(mac_ctx, LOGE, FL("START_SCAN_OFFLOAD failed %u"), rc); + qdf_mem_free(scan_offload_req); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * lim_preauth_scan_event_handler() - Process firmware preauth scan events + * + * @mac_ctx:Pointer to global MAC structure + * @event: Scan event + * @session_id: session entry + * @scan_id: scan id from WMA scan event. + * + * If scan event signifies failure or successful completion, operation + * is complete. + * If scan event signifies that STA is on foreign channel, send auth frame + * + * Return: void + */ + +void lim_preauth_scan_event_handler(tpAniSirGlobal mac_ctx, + enum lim_scan_event_type event, + uint8_t session_id, + uint32_t scan_id) +{ + tpPESession session_entry; + + session_entry = pe_find_session_by_session_id(mac_ctx, session_id); + if (session_entry == NULL) { + lim_log(mac_ctx, LOGE, + FL("SessionId:%d Session Does not exist"), session_id); + return; + } + + switch (event) { + case LIM_SCAN_EVENT_START_FAILED: + /* Scan command is rejected by firmware */ + lim_log(mac_ctx, LOGE, FL("Failed to start preauth scan")); + lim_post_ft_pre_auth_rsp(mac_ctx, eSIR_FAILURE, NULL, 0, + session_entry); + return; + + case LIM_SCAN_EVENT_COMPLETED: + /* + * Scan either completed succesfully or or got terminated + * after successful auth, or timed out. Either way, STA + * is back to home channel. Data traffic can continue. + */ + lim_ft_process_pre_auth_result(mac_ctx, QDF_STATUS_SUCCESS, + session_entry); + break; + + case LIM_SCAN_EVENT_FOREIGN_CHANNEL: + /* Sta is on candidate channel. Send auth */ + lim_perform_ft_pre_auth(mac_ctx, QDF_STATUS_SUCCESS, NULL, + session_entry); + break; + default: + /* Don't print message for scan events that are ignored */ + break; + } +} +