| /* |
| * Copyright (c) 2011-2017 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. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * |
| * This file limProcessAuthFrame.cc contains the code |
| * for processing received Authentication Frame. |
| * Author: Chandra Modumudi |
| * Date: 03/11/02 |
| * History:- |
| * Date Modified by Modification Information |
| * -------------------------------------------------------------------- |
| * 05/12/2010 js To support Shared key authentication at AP side |
| * |
| */ |
| |
| #include "wniApi.h" |
| #include "wni_cfg.h" |
| #include "aniGlobal.h" |
| #include "cfgApi.h" |
| |
| #include "utilsApi.h" |
| #include "limUtils.h" |
| #include "limAssocUtils.h" |
| #include "limSecurityUtils.h" |
| #include "limSerDesUtils.h" |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| #include "limFT.h" |
| #endif |
| #include "vos_utils.h" |
| #include "lim_process_fils.h" |
| |
| /** |
| * isAuthValid |
| * |
| *FUNCTION: |
| * This function is called by limProcessAuthFrame() upon Authentication |
| * frame reception. |
| * |
| *LOGIC: |
| * This function is used to test validity of auth frame: |
| * - AUTH1 and AUTH3 must be received in AP mode |
| * - AUTH2 and AUTH4 must be received in STA mode |
| * - AUTH3 and AUTH4 must have challenge text IE, that is,'type' field has been set to |
| * SIR_MAC_CHALLENGE_TEXT_EID by parser |
| * - |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * |
| * @param *auth - Pointer to extracted auth frame body |
| * |
| * @return 0 or 1 (Valid) |
| */ |
| |
| |
| static inline unsigned int |
| isAuthValid(tpAniSirGlobal pMac, tpSirMacAuthFrameBody auth, |
| tpPESession sessionEntry) |
| { |
| unsigned int valid = 1; |
| |
| if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_1) || |
| (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3)) && |
| (LIM_IS_STA_ROLE(sessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(sessionEntry))) |
| valid = 0; |
| |
| if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_2) || |
| (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) && |
| (LIM_IS_AP_ROLE(sessionEntry) || LIM_IS_BT_AMP_AP_ROLE(sessionEntry))) |
| valid = 0; |
| |
| if (((auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_3) || |
| (auth->authTransactionSeqNumber == SIR_MAC_AUTH_FRAME_4)) && |
| (auth->type != SIR_MAC_CHALLENGE_TEXT_EID) && |
| (auth->authAlgoNumber != eSIR_SHARED_KEY)) |
| valid = 0; |
| |
| return valid; |
| } |
| |
| |
| /** |
| * limProcessAuthFrame |
| * |
| *FUNCTION: |
| * This function is called by limProcessMessageQueue() upon Authentication |
| * frame reception. |
| * |
| *LOGIC: |
| * This function processes received Authentication frame and responds |
| * with either next Authentication frame in sequence to peer MAC entity |
| * or LIM_MLM_AUTH_IND on AP or LIM_MLM_AUTH_CNF on STA. |
| * |
| *ASSUMPTIONS: |
| * |
| *NOTE: |
| * 1. Authentication failures are reported to SME with same status code |
| * received from the peer MAC entity. |
| * 2. Authentication frame2/4 received with alogirthm number other than |
| * one requested in frame1/3 are logged with an error and auth confirm |
| * will be sent to SME only after auth failure timeout. |
| * 3. Inconsistency in the spec: |
| * On receiving Auth frame2, specs says that if WEP key mapping key |
| * or default key is NULL, Auth frame3 with a status code 15 (challenge |
| * failure to be returned to peer entity. However, section 7.2.3.10, |
| * table 14 says that status code field is 'reserved' for frame3 ! |
| * In the current implementation, Auth frame3 is returned with status |
| * code 15 overriding section 7.2.3.10. |
| * 4. If number pre-authentications reach configrable max limit, |
| * Authentication frame with 'unspecified failure' status code is |
| * returned to requesting entity. |
| * |
| * @param pMac - Pointer to Global MAC structure |
| * @param *pRxPacketInfo - A pointer to Rx packet info structure |
| * @return None |
| */ |
| |
| void |
| limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) |
| { |
| tANI_U8 *pBody, keyId, cfgPrivacyOptImp, |
| defaultKey[SIR_MAC_KEY_LENGTH], |
| *encrAuthFrame = NULL, |
| *plainBody = NULL; |
| tANI_U16 frameLen; |
| tANI_U32 maxNumPreAuth, val; |
| tSirMacAuthFrameBody *pRxAuthFrameBody, |
| *rxAuthFrame = NULL, |
| *authFrame = NULL; |
| tpSirMacMgmtHdr pHdr; |
| tCfgWepKeyEntry *pKeyMapEntry = NULL; |
| struct tLimPreAuthNode *pAuthNode; |
| tLimMlmAuthInd mlmAuthInd; |
| tANI_U8 decryptResult; |
| tANI_U8 *pChallenge; |
| tANI_U32 key_length=8; |
| tANI_U8 *challengeTextArray = NULL; |
| tpDphHashNode pStaDs = NULL; |
| tANI_U16 assocId = 0; |
| tANI_U16 currSeqNum = 0; |
| |
| // Get pointer to Authentication frame header and body |
| pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); |
| |
| |
| if (!frameLen) |
| { |
| // Log error |
| limLog(pMac, LOGE, |
| FL("received Authentication frame with no body from ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGE); |
| |
| return; |
| } |
| |
| if (limIsGroupAddr(pHdr->sa)) |
| { |
| // Received Auth frame from a BC/MC address |
| // Log error and ignore it |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame from a BC/MC address - "));) |
| PELOGE( limPrintMacAddr(pMac, pHdr->sa, LOGE);) |
| |
| return; |
| } |
| currSeqNum = (pHdr->seqControl.seqNumHi << 4) | |
| (pHdr->seqControl.seqNumLo); |
| limLog(pMac, LOG1, |
| FL("Sessionid: %d System role : %d limMlmState: %d :Auth " |
| "Frame Received: BSSID: "MAC_ADDRESS_STR " (RSSI %d)"), |
| psessionEntry->peSessionId, GET_LIM_SYSTEM_ROLE(psessionEntry), |
| psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->bssId), |
| (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pRxPacketInfo))); |
| |
| pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); |
| |
| //Restore default failure timeout |
| if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona && psessionEntry->defaultAuthFailureTimeout) |
| { |
| limLog(pMac, LOG1, FL("Restore default failure timeout")); |
| ccmCfgSetInt(pMac,WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT , |
| psessionEntry->defaultAuthFailureTimeout, NULL, eANI_BOOLEAN_FALSE); |
| } |
| |
| rxAuthFrame = vos_mem_malloc(sizeof(tSirMacAuthFrameBody)); |
| if (!rxAuthFrame) { |
| limLog(pMac, LOGE, FL("Failed to allocate memory")); |
| return; |
| } |
| |
| authFrame = vos_mem_malloc(sizeof(tSirMacAuthFrameBody)); |
| if (!authFrame) { |
| limLog(pMac, LOGE, FL("failed to allocate memory")); |
| goto free; |
| } |
| |
| plainBody = vos_mem_malloc(LIM_ENCR_AUTH_BODY_LEN); |
| if (!plainBody) { |
| limLog(pMac, LOGE, FL("failed to allocate memory")); |
| goto free; |
| } |
| |
| challengeTextArray = vos_mem_malloc(SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); |
| if(!challengeTextArray) { |
| limLog(pMac, LOGE, FL("failed to allocate memory")); |
| goto free; |
| } |
| |
| vos_mem_set(rxAuthFrame, sizeof(tSirMacAuthFrameBody), 0); |
| vos_mem_set(authFrame, sizeof(tSirMacAuthFrameBody), 0); |
| vos_mem_set(plainBody, LIM_ENCR_AUTH_BODY_LEN, 0); |
| vos_mem_set(challengeTextArray, SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH, 0); |
| |
| /// Determine if WEP bit is set in the FC or received MAC header |
| if (pHdr->fc.wep) |
| { |
| /** |
| * WEP bit is set in FC of MAC header. |
| */ |
| |
| // If TKIP counter measures enabled issue Deauth frame to station |
| if ((psessionEntry->bTkipCntrMeasActive) && |
| LIM_IS_AP_ROLE(psessionEntry)) { |
| PELOGE( limLog(pMac, LOGE, |
| FL("Tkip counter measures Enabled, sending Deauth frame to")); ) |
| limPrintMacAddr(pMac, pHdr->sa, LOGE); |
| |
| limSendDeauthMgmtFrame( pMac, eSIR_MAC_MIC_FAILURE_REASON, |
| pHdr->sa, psessionEntry, FALSE ); |
| goto free; |
| } |
| |
| // Extract key ID from IV (most 2 bits of 4th byte of IV) |
| |
| keyId = (*(pBody + 3)) >> 6; |
| |
| /** |
| * On STA in infrastructure BSS, Authentication frames received |
| * with WEP bit set in the FC must be rejected with challenge |
| * failure status code (wierd thing in the spec - this should have |
| * been rejected with unspecified failure or unexpected assertion |
| * of wep bit (this status code does not exist though) or |
| * Out-of-sequence-Authentication-Frame status code. |
| */ |
| |
| if (LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) { |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame with wep bit set on role=%d" |
| MAC_ADDRESS_STR), GET_LIM_SYSTEM_ROLE(psessionEntry), |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| |
| if ((frameLen < LIM_ENCR_AUTH_BODY_LEN_SAP) || |
| (frameLen > LIM_ENCR_AUTH_BODY_LEN)) |
| { |
| // Log error |
| limLog(pMac, LOGE, |
| FL("Not enough size [%d] to decrypt received Auth frame"), |
| frameLen); |
| limPrintMacAddr(pMac, pHdr->sa, LOGE); |
| |
| goto free; |
| } |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| val = psessionEntry->privacy; |
| } |
| else |
| // Accept Authentication frame only if Privacy is implemented |
| if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, |
| &val) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Privacy option |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, FL("could not retrieve Privacy option")); |
| } |
| |
| cfgPrivacyOptImp = (tANI_U8)val; |
| if (cfgPrivacyOptImp) |
| { |
| /** |
| * Privacy option is implemented. |
| * Check if the received frame is Authentication |
| * frame3 and there is a context for requesting STA. |
| * If not, reject with unspecified failure status code |
| */ |
| pAuthNode = limSearchPreAuthList(pMac, pHdr->sa); |
| |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame from peer that has no preauth context with WEP bit set " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /** |
| * No 'pre-auth' context exists for this STA that sent |
| * an Authentication frame with FC bit set. |
| * Send Auth frame4 with 'out of sequence' status code. |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| else |
| { |
| /// Change the auth-response timeout |
| limDeactivateAndChangePerStaIdTimer(pMac, |
| eLIM_AUTH_RSP_TIMER, |
| pAuthNode->authNodeIdx); |
| |
| /// 'Pre-auth' status exists for STA |
| if ((pAuthNode->mlmState != |
| eLIM_MLM_WT_AUTH_FRAME3_STATE) && |
| (pAuthNode->mlmState != |
| eLIM_MLM_AUTH_RSP_TIMEOUT_STATE)) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame from peer that is in state %d " |
| MAC_ADDRESS_STR), |
| pAuthNode->mlmState, MAC_ADDR_ARRAY(pHdr->sa));) |
| /** |
| * Should not have received Authentication frame |
| * with WEP bit set in FC in other states. |
| * Reject by sending Authenticaton frame with |
| * out of sequence Auth frame status code. |
| */ |
| |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| } |
| |
| /** |
| * Check if there exists a key mappping key |
| * for the STA that sent Authentication frame |
| */ |
| pKeyMapEntry = limLookUpKeyMappings(pHdr->sa); |
| |
| if (pKeyMapEntry) |
| { |
| if (!pKeyMapEntry->wepOn) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame3 from peer that has NULL key map entry " |
| MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));) |
| /** |
| * Key Mapping entry has null key. |
| * Send Authentication frame |
| * with challenge failure status code |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } // if (!pKeyMapEntry->wepOn) |
| else |
| { |
| decryptResult = limDecryptAuthFrame(pMac, pKeyMapEntry->key, |
| pBody, |
| plainBody, |
| key_length, |
| (tANI_U16) (frameLen-SIR_MAC_WEP_IV_LENGTH)); |
| if (decryptResult == LIM_DECRYPT_ICV_FAIL) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame from peer that failed decryption, Addr " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| limDeletePreAuthNode(pMac, |
| pHdr->sa); |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| |
| goto free; |
| } |
| |
| if ((sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8, |
| rxAuthFrame)!=eSIR_SUCCESS ) || |
| ( !isAuthValid(pMac, rxAuthFrame,psessionEntry))) |
| { |
| PELOGE(limLog(pMac, LOGE, FL( |
| "failed to convert Auth Frame to structure or Auth is not valid "));) |
| goto free; |
| } |
| } // end if (pKeyMapEntry->key == NULL) |
| } // if keyMappings has entry |
| else |
| { |
| |
| val = SIR_MAC_KEY_LENGTH; |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| tpSirKeys pKey; |
| pKey = &psessionEntry->WEPKeyMaterial[keyId].key[0]; |
| vos_mem_copy(defaultKey, pKey->key, pKey->keyLength); |
| val = pKey->keyLength; |
| } else if (wlan_cfgGetStr(pMac, |
| (tANI_U16) (WNI_CFG_WEP_DEFAULT_KEY_1 + keyId), |
| defaultKey, &val) != eSIR_SUCCESS) { |
| /// Could not get Default key from CFG. |
| //Log error. |
| limLog(pMac, LOGP, |
| FL("could not retrieve Default key")); |
| |
| /** |
| * Send Authentication frame |
| * with challenge failure status code |
| */ |
| |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| goto free; |
| } |
| |
| key_length=val; |
| |
| decryptResult = limDecryptAuthFrame(pMac, defaultKey, |
| pBody, |
| plainBody, |
| key_length, |
| (tANI_U16) (frameLen-SIR_MAC_WEP_IV_LENGTH)); |
| if (decryptResult == LIM_DECRYPT_ICV_FAIL) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame from peer that failed decryption: " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| /// ICV failure |
| limDeletePreAuthNode(pMac, |
| pHdr->sa); |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| if ( ( sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8, |
| rxAuthFrame)!=eSIR_SUCCESS ) || |
| ( !isAuthValid(pMac, rxAuthFrame, psessionEntry) ) ) |
| { |
| limLog(pMac, LOGE, |
| FL("failed to convert Auth Frame to structure or Auth is not valid ")); |
| goto free; |
| } |
| } // End of check for Key Mapping/Default key presence |
| } |
| else |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame3 from peer that while privacy option is turned OFF " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| /** |
| * Privacy option is not implemented. |
| * So reject Authentication frame received with |
| * WEP bit set by sending Authentication frame |
| * with 'challenge failure' status code. This is |
| * another strange thing in the spec. Status code |
| * should have been 'unsupported algorithm' status code. |
| */ |
| |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } // else if (wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) |
| } // if (fc.wep) |
| else |
| { |
| if ( ( sirConvertAuthFrame2Struct(pMac, pBody, |
| frameLen, rxAuthFrame)!=eSIR_SUCCESS ) || |
| ( !isAuthValid(pMac, rxAuthFrame,psessionEntry) ) ) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("failed to convert Auth Frame to structure or Auth is not valid "));) |
| goto free; |
| } |
| } |
| |
| |
| pRxAuthFrameBody = rxAuthFrame; |
| |
| PELOGW(limLog(pMac, LOGW, |
| FL("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), |
| (tANI_U32) pRxAuthFrameBody->authAlgoNumber, |
| (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber, |
| (tANI_U32) pRxAuthFrameBody->authStatusCode,(tANI_U32)pMac->lim.gLimNumPreAuthContexts);) |
| if (!lim_is_valid_fils_auth_frame(pMac, psessionEntry, pRxAuthFrameBody)) |
| { |
| limLog(pMac, LOGE, FL("Received invalid FILS auth packet")); |
| goto free; |
| } |
| // IOT Workaround: with invalid WEP password, some APs reply AUTH frame 4 |
| // with invalid seqNumber. This AUTH frame will be dropped by driver, |
| // thus driver sends the generic status code instead of protocol status code. |
| // As a workaround, assign the correct seqNumber for the AUTH frame 4. |
| if (psessionEntry->limMlmState == eLIM_MLM_WT_AUTH_FRAME4_STATE && |
| pRxAuthFrameBody->authTransactionSeqNumber != SIR_MAC_AUTH_FRAME_1 && |
| pRxAuthFrameBody->authTransactionSeqNumber != SIR_MAC_AUTH_FRAME_2 && |
| pRxAuthFrameBody->authTransactionSeqNumber != SIR_MAC_AUTH_FRAME_3) { |
| PELOGE(limLog(pMac, LOGE, FL("Workaround: Assign a correct seqNumber=4 " |
| "for AUTH frame 4"));) |
| pRxAuthFrameBody->authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_4; |
| } |
| |
| switch (pRxAuthFrameBody->authTransactionSeqNumber) |
| { |
| case SIR_MAC_AUTH_FRAME_1: |
| // AuthFrame 1 |
| |
| pStaDs = dphLookupHashEntry(pMac, pHdr->sa, |
| &assocId, &psessionEntry->dph.dphHashTable); |
| if (pStaDs) |
| { |
| tLimMlmDisassocReq *pMlmDisassocReq = NULL; |
| tLimMlmDeauthReq *pMlmDeauthReq = NULL; |
| tAniBool isConnected = eSIR_TRUE; |
| |
| pMlmDisassocReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq; |
| if (pMlmDisassocReq && |
| (vos_mem_compare((tANI_U8 *) pHdr->sa, |
| (tANI_U8 *) &pMlmDisassocReq->peerMacAddr, |
| sizeof(tSirMacAddr)))) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("TODO:Ack for disassoc " |
| "frame is pending Issue delsta for " |
| MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pMlmDisassocReq->peerMacAddr));) |
| limProcessDisassocAckTimeout(pMac); |
| isConnected = eSIR_FALSE; |
| } |
| pMlmDeauthReq = pMac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq; |
| if (pMlmDeauthReq && |
| (vos_mem_compare((tANI_U8 *) pHdr->sa, |
| (tANI_U8 *) &pMlmDeauthReq->peerMacAddr, |
| sizeof(tSirMacAddr)))) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("TODO:Ack for deauth frame " |
| "is pending Issue delsta for " |
| MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pMlmDeauthReq->peerMacAddr));) |
| limProcessDeauthAckTimeout(pMac); |
| isConnected = eSIR_FALSE; |
| } |
| |
| /* pStaDS != NULL and isConnected = 1 means the STA is already |
| * connected, But SAP received the Auth from that station. |
| * For non PMF connection, just delete the STA here as it will |
| * retry to connect back after timeout. |
| * |
| * For PMF connection the AP should not tear down or otherwise |
| * modify the state of the existing association until the |
| * SA-Query procedure determines that the original SA is |
| * invalid. |
| */ |
| if (isConnected |
| #ifdef WLAN_FEATURE_11W |
| && !pStaDs->rmfEnabled |
| #endif |
| ) |
| { |
| limLog(pMac, LOGE, |
| FL("STA is already connected but received auth frame" |
| "Send the Deauth and lim Delete Station Context" |
| "(staId: %d, assocId: %d) "), |
| pStaDs->staIndex, assocId); |
| limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); |
| goto free; |
| } |
| } |
| |
| /// Check if there exists pre-auth context for this STA |
| pAuthNode = limSearchPreAuthList(pMac, pHdr->sa); |
| if (pAuthNode) |
| { |
| /// Pre-auth context exists for the STA |
| if (pHdr->fc.retry == 0 || pAuthNode->seqNum != currSeqNum) |
| { |
| /** |
| * STA is initiating brand-new Authentication |
| * sequence after local Auth Response timeout. |
| * Or STA retrying to transmit First Auth frame due to packet drop OTA |
| * Delete Pre-auth node and fall through. |
| */ |
| if(pAuthNode->fTimerStarted) |
| { |
| limDeactivateAndChangePerStaIdTimer(pMac, |
| eLIM_AUTH_RSP_TIMER, |
| pAuthNode->authNodeIdx); |
| } |
| limLog(pMac, LOGW, FL("STA is initiating brand-new Authentication ...")); |
| limDeletePreAuthNode(pMac, |
| pHdr->sa); |
| /** |
| * SAP Mode:Disassociate the station and |
| * delete its entry if we have its entry |
| * already and received "auth" from the |
| * same station. |
| */ |
| |
| for (assocId = 0; assocId < psessionEntry->dph.dphHashTable.size; assocId++)// Softap dphHashTable.size = 8 |
| { |
| pStaDs = dphGetHashEntry(pMac, assocId, &psessionEntry->dph.dphHashTable); |
| |
| if (NULL == pStaDs) |
| continue; |
| |
| if (pStaDs->valid) |
| { |
| if (vos_mem_compare((tANI_U8 *) &pStaDs->staAddr, |
| (tANI_U8 *) &(pHdr->sa), (tANI_U8) (sizeof(tSirMacAddr))) ) |
| break; |
| } |
| |
| pStaDs = NULL; |
| } |
| |
| if (NULL != pStaDs |
| #ifdef WLAN_FEATURE_11W |
| && !pStaDs->rmfEnabled |
| #endif |
| ) |
| { |
| PELOGE(limLog(pMac, LOGE, |
| FL("lim Delete Station Context (staId: %d, assocId: %d) "), |
| pStaDs->staIndex, assocId);) |
| limSendDeauthMgmtFrame(pMac, |
| eSIR_MAC_UNSPEC_FAILURE_REASON, (tANI_U8 *) pAuthNode->peerMacAddr, psessionEntry, FALSE); |
| limTriggerSTAdeletion(pMac, pStaDs, psessionEntry); |
| goto free; |
| } |
| } |
| else |
| { |
| /* |
| * This can happen when first authentication frame is received |
| * but ACK lost at STA side, in this case 2nd auth frame is already |
| * in transmission queue |
| * */ |
| limLog(pMac, LOGW, FL("STA is initiating Authentication after ACK lost...")); |
| goto free; |
| } |
| } |
| if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_NUM_PRE_AUTH, |
| (tANI_U32 *) &maxNumPreAuth) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get MaxNumPreAuth |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve MaxNumPreAuth")); |
| } |
| if (pMac->lim.gLimNumPreAuthContexts == maxNumPreAuth && |
| !limDeleteOpenAuthPreAuthNode(pMac)) |
| { |
| PELOGE(limLog(pMac, LOGE, FL("Max number of preauth context reached"));) |
| /** |
| * Maximum number of pre-auth contexts |
| * reached. Send Authentication frame |
| * with unspecified failure |
| */ |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| goto free; |
| } |
| /// No Pre-auth context exists for the STA. |
| if (limIsAuthAlgoSupported( |
| pMac, |
| (tAniAuthType) |
| pRxAuthFrameBody->authAlgoNumber, psessionEntry)) |
| { |
| switch (pRxAuthFrameBody->authAlgoNumber) |
| { |
| case eSIR_OPEN_SYSTEM: |
| PELOGW(limLog(pMac, LOGW, FL("=======> eSIR_OPEN_SYSTEM ..."));) |
| /// Create entry for this STA in pre-auth list |
| pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| limLog(pMac, LOGW, |
| FL("Max pre-auth nodes reached ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGW); |
| goto free; |
| } |
| |
| PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %pK peer"), pAuthNode); |
| limPrintMacAddr(pMac, pHdr->sa, LOG1);) |
| |
| vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, |
| pHdr->sa, |
| sizeof(tSirMacAddr)); |
| |
| pAuthNode->mlmState = |
| eLIM_MLM_AUTHENTICATED_STATE; |
| pAuthNode->authType = (tAniAuthType) |
| pRxAuthFrameBody->authAlgoNumber; |
| pAuthNode->fSeen = 0; |
| pAuthNode->fTimerStarted = 0; |
| pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | |
| (pHdr->seqControl.seqNumLo)); |
| pAuthNode->timestamp = vos_timer_get_system_ticks(); |
| limAddPreAuthNode(pMac, pAuthNode); |
| |
| /** |
| * Send Authenticaton frame with Success |
| * status code. |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = eSIR_MAC_SUCCESS_STATUS; |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| /// Send Auth indication to SME |
| |
| vos_mem_copy((tANI_U8 *) mlmAuthInd.peerMacAddr, |
| (tANI_U8 *) pHdr->sa, |
| sizeof(tSirMacAddr)); |
| mlmAuthInd.authType = (tAniAuthType) |
| pRxAuthFrameBody->authAlgoNumber; |
| mlmAuthInd.sessionId = psessionEntry->smeSessionId; |
| |
| limPostSmeMessage(pMac, |
| LIM_MLM_AUTH_IND, |
| (tANI_U32 *) &mlmAuthInd); |
| break; |
| |
| case eSIR_SHARED_KEY: |
| PELOGW(limLog(pMac, LOGW, FL("=======> eSIR_SHARED_KEY ..."));) |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| val = psessionEntry->privacy; |
| } else if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, |
| &val) != eSIR_SUCCESS) { |
| /** |
| * Could not get Privacy option |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve Privacy option")); |
| } |
| cfgPrivacyOptImp = (tANI_U8)val; |
| if (!cfgPrivacyOptImp) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame for unsupported auth algorithm %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /** |
| * Authenticator does not have WEP |
| * implemented. |
| * Reject by sending Authentication frame |
| * with Auth algorithm not supported status |
| * code. |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| else |
| { |
| // Create entry for this STA |
| //in pre-auth list |
| pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| limLog(pMac, LOGW, |
| FL("Max pre-auth nodes reached ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGW); |
| |
| goto free; |
| } |
| |
| vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, |
| pHdr->sa, |
| sizeof(tSirMacAddr)); |
| |
| pAuthNode->mlmState = |
| eLIM_MLM_WT_AUTH_FRAME3_STATE; |
| pAuthNode->authType = |
| (tAniAuthType) |
| pRxAuthFrameBody->authAlgoNumber; |
| pAuthNode->fSeen = 0; |
| pAuthNode->fTimerStarted = 0; |
| pAuthNode->seqNum = |
| ((pHdr->seqControl.seqNumHi << 4) | |
| (pHdr->seqControl.seqNumLo)); |
| pAuthNode->timestamp = vos_timer_get_system_ticks(); |
| limAddPreAuthNode(pMac, pAuthNode); |
| |
| PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %pK id %d peer "), |
| pAuthNode, pAuthNode->authNodeIdx);) |
| PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) |
| |
| /// Create and activate Auth Response timer |
| if (tx_timer_change_context(&pAuthNode->timer, pAuthNode->authNodeIdx) != TX_SUCCESS) |
| { |
| /// Could not start Auth response timer. |
| // Log error |
| limLog(pMac, LOGP, |
| FL("Unable to chg context auth response timer for peer ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGP); |
| |
| /** |
| * Send Authenticaton frame with |
| * unspecified failure status code. |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_UNSPEC_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| limDeletePreAuthNode(pMac, pHdr->sa); |
| goto free; |
| } |
| |
| limActivateAuthRspTimer(pMac, pAuthNode); |
| |
| pAuthNode->fTimerStarted = 1; |
| |
| /* |
| * get random bytes and use as challenge text |
| */ |
| if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH ) ) ) |
| { |
| limLog(pMac, LOGE,FL("Challenge text preparation failed in limProcessAuthFrame")); |
| goto free; |
| } |
| |
| pChallenge = pAuthNode->challengeText; |
| |
| vos_mem_copy(pChallenge, |
| (tANI_U8 *) challengeTextArray, |
| sizeof(challengeTextArray)); |
| |
| /** |
| * Sending Authenticaton frame with challenge. |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_SUCCESS_STATUS; |
| authFrame->type = SIR_MAC_CHALLENGE_TEXT_EID; |
| authFrame->length = SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH; |
| vos_mem_copy(authFrame->challengeText, |
| pAuthNode->challengeText, |
| SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH); |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| } // if (wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) |
| |
| break; |
| |
| default: |
| // Log error |
| PELOGE( limLog(pMac, LOGE, |
| FL("received Auth frame for unsupported auth algorithm %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /** |
| * Responding party does not support the |
| * authentication algorithm requested by |
| * sending party. |
| * Reject by sending Authentication frame |
| * with auth algorithm not supported status code |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } // end switch(pRxAuthFrameBody->authAlgoNumber) |
| } // if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber)) |
| else |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame for unsupported auth algorithm %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /** |
| * Responding party does not support the |
| * authentication algorithm requested by sending party. |
| * Reject Authentication with StatusCode=13. |
| */ |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } //end if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber)) |
| break; |
| |
| case SIR_MAC_AUTH_FRAME_2: |
| // AuthFrame 2 |
| |
| if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME2_STATE) |
| { |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| /** |
| * Check if a Reassociation is in progress and this is a |
| * Pre-Auth frame |
| */ |
| if ((LIM_IS_STA_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_STA_ROLE(psessionEntry)) && |
| (psessionEntry->limSmeState == eLIM_SME_WT_REASSOC_STATE) && |
| (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) && |
| (psessionEntry->ftPEContext.pFTPreAuthReq != NULL) && |
| (vos_mem_compare( |
| psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, |
| pHdr->sa, sizeof(tSirMacAddr)))) |
| { |
| // Update the FTIEs in the saved auth response |
| PELOGW(limLog(pMac, LOGW, FL("received another PreAuth frame2" |
| " from peer " MAC_ADDRESS_STR" in Smestate %d"), |
| MAC_ADDR_ARRAY(pHdr->sa), psessionEntry->limSmeState);) |
| |
| psessionEntry->ftPEContext.saved_auth_rsp_length = 0; |
| if ((pBody != NULL) && (frameLen < MAX_FTIE_SIZE)) |
| { |
| vos_mem_copy(psessionEntry->ftPEContext.saved_auth_rsp, |
| pBody, frameLen); |
| psessionEntry->ftPEContext.saved_auth_rsp_length = frameLen; |
| } |
| } |
| else |
| #endif |
| { |
| /** |
| * Received Authentication frame2 in an unexpected state. |
| * Log error and ignore the frame. |
| */ |
| |
| // Log error |
| PELOG1(limLog(pMac, LOG1, |
| FL("received Auth frame2 from peer in state %d, addr "), |
| psessionEntry->limMlmState);) |
| PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) |
| } |
| |
| goto free; |
| |
| } |
| |
| if ( !vos_mem_compare((tANI_U8 *) pHdr->sa, |
| (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, |
| sizeof(tSirMacAddr)) ) |
| { |
| /** |
| * Received Authentication frame from an entity |
| * other than one request was initiated. |
| * Wait until Authentication Failure Timeout. |
| */ |
| |
| // Log error |
| PELOGW(limLog(pMac, LOGW, |
| FL("received Auth frame2 from unexpected peer " |
| MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| break; |
| } |
| |
| if (pRxAuthFrameBody->authStatusCode == |
| eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS) |
| { |
| /** |
| * Interoperability workaround: Linksys WAP4400N is returning |
| * wrong authType in OpenAuth response in case of |
| * SharedKey AP configuration. Pretend we don't see that, |
| * so upper layer can fallback to SharedKey authType, |
| * and successfully connect to the AP. |
| */ |
| if (pRxAuthFrameBody->authAlgoNumber != |
| pMac->lim.gpLimMlmAuthReq->authType) |
| { |
| pRxAuthFrameBody->authAlgoNumber = |
| pMac->lim.gpLimMlmAuthReq->authType; |
| } |
| } |
| |
| if (pRxAuthFrameBody->authAlgoNumber != |
| pMac->lim.gpLimMlmAuthReq->authType) |
| { |
| /** |
| * Received Authentication frame with an auth |
| * algorithm other than one requested. |
| * Wait until Authentication Failure Timeout. |
| */ |
| |
| // Log error |
| PELOGW(limLog(pMac, LOGW, |
| FL("received Auth frame2 for unexpected auth algo number %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| break; |
| } |
| |
| if (pRxAuthFrameBody->authStatusCode == |
| eSIR_MAC_SUCCESS_STATUS) |
| { |
| if (lim_process_fils_auth_frame2(pMac, psessionEntry, pRxAuthFrameBody)) |
| { |
| limRestoreFromAuthState(pMac, eSIR_SME_SUCCESS, |
| pRxAuthFrameBody->authStatusCode, psessionEntry); |
| goto free; |
| } |
| if (pRxAuthFrameBody->authAlgoNumber == |
| eSIR_OPEN_SYSTEM) |
| { |
| psessionEntry->limCurrentAuthType = eSIR_OPEN_SYSTEM; |
| |
| pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); |
| |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| limLog(pMac, LOGW, |
| FL("Max pre-auth nodes reached ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGW); |
| |
| goto free; |
| } |
| |
| PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %pK peer "), pAuthNode);) |
| PELOG1(limPrintMacAddr(pMac, pHdr->sa, LOG1);) |
| |
| vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, |
| pMac->lim.gpLimMlmAuthReq->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| pAuthNode->fTimerStarted = 0; |
| pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | |
| (pHdr->seqControl.seqNumLo)); |
| pAuthNode->authType = pMac->lim.gpLimMlmAuthReq->authType; |
| pAuthNode->timestamp = vos_timer_get_system_ticks(); |
| limAddPreAuthNode(pMac, pAuthNode); |
| |
| limRestoreFromAuthState(pMac, eSIR_SME_SUCCESS, |
| pRxAuthFrameBody->authStatusCode,psessionEntry); |
| } // if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) |
| else |
| { |
| // Shared key authentication |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| val = psessionEntry->privacy; |
| } else if (wlan_cfgGetInt(pMac, WNI_CFG_PRIVACY_ENABLED, |
| &val) != eSIR_SUCCESS) { |
| /** |
| * Could not get Privacy option |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve Privacy option")); |
| } |
| cfgPrivacyOptImp = (tANI_U8)val; |
| if (!cfgPrivacyOptImp) |
| { |
| /** |
| * Requesting STA does not have WEP implemented. |
| * Reject with unsupported authentication algorithm |
| * Status code and wait until auth failure timeout |
| */ |
| |
| // Log error |
| PELOGE( limLog(pMac, LOGE, |
| FL("received Auth frame from peer for unsupported auth algo %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| else |
| { |
| |
| if (pRxAuthFrameBody->type != |
| SIR_MAC_CHALLENGE_TEXT_EID) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame with invalid challenge text IE"));) |
| |
| goto free; |
| } |
| |
| /** |
| * Check if there exists a key mappping key |
| * for the STA that sent Authentication frame |
| */ |
| pKeyMapEntry = limLookUpKeyMappings( |
| pHdr->sa); |
| |
| if (pKeyMapEntry) |
| { |
| ((tpSirMacAuthFrameBody) plainBody)->authAlgoNumber = |
| sirSwapU16ifNeeded(pRxAuthFrameBody->authAlgoNumber); |
| ((tpSirMacAuthFrameBody) plainBody)->authTransactionSeqNumber = |
| sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1)); |
| ((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS; |
| ((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID; |
| ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length; |
| vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, |
| pRxAuthFrameBody->challengeText, |
| pRxAuthFrameBody->length); |
| encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length + |
| LIM_ENCR_AUTH_INFO_LEN); |
| if (!encrAuthFrame) { |
| limLog(pMac, LOGE, FL("failed to allocate memory")); |
| goto free; |
| } |
| vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length + |
| LIM_ENCR_AUTH_INFO_LEN, 0); |
| |
| limEncryptAuthFrame(pMac, 0, |
| pKeyMapEntry->key, |
| plainBody, |
| encrAuthFrame,key_length); |
| |
| psessionEntry->limMlmState = eLIM_MLM_WT_AUTH_FRAME4_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); |
| |
| limSendAuthMgmtFrame(pMac, |
| (tpSirMacAuthFrameBody) encrAuthFrame, |
| pHdr->sa, |
| pRxAuthFrameBody->length, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| break; |
| } // if (pKeyMapEntry) |
| else |
| { |
| if (wlan_cfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, |
| &val) != eSIR_SUCCESS) |
| { |
| /** |
| * Could not get Default keyId |
| * from CFG. Log error. |
| */ |
| limLog(pMac, LOGP, |
| FL("could not retrieve Default keyId")); |
| } |
| keyId = (tANI_U8)val; |
| |
| val = SIR_MAC_KEY_LENGTH; |
| |
| if (LIM_IS_AP_ROLE(psessionEntry)) { |
| tpSirKeys pKey; |
| pKey = &psessionEntry->WEPKeyMaterial[keyId].key[0]; |
| vos_mem_copy(defaultKey, pKey->key, pKey->keyLength); |
| } else if (wlan_cfgGetStr(pMac, |
| (tANI_U16) (WNI_CFG_WEP_DEFAULT_KEY_1 + keyId), |
| defaultKey, &val) != eSIR_SUCCESS) { |
| /// Could not get Default key from CFG. |
| //Log error. |
| limLog(pMac, LOGP, |
| FL("could not retrieve Default key")); |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| pRxAuthFrameBody->authTransactionSeqNumber + 1; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| limRestoreFromAuthState(pMac, eSIR_SME_INVALID_WEP_DEFAULT_KEY, |
| eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); |
| |
| break; |
| } |
| key_length=val; |
| ((tpSirMacAuthFrameBody) plainBody)->authAlgoNumber = |
| sirSwapU16ifNeeded(pRxAuthFrameBody->authAlgoNumber); |
| ((tpSirMacAuthFrameBody) plainBody)->authTransactionSeqNumber = |
| sirSwapU16ifNeeded((tANI_U16) (pRxAuthFrameBody->authTransactionSeqNumber + 1)); |
| ((tpSirMacAuthFrameBody) plainBody)->authStatusCode = eSIR_MAC_SUCCESS_STATUS; |
| ((tpSirMacAuthFrameBody) plainBody)->type = SIR_MAC_CHALLENGE_TEXT_EID; |
| ((tpSirMacAuthFrameBody) plainBody)->length = pRxAuthFrameBody->length; |
| vos_mem_copy((tANI_U8 *) ((tpSirMacAuthFrameBody) plainBody)->challengeText, |
| pRxAuthFrameBody->challengeText, |
| pRxAuthFrameBody->length); |
| |
| encrAuthFrame = vos_mem_malloc(pRxAuthFrameBody->length + |
| LIM_ENCR_AUTH_INFO_LEN); |
| if (!encrAuthFrame) { |
| limLog(pMac, LOGE, FL("failed to allocate memory")); |
| goto free; |
| } |
| vos_mem_set(encrAuthFrame, pRxAuthFrameBody->length + |
| LIM_ENCR_AUTH_INFO_LEN, 0); |
| |
| limEncryptAuthFrame(pMac, keyId, |
| defaultKey, |
| plainBody, |
| encrAuthFrame,key_length); |
| |
| psessionEntry->limMlmState = |
| eLIM_MLM_WT_AUTH_FRAME4_STATE; |
| MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); |
| |
| limSendAuthMgmtFrame(pMac, |
| (tpSirMacAuthFrameBody) encrAuthFrame, |
| pHdr->sa, |
| pRxAuthFrameBody->length, |
| psessionEntry, |
| eSIR_FALSE); |
| break; |
| } // end if (pKeyMapEntry) |
| } // end if (!wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED)) |
| } // end if (pRxAuthFrameBody->authAlgoNumber == eSIR_OPEN_SYSTEM) |
| } // if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) |
| else |
| { |
| /** |
| * Authentication failure. |
| * Return Auth confirm with received failure code to SME |
| */ |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame from peer with failure code %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authStatusCode, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| limRestoreFromAuthState(pMac, eSIR_SME_AUTH_REFUSED, |
| pRxAuthFrameBody->authStatusCode,psessionEntry); |
| } // end if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) |
| |
| break; |
| |
| case SIR_MAC_AUTH_FRAME_3: |
| // AuthFrame 3 |
| |
| if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame3 from peer with auth algo number %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /** |
| * Received Authentication frame3 with algorithm other than |
| * Shared Key authentication type. Reject with Auth frame4 |
| * with 'out of sequence' status code. |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| |
| if (LIM_IS_AP_ROLE(psessionEntry) || |
| LIM_IS_BT_AMP_AP_ROLE(psessionEntry) || |
| LIM_IS_IBSS_ROLE(psessionEntry)) { |
| /** |
| * Check if wep bit was set in FC. If not set, |
| * reject with Authentication frame4 with |
| * 'challenge failure' status code. |
| */ |
| if (!pHdr->fc.wep) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame3 from peer with no WEP bit set "MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| /// WEP bit is not set in FC of Auth Frame3 |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| |
| pAuthNode = limSearchPreAuthList(pMac, |
| pHdr->sa); |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| PELOGE(limLog(pMac, LOGW, |
| FL("received AuthFrame3 from peer that has no preauth context " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| /** |
| * No 'pre-auth' context exists for |
| * this STA that sent an Authentication |
| * frame3. |
| * Send Auth frame4 with 'out of sequence' |
| * status code. |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| |
| if (pAuthNode->mlmState == eLIM_MLM_AUTH_RSP_TIMEOUT_STATE) |
| { |
| // Log error |
| limLog(pMac, LOGW, |
| FL("auth response timer timedout for peer " |
| MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa)); |
| |
| /** |
| * Received Auth Frame3 after Auth Response timeout. |
| * Reject by sending Auth Frame4 with |
| * Auth respone timeout Status Code. |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_AUTH_RSP_TIMEOUT_STATUS; |
| |
| limSendAuthMgmtFrame( |
| pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| /// Delete pre-auth context of STA |
| limDeletePreAuthNode(pMac, |
| pHdr->sa); |
| |
| goto free; |
| } // end switch (pAuthNode->mlmState) |
| |
| if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS) |
| { |
| /** |
| * Received Authenetication Frame 3 with status code |
| * other than success. Wait until Auth response timeout |
| * to delete STA context. |
| */ |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame3 from peer with status code %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authStatusCode, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| goto free; |
| } |
| |
| /** |
| * Check if received challenge text is same as one sent in |
| * Authentication frame3 |
| */ |
| |
| if (vos_mem_compare(pRxAuthFrameBody->challengeText, |
| pAuthNode->challengeText, |
| SIR_MAC_SAP_AUTH_CHALLENGE_LENGTH)) |
| { |
| /// Challenge match. STA is autheticated ! |
| |
| /// Delete Authentication response timer if running |
| limDeactivateAndChangePerStaIdTimer(pMac, |
| eLIM_AUTH_RSP_TIMER, |
| pAuthNode->authNodeIdx); |
| |
| pAuthNode->fTimerStarted = 0; |
| pAuthNode->mlmState = eLIM_MLM_AUTHENTICATED_STATE; |
| |
| /** |
| * Send Authentication Frame4 with 'success' Status Code. |
| */ |
| authFrame->authAlgoNumber = eSIR_SHARED_KEY; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = eSIR_MAC_SUCCESS_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| |
| /// Send Auth indication to SME |
| vos_mem_copy((tANI_U8 *) mlmAuthInd.peerMacAddr, |
| (tANI_U8 *) pHdr->sa, |
| sizeof(tSirMacAddr)); |
| mlmAuthInd.authType = (tAniAuthType) |
| pRxAuthFrameBody->authAlgoNumber; |
| mlmAuthInd.sessionId = psessionEntry->smeSessionId; |
| |
| limPostSmeMessage(pMac, |
| LIM_MLM_AUTH_IND, |
| (tANI_U32 *) &mlmAuthInd); |
| |
| break; |
| } |
| else |
| { |
| // Log error |
| PELOGE( limLog(pMac, LOGW, |
| FL("Challenge failure for peer "MAC_ADDRESS_STR), |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| /** |
| * Challenge Failure. |
| * Send Authentication frame4 with 'challenge failure' |
| * status code and wait until Auth response timeout to |
| * delete STA context. |
| */ |
| |
| authFrame->authAlgoNumber = |
| pRxAuthFrameBody->authAlgoNumber; |
| authFrame->authTransactionSeqNumber = |
| SIR_MAC_AUTH_FRAME_4; |
| authFrame->authStatusCode = |
| eSIR_MAC_CHALLENGE_FAILURE_STATUS; |
| |
| limSendAuthMgmtFrame(pMac, authFrame, |
| pHdr->sa, |
| LIM_NO_WEP_IN_FC, |
| psessionEntry, |
| eSIR_FALSE); |
| goto free; |
| } |
| } // if (pMac->lim.gLimSystemRole == eLIM_AP_ROLE || ... |
| |
| break; |
| |
| case SIR_MAC_AUTH_FRAME_4: |
| // AuthFrame 4 |
| if (psessionEntry->limMlmState != eLIM_MLM_WT_AUTH_FRAME4_STATE) |
| { |
| /** |
| * Received Authentication frame4 in an unexpected state. |
| * Log error and ignore the frame. |
| */ |
| |
| // Log error |
| PELOG1(limLog(pMac, LOG1, |
| FL("received unexpected Auth frame4 from peer in state %d, addr " |
| MAC_ADDRESS_STR), psessionEntry->limMlmState, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| goto free; |
| } |
| |
| if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY) |
| { |
| /** |
| * Received Authentication frame4 with algorithm other than |
| * Shared Key authentication type. |
| * Wait until Auth failure timeout to report authentication |
| * failure to SME. |
| */ |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame4 from peer with invalid auth algo %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| goto free; |
| } |
| |
| if ( !vos_mem_compare((tANI_U8 *) pHdr->sa, |
| (tANI_U8 *) &pMac->lim.gpLimMlmAuthReq->peerMacAddr, |
| sizeof(tSirMacAddr)) ) |
| { |
| /** |
| * Received Authentication frame from an entity |
| * other than one to which request was initiated. |
| * Wait until Authentication Failure Timeout. |
| */ |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGW, |
| FL("received Auth frame4 from unexpected peer " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| break; |
| } |
| |
| if (pRxAuthFrameBody->authAlgoNumber != |
| pMac->lim.gpLimMlmAuthReq->authType) |
| { |
| /** |
| * Received Authentication frame with an auth algorithm |
| * other than one requested. |
| * Wait until Authentication Failure Timeout. |
| */ |
| |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Authentication frame from peer with invalid auth seq number %d " |
| MAC_ADDRESS_STR), pRxAuthFrameBody->authTransactionSeqNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| break; |
| } |
| |
| if (pRxAuthFrameBody->authStatusCode == |
| eSIR_MAC_SUCCESS_STATUS) |
| { |
| /** |
| * Authentication Success ! |
| * Inform SME of same. |
| */ |
| psessionEntry->limCurrentAuthType = eSIR_SHARED_KEY; |
| |
| pAuthNode = limAcquireFreePreAuthNode(pMac, &pMac->lim.gLimPreAuthTimerTable); |
| if (pAuthNode == NULL) |
| { |
| // Log error |
| limLog(pMac, LOGW, |
| FL("Max pre-auth nodes reached ")); |
| limPrintMacAddr(pMac, pHdr->sa, LOGW); |
| |
| goto free; |
| } |
| PELOG1(limLog(pMac, LOG1, FL("Alloc new data: %pK peer "), pAuthNode); |
| limPrintMacAddr(pMac, pHdr->sa, LOG1);) |
| |
| vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr, |
| pMac->lim.gpLimMlmAuthReq->peerMacAddr, |
| sizeof(tSirMacAddr)); |
| pAuthNode->fTimerStarted = 0; |
| pAuthNode->authType = pMac->lim.gpLimMlmAuthReq->authType; |
| pAuthNode->seqNum = ((pHdr->seqControl.seqNumHi << 4) | |
| (pHdr->seqControl.seqNumLo)); |
| pAuthNode->timestamp = vos_timer_get_system_ticks(); |
| limAddPreAuthNode(pMac, pAuthNode); |
| |
| limRestoreFromAuthState(pMac, eSIR_SME_SUCCESS, |
| pRxAuthFrameBody->authStatusCode,psessionEntry); |
| |
| } // if (pRxAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS) |
| else |
| { |
| /** |
| * Authentication failure. |
| * Return Auth confirm with received failure code to SME |
| */ |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGE, FL("Authentication failure from peer " |
| MAC_ADDRESS_STR), MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| limRestoreFromAuthState(pMac, eSIR_SME_AUTH_REFUSED, |
| pRxAuthFrameBody->authStatusCode,psessionEntry); |
| } // end if (pRxAuthFrameBody->Status == 0) |
| |
| break; |
| |
| default: |
| /// Invalid Authentication Frame received. Ignore it. |
| |
| // Log error |
| PELOGE(limLog(pMac, LOGE, |
| FL("received Auth frame from peer with invalid auth seq " |
| "number %d " MAC_ADDRESS_STR), |
| pRxAuthFrameBody->authTransactionSeqNumber, |
| MAC_ADDR_ARRAY(pHdr->sa));) |
| |
| break; |
| } // end switch (pRxAuthFrameBody->authTransactionSeqNumber) |
| |
| free: |
| if (authFrame) |
| vos_mem_free(authFrame); |
| if (rxAuthFrame) |
| vos_mem_free(rxAuthFrame); |
| if (encrAuthFrame) |
| vos_mem_free(encrAuthFrame); |
| if (plainBody) |
| vos_mem_free(plainBody); |
| if (challengeTextArray) |
| vos_mem_free(challengeTextArray); |
| |
| } /*** end limProcessAuthFrame() ***/ |
| |
| |
| |
| |
| |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| |
| /*---------------------------------------------------------------------- |
| * |
| * Pass the received Auth frame. This is possibly the pre-auth from the |
| * neighbor AP, in the same mobility domain. |
| * This will be used in case of 11r FT. |
| * |
| * !!!! This is going to be renoved for the next checkin. We will be creating |
| * the session before sending out the Auth. Thus when auth response |
| * is received we will have a session in progress. !!!!! |
| *---------------------------------------------------------------------- |
| */ |
| tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, void *body) |
| { |
| tpSirMacMgmtHdr pHdr; |
| tpPESession psessionEntry = NULL; |
| tANI_U8 *pBody; |
| tANI_U16 frameLen; |
| tSirMacAuthFrameBody *rxAuthFrame = NULL; |
| tSirMacAuthFrameBody *pRxAuthFrameBody = NULL; |
| tSirRetStatus ret_status = eSIR_FAILURE; |
| int i; |
| |
| pHdr = WDA_GET_RX_MAC_HEADER(pBd); |
| pBody = WDA_GET_RX_MPDU_DATA(pBd); |
| frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); |
| |
| limLog(pMac, LOG1, |
| FL("Auth Frame Received: BSSID "MAC_ADDRESS_STR" (RSSI %d)"), |
| MAC_ADDR_ARRAY(pHdr->bssId), |
| (uint)abs((tANI_S8)WDA_GET_RX_RSSI_NORMALIZED(pBd))); |
| |
| /* Auth frame has come on a new BSS, however, we need to find the session |
| * from where the auth-req was sent to the new AP |
| */ |
| for (i = 0; i < pMac->lim.maxBssId; i++) { |
| /* Find first free room in session table */ |
| if (pMac->lim.gpSession[i].valid == TRUE && |
| pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession == VOS_TRUE) { |
| /* Found the session */ |
| psessionEntry = &pMac->lim.gpSession[i]; |
| pMac->lim.gpSession[i].ftPEContext.ftPreAuthSession = VOS_FALSE; |
| } |
| } |
| |
| if (psessionEntry == NULL) |
| { |
| limLog(pMac, LOGE, |
| FL("Error: Unable to find session id while in pre-auth phase for FT")); |
| return eSIR_FAILURE; |
| } |
| |
| if (psessionEntry->ftPEContext.pFTPreAuthReq == NULL) |
| { |
| limLog(pMac, LOGE, FL("Error: No FT")); |
| // No FT in progress. |
| return eSIR_FAILURE; |
| } |
| |
| if (frameLen == 0) |
| { |
| limLog(pMac, LOGE, FL("Error: Frame len = 0")); |
| return eSIR_FAILURE; |
| } |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| limPrintMacAddr(pMac, pHdr->bssId, LOG2); |
| limPrintMacAddr(pMac, |
| psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, LOG2); |
| limLog(pMac,LOG2,FL("seqControl 0x%X"), |
| ((pHdr->seqControl.seqNumHi << 8) | |
| (pHdr->seqControl.seqNumLo << 4) | |
| (pHdr->seqControl.fragNum))); |
| #endif |
| |
| // Check that its the same bssId we have for preAuth |
| if (!vos_mem_compare(psessionEntry->ftPEContext.pFTPreAuthReq->preAuthbssId, |
| pHdr->bssId, sizeof( tSirMacAddr ))) |
| { |
| limLog(pMac, LOGE, FL("Error: Same bssid as preauth BSSID")); |
| // In this case SME if indeed has triggered a |
| // pre auth it will time out. |
| return eSIR_FAILURE; |
| } |
| |
| if (eANI_BOOLEAN_TRUE == |
| psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed) |
| { |
| /* |
| * This is likely a duplicate for the same pre-auth request. |
| * PE/LIM already posted a response to SME. Hence, drop it. |
| * TBD: |
| * 1) How did we even receive multiple auth responses? |
| * 2) Do we need to delete pre-auth session? Suppose we |
| * previously received an auth resp with failure which |
| * would not have created the session and forwarded to SME. |
| * And, we subsequently received an auth resp with success |
| * which would have created the session. This will now be |
| * dropped without being forwarded to SME! However, it is |
| * very unlikely to receive auth responses from the same |
| * AP with different reason codes. |
| * NOTE: return eSIR_SUCCESS so that the packet is dropped |
| * as this was indeed a response from the BSSID we tried to |
| * pre-auth. |
| */ |
| PELOGE(limLog(pMac,LOG1,"Auth rsp already posted to SME" |
| " (session %pK, FT session %pK)", psessionEntry, |
| psessionEntry);); |
| return eSIR_SUCCESS; |
| } |
| else |
| { |
| PELOGE(limLog(pMac,LOGW,"Auth rsp not yet posted to SME" |
| " (session %pK, FT session %pK)", psessionEntry, |
| psessionEntry);); |
| psessionEntry->ftPEContext.pFTPreAuthReq->bPreAuthRspProcessed = |
| eANI_BOOLEAN_TRUE; |
| } |
| |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| limLog(pMac, LOG1, FL("Pre-Auth response received from neighbor")); |
| limLog(pMac, LOG1, FL("Pre-Auth done state")); |
| #endif |
| // Stopping timer now, that we have our unicast from the AP |
| // of our choice. |
| limDeactivateAndChangeTimer(pMac, eLIM_FT_PREAUTH_RSP_TIMER); |
| |
| rxAuthFrame = vos_mem_malloc(sizeof(tSirMacAuthFrameBody)); |
| if (!rxAuthFrame) { |
| limLog(pMac, LOGE, FL("Failed to allocate memory")); |
| return eSIR_MEM_ALLOC_FAILED; |
| } |
| |
| |
| // Save off the auth resp. |
| if ((sirConvertAuthFrame2Struct(pMac, pBody, frameLen, rxAuthFrame) != eSIR_SUCCESS)) |
| { |
| limLog(pMac, LOGE, FL("failed to convert Auth frame to struct")); |
| limHandleFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, psessionEntry); |
| ret_status = eSIR_FAILURE; |
| goto free; |
| } |
| pRxAuthFrameBody = rxAuthFrame; |
| |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| PELOGE(limLog(pMac, LOG1, |
| FL("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"), |
| (tANI_U32) pRxAuthFrameBody->authAlgoNumber, |
| (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber, |
| (tANI_U32) pRxAuthFrameBody->authStatusCode,(tANI_U32)pMac->lim.gLimNumPreAuthContexts);) |
| #endif |
| |
| switch (pRxAuthFrameBody->authTransactionSeqNumber) |
| { |
| case SIR_MAC_AUTH_FRAME_2: |
| if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS) |
| { |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| PELOGE(limLog( pMac, LOGE, "Auth status code received is %d", |
| (tANI_U32) pRxAuthFrameBody->authStatusCode);); |
| #endif |
| if (eSIR_MAC_MAX_ASSOC_STA_REACHED_STATUS == pRxAuthFrameBody->authStatusCode) |
| ret_status = eSIR_LIM_MAX_STA_REACHED_ERROR; |
| } |
| else |
| { |
| ret_status = eSIR_SUCCESS; |
| } |
| break; |
| |
| default: |
| #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG |
| PELOGE(limLog( pMac, LOGE, "Seq. no incorrect expected 2 received %d", |
| (tANI_U32) pRxAuthFrameBody->authTransactionSeqNumber);) |
| #endif |
| break; |
| } |
| |
| // Send the Auth response to SME |
| limHandleFTPreAuthRsp(pMac, ret_status, pBody, frameLen, psessionEntry); |
| free: |
| if (rxAuthFrame) |
| vos_mem_free(rxAuthFrame); |
| |
| return ret_status; |
| } |
| |
| #endif /* WLAN_FEATURE_VOWIFI_11R */ |