blob: e80d3a18ffc041ad279f2c79b3f3223b5a6143a7 [file] [edit]
/******************************************************************************
*
* This file is provided under a dual license. When you use or
* distribute this software, you may choose to be licensed under
* version 2 of the GNU General Public License ("GPLv2 License")
* or BSD License.
*
* GPLv2 License
*
* Copyright(C) 2016 MediaTek Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See http://www.gnu.org/licenses/gpl-2.0.html for more details.
*
* BSD LICENSE
*
* Copyright(C) 2016 MediaTek Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
/*
* Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/auth.c#1
*/
/*! \file "auth.c"
* \brief This file includes the authentication-related functions.
*
* This file includes the authentication-related functions.
*/
/*******************************************************************************
* C O M P I L E R F L A G S
*******************************************************************************
*/
/*******************************************************************************
* E X T E R N A L R E F E R E N C E S
*******************************************************************************
*/
#include "precomp.h"
/*******************************************************************************
* C O N S T A N T S
*******************************************************************************
*/
/*******************************************************************************
* D A T A T Y P E S
*******************************************************************************
*/
/*******************************************************************************
* P U B L I C D A T A
*******************************************************************************
*/
struct APPEND_VAR_IE_ENTRY txAuthIETable[] = {
{(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), NULL,
authAddIEChallengeText},
{0, authCalculateRSNIELen, authAddRSNIE}, /* Element ID: 48 */
{(ELEM_HDR_LEN + 1), NULL, authAddMDIE}, /* Element ID: 54 */
{0, rsnCalculateFTIELen, rsnGenerateFTIE}, /* Element ID: 55 */
};
struct HANDLE_IE_ENTRY rxAuthIETable[] = {
{ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText}
};
/*******************************************************************************
* P R I V A T E D A T A
*******************************************************************************
*/
/*******************************************************************************
* M A C R O S
*******************************************************************************
*/
/*******************************************************************************
* F U N C T I O N D E C L A R A T I O N S
*******************************************************************************
*/
/*******************************************************************************
* F U N C T I O N S
*******************************************************************************
*/
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will compose the Authentication frame header and
* fixed fields.
*
* @param[in] pucBuffer Pointer to the frame buffer.
* @param[in] aucPeerMACAddress Given Peer MAC Address.
* @param[in] aucMACAddress Given Our MAC Address.
* @param[in] u2AuthAlgNum Authentication Algorithm Number
* @param[in] u2TransactionSeqNum Transaction Sequence Number
* @param[in] u2StatusCode Status Code
*
* \return (none)
*/
/*----------------------------------------------------------------------------*/
static __KAL_INLINE__ void
authComposeAuthFrameHeaderAndFF(IN struct ADAPTER *prAdapter,
IN struct STA_RECORD *prStaRec,
IN uint8_t *pucBuffer,
IN uint8_t aucPeerMACAddress[],
IN uint8_t aucMACAddress[],
IN uint16_t u2AuthAlgNum,
IN uint16_t u2TransactionSeqNum,
IN uint16_t u2StatusCode)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
uint16_t u2FrameCtrl;
#if CFG_SUPPORT_CFG80211_AUTH
struct CONNECTION_SETTINGS *prConnSettings;
prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
#endif
ASSERT(pucBuffer);
ASSERT(aucPeerMACAddress);
ASSERT(aucMACAddress);
prAuthFrame = (struct WLAN_AUTH_FRAME *)pucBuffer;
/* 4 <1> Compose the frame header of the Authentication frame. */
/* Fill the Frame Control field. */
u2FrameCtrl = MAC_FRAME_AUTH;
/* If this frame is the third frame in the shared key authentication
* sequence, it shall be encrypted.
*/
if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)
&& (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3))
u2FrameCtrl |= MASK_FC_PROTECTED_FRAME;
/* HW will also detect this bit for applying encryption */
/* WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); */
prAuthFrame->u2FrameCtrl = u2FrameCtrl;
/* NOTE(Kevin): Optimized for ARM */
/* Fill the DA field with Target BSSID. */
COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress);
/* Fill the SA field with our MAC Address. */
COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress);
if (prStaRec != NULL && IS_AP_STA(prStaRec)) {
/* Fill the BSSID field with Target BSSID. */
COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress);
} else {
/* Fill the BSSID field with Current BSSID. */
COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress);
}
/* Clear the SEQ/FRAG_NO field. */
prAuthFrame->u2SeqCtrl = 0;
/* 4 <2> Compose the frame body's fixed field part of
* the Authentication frame.
*/
/* Fill the Authentication Algorithm Number field. */
/* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); */
prAuthFrame->u2AuthAlgNum = u2AuthAlgNum;
/* NOTE(Kevin): Optimized for ARM */
#if CFG_SUPPORT_CFG80211_AUTH
if ((prConnSettings->ucAuthDataLen != 0) &&
prStaRec &&
!IS_STA_IN_P2P(prStaRec)) {
kalMemCopy(prAuthFrame->aucAuthData,
prConnSettings->aucAuthData,
prConnSettings->ucAuthDataLen);
} else {
/* Fill the Authentication Transaction Sequence Number field. */
/* NOTE(Kevin): Optimized for ARM */
prAuthFrame->aucAuthData[0] = (uint8_t)
(u2TransactionSeqNum & 0xff);
prAuthFrame->aucAuthData[1] = (uint8_t)
((u2TransactionSeqNum >> 8) & 0xff);
/* Fill the Status Code field. */
/* NOTE(Kevin): Optimized for ARM */
prAuthFrame->aucAuthData[2] = (uint8_t)(u2StatusCode & 0xff);
prAuthFrame->aucAuthData[3] = (uint8_t)
((u2StatusCode >> 8) & 0xff);
}
DBGLOG(SAA, INFO, "Compose auth with TransSN = %d,Status = %d\n",
prAuthFrame->aucAuthData[0], prAuthFrame->aucAuthData[2]);
#else
/* Fill the Authentication Transaction Sequence Number field. */
/* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo,
* u2TransactionSeqNum);
*/
prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum;
/* NOTE(Kevin): Optimized for ARM */
/* Fill the Status Code field. */
/* WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); */
prAuthFrame->u2StatusCode = u2StatusCode;
/* NOTE(Kevin): Optimized for ARM */
#endif
} /* end of authComposeAuthFrameHeaderAndFF() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will append Challenge Text IE to the Authentication
* frame
*
* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T.
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void authAddIEChallengeText(IN struct ADAPTER *prAdapter,
IN OUT struct MSDU_INFO *prMsduInfo)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
struct STA_RECORD *prStaRec;
uint16_t u2TransactionSeqNum;
ASSERT(prMsduInfo);
prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
if (!prStaRec)
return;
ASSERT(prStaRec);
/* For Management, frame header and payload are in a continuous
* buffer
*/
prAuthFrame = (struct WLAN_AUTH_FRAME *)prMsduInfo->prPacket;
#if CFG_SUPPORT_CFG80211_AUTH
WLAN_GET_FIELD_16(&prAuthFrame->aucAuthData[0], &u2TransactionSeqNum)
#else
WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum)
#endif
/* Only consider SEQ_3 for Challenge Text */
if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) &&
(prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)
&& (prStaRec->prChallengeText != NULL)) {
COPY_IE(((unsigned long)(prMsduInfo->prPacket) +
prMsduInfo->u2FrameLength),
(prStaRec->prChallengeText));
prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText);
}
return;
} /* end of authAddIEChallengeText() */
#if !CFG_SUPPORT_AAA
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will send the Authenticiation frame
*
* @param[in] prStaRec Pointer to the STA_RECORD_T
* @param[in] u2TransactionSeqNum Transaction Sequence Number
*
* @retval WLAN_STATUS_RESOURCES No available resource for frame composing.
* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module
*/
/*----------------------------------------------------------------------------*/
uint32_t authSendAuthFrame(IN struct ADAPTER *prAdapter,
IN struct STA_RECORD *prStaRec,
IN uint16_t u2TransactionSeqNum)
{
struct MSDU_INFO *prMsduInfo;
struct BSS_INFO *prBssInfo;
uint16_t u2EstimatedFrameLen;
uint16_t u2EstimatedExtraIELen;
uint16_t u2PayloadLen;
uint32_t i;
DBGLOG(SAA, LOUD, "Send Auth Frame\n");
ASSERT(prStaRec);
/* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */
/* Init with MGMT Header Length + Length of Fixed Fields */
u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD +
WLAN_MAC_MGMT_HEADER_LEN +
AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN +
STATUS_CODE_FIELD_LEN);
/* + Extra IE Length */
u2EstimatedExtraIELen = 0;
for (i = 0;
i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY);
i++) {
if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0)
u2EstimatedExtraIELen +=
txAssocRespIETable[i].u2EstimatedFixedIELen;
else if (txAssocRespIETable[i].pfnCalculateVariableIELen !=
NULL)
u2EstimatedExtraIELen +=
(uint16_t)txAssocRespIETable[i]
.pfnCalculateVariableIELen(
prAdapter, prStaRec->ucBssIndex,
prStaRec);
}
u2EstimatedFrameLen += u2EstimatedExtraIELen;
/* Allocate a MSDU_INFO_T */
prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen);
if (prMsduInfo == NULL) {
DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n");
return WLAN_STATUS_RESOURCES;
}
/* 4 <2> Compose Authentication Request frame header and fixed fields
* in MSDU_INfO_T.
*/
ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum);
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex)
/* Compose Header and some Fixed Fields */
authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (uint8_t *)
((uint32_t) (prMsduInfo->prPacket) +
MAC_TX_RESERVED_FIELD),
prStaRec->aucMacAddr,
prBssInfo->aucOwnMacAddr,
prStaRec->ucAuthAlgNum,
u2TransactionSeqNum,
STATUS_CODE_RESERVED);
u2PayloadLen =
(AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN);
/* 4 <3> Update information of MSDU_INFO_T */
TX_SET_MMPDU(prAdapter,
prMsduInfo,
prStaRec->ucBssIndex,
prStaRec->ucIndex,
WLAN_MAC_MGMT_HEADER_LEN,
WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen,
saaFsmRunEventTxDone, MSDU_RATE_MODE_AUTO);
/* 4 <4> Compose IEs in MSDU_INFO_T */
for (i = 0; i < sizeof(txAuthIETable) / sizeof(struct APPEND_IE_ENTRY);
i++) {
if (txAuthIETable[i].pfnAppendIE)
txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo);
}
/* TODO(Kevin):
* Also release the unused tail room of the composed MMPDU
*/
nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE);
/* 4 <6> Inform TXM to send this Authentication frame. */
nicTxEnqueueMsdu(prAdapter, prMsduInfo);
return WLAN_STATUS_SUCCESS;
} /* end of authSendAuthFrame() */
#else
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will send the Authenticiation frame
*
* @param[in] prStaRec Pointer to the STA_RECORD_T
* @param[in] u2TransactionSeqNum Transaction Sequence Number
*
* @retval WLAN_STATUS_RESOURCES No available resource for frame composing.
* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module
*/
/*----------------------------------------------------------------------------*/
uint32_t
authSendAuthFrame(IN struct ADAPTER *prAdapter,
IN struct STA_RECORD *prStaRec,
IN uint8_t ucBssIndex,
IN struct SW_RFB *prFalseAuthSwRfb,
IN uint16_t u2TransactionSeqNum, IN uint16_t u2StatusCode)
{
uint8_t *pucReceiveAddr;
uint8_t *pucTransmitAddr;
struct MSDU_INFO *prMsduInfo;
struct BSS_INFO *prBssInfo;
/*get from input parameter */
/* ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; */
PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL;
uint16_t u2EstimatedFrameLen;
uint16_t u2EstimatedExtraIELen;
uint16_t u2PayloadLen;
uint16_t ucAuthAlgNum;
uint32_t i;
#if CFG_SUPPORT_CFG80211_AUTH
struct CONNECTION_SETTINGS *prConnSettings;
prConnSettings = &(prAdapter->rWifiVar.rConnSettings);
#endif
DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n",
u2TransactionSeqNum, u2StatusCode);
#if CFG_SUPPORT_CFG80211_AUTH
if (prStaRec && !IS_STA_IN_P2P(prStaRec) &&
(prConnSettings->ucAuthDataLen != 0)) {
DBGLOG(SAA, INFO, "prConnSettings->ucAuthDataLen = %d\n",
prConnSettings->ucAuthDataLen);
u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD +
WLAN_MAC_MGMT_HEADER_LEN +
AUTH_ALGORITHM_NUM_FIELD_LEN +
prConnSettings->ucAuthDataLen);
} else
u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD +
WLAN_MAC_MGMT_HEADER_LEN +
AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN +
STATUS_CODE_FIELD_LEN);
#else
/* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */
/* Init with MGMT Header Length + Length of Fixed Fields */
u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD +
WLAN_MAC_MGMT_HEADER_LEN +
AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN +
STATUS_CODE_FIELD_LEN);
#endif
/* + Extra IE Length */
u2EstimatedExtraIELen = 0;
for (i = 0;
i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY);
i++) {
if (txAuthIETable[i].u2EstimatedFixedIELen != 0)
u2EstimatedExtraIELen +=
txAuthIETable[i].u2EstimatedFixedIELen;
else
u2EstimatedExtraIELen +=
txAuthIETable[i].pfnCalculateVariableIELen(
prAdapter, ucBssIndex, prStaRec);
}
u2EstimatedFrameLen += u2EstimatedExtraIELen;
/* Allocate a MSDU_INFO_T */
prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen);
if (prMsduInfo == NULL) {
DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n");
return WLAN_STATUS_RESOURCES;
}
/* 4 <2> Compose Authentication Request frame header and
* fixed fields in MSDU_INfO_T.
*/
if (prStaRec) {
ASSERT(prStaRec->ucBssIndex <= prAdapter->ucHwBssIdNum);
prBssInfo =
GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex);
pucTransmitAddr = prBssInfo->aucOwnMacAddr;
pucReceiveAddr = prStaRec->aucMacAddr;
ucAuthAlgNum = prStaRec->ucAuthAlgNum;
#if CFG_SUPPORT_CFG80211_AUTH
if (IS_AP_STA(prStaRec)) /* STA mode */
pfTxDoneHandler = saaFsmRunEventTxDone;
else if (IS_CLIENT_STA(prStaRec))
pfTxDoneHandler = aaaFsmRunEventTxDone;
else {
DBGLOG(SAA, WARN,
"Can't send auth with unsupport peer's StaType:%d\n",
prStaRec->eStaType);
return WLAN_STATUS_FAILURE;
}
#else
switch (u2TransactionSeqNum) {
case AUTH_TRANSACTION_SEQ_1:
case AUTH_TRANSACTION_SEQ_3:
pfTxDoneHandler = saaFsmRunEventTxDone;
break;
case AUTH_TRANSACTION_SEQ_2:
case AUTH_TRANSACTION_SEQ_4:
pfTxDoneHandler = aaaFsmRunEventTxDone;
break;
}
#endif
} else { /* For Error Status Code */
struct WLAN_AUTH_FRAME *prFalseAuthFrame;
ASSERT(prFalseAuthSwRfb);
prFalseAuthFrame =
(struct WLAN_AUTH_FRAME *)prFalseAuthSwRfb->pvHeader;
ASSERT((u2StatusCode != STATUS_CODE_SUCCESSFUL) &&
(u2StatusCode != WLAN_STATUS_SAE_HASH_TO_ELEMENT));
pucTransmitAddr = prFalseAuthFrame->aucDestAddr;
pucReceiveAddr = prFalseAuthFrame->aucSrcAddr;
ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum;
#if CFG_SUPPORT_CFG80211_AUTH
u2TransactionSeqNum = (prFalseAuthFrame->aucAuthData[1] << 8) +
(prFalseAuthFrame->aucAuthData[0] + 1);
#else
u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1);
#endif
}
/* Compose Header and some Fixed Fields */
authComposeAuthFrameHeaderAndFF(prAdapter, prStaRec, (uint8_t *)
((unsigned long)(prMsduInfo->prPacket) +
MAC_TX_RESERVED_FIELD), pucReceiveAddr,
pucTransmitAddr, ucAuthAlgNum,
u2TransactionSeqNum, u2StatusCode);
/* fill the length of auth frame body */
#if CFG_SUPPORT_CFG80211_AUTH
if (prStaRec && !IS_STA_IN_P2P(prStaRec) &&
(prConnSettings->ucAuthDataLen != 0))
u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN +
prConnSettings->ucAuthDataLen);
else
u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN +
STATUS_CODE_FIELD_LEN);
#else
u2PayloadLen =
(AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN);
#endif
/* 4 <3> Update information of MSDU_INFO_T */
TX_SET_MMPDU(prAdapter,
prMsduInfo,
ucBssIndex,
(prStaRec !=
NULL) ? (prStaRec->ucIndex) : (STA_REC_INDEX_NOT_FOUND),
WLAN_MAC_MGMT_HEADER_LEN,
WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen, pfTxDoneHandler,
MSDU_RATE_MODE_AUTO);
if ((ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)
&& (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3))
nicTxConfigPktOption(prMsduInfo, MSDU_OPT_PROTECTED_FRAME,
TRUE);
/* 4 <4> Compose IEs in MSDU_INFO_T */
for (i = 0;
i < sizeof(txAuthIETable) / sizeof(struct APPEND_VAR_IE_ENTRY);
i++) {
if (txAuthIETable[i].pfnAppendIE)
txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo);
}
/* TODO(Kevin):
* Also release the unused tail room of the composed MMPDU
*/
nicTxConfigPktControlFlag(prMsduInfo, MSDU_CONTROL_FLAG_FORCE_TX, TRUE);
/* 4 <6> Inform TXM to send this Authentication frame. */
nicTxEnqueueMsdu(prAdapter, prMsduInfo);
DBGLOG(SAA, INFO,
"Send Auth Frame, TranSeq: %d, Status: %d, Seq: %d\n",
u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum);
return WLAN_STATUS_SUCCESS;
} /* end of authSendAuthFrame() */
#endif /* CFG_SUPPORT_AAA */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will strictly check the TX Authentication frame
* for SAA/AAA event handling.
*
* @param[in] prMsduInfo Pointer of MSDU_INFO_T
* @param[in] u2TransactionSeqNum Transaction Sequence Number
*
* @retval WLAN_STATUS_FAILURE This is not the frame we should handle
* at current state.
* @retval WLAN_STATUS_SUCCESS This is the frame we should handle.
*/
/*----------------------------------------------------------------------------*/
uint32_t authCheckTxAuthFrame(IN struct ADAPTER *prAdapter,
IN struct MSDU_INFO *prMsduInfo,
IN uint16_t u2TransactionSeqNum)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
struct STA_RECORD *prStaRec;
uint16_t u2TxFrameCtrl;
uint16_t u2TxAuthAlgNum;
uint16_t u2TxTransactionSeqNum;
ASSERT(prMsduInfo);
prAuthFrame = (struct WLAN_AUTH_FRAME *)(prMsduInfo->prPacket);
ASSERT(prAuthFrame);
prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
ASSERT(prStaRec);
if (!prStaRec)
return WLAN_STATUS_INVALID_PACKET;
/* WLAN_GET_FIELD_16(&prAuthFrame->u2FrameCtrl, &u2TxFrameCtrl) */
u2TxFrameCtrl = prAuthFrame->u2FrameCtrl;
/* NOTE(Kevin): Optimized for ARM */
u2TxFrameCtrl &= MASK_FRAME_TYPE;
if (u2TxFrameCtrl != MAC_FRAME_AUTH)
return WLAN_STATUS_FAILURE;
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2TxAuthAlgNum) */
u2TxAuthAlgNum = prAuthFrame->u2AuthAlgNum;
/* NOTE(Kevin): Optimized for ARM */
if (u2TxAuthAlgNum != (uint16_t) (prStaRec->ucAuthAlgNum))
return WLAN_STATUS_FAILURE;
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo,
* &u2TxTransactionSeqNum)
*/
#if CFG_SUPPORT_CFG80211_AUTH
u2TxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) +
prAuthFrame->aucAuthData[0];
#else
u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo;
#endif
/* NOTE(Kevin): Optimized for ARM */
if (u2TxTransactionSeqNum != u2TransactionSeqNum)
return WLAN_STATUS_FAILURE;
return WLAN_STATUS_SUCCESS;
} /* end of authCheckTxAuthFrame() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will check the incoming Auth Frame's Transaction
* Sequence Number before delivering it to the corresponding
* SAA or AAA Module.
*
* @param[in] prSwRfb Pointer to the SW_RFB_T structure.
*
* @retval WLAN_STATUS_SUCCESS Always not retain authentication frames
*/
/*----------------------------------------------------------------------------*/
uint32_t authCheckRxAuthFrameTransSeq(IN struct ADAPTER *prAdapter,
IN struct SW_RFB *prSwRfb)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
uint16_t u2RxTransactionSeqNum;
uint16_t u2MinPayloadLen;
#if CFG_SUPPORT_SAE
#if CFG_IGNORE_INVALID_AUTH_TSN
struct STA_RECORD *prStaRec;
#endif
struct BSS_INFO *prBssInfo = NULL;
#endif
ASSERT(prSwRfb);
/* 4 <1> locate the Authentication Frame. */
prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader;
/* 4 <2> Parse the Header of Authentication Frame. */
u2MinPayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN +
STATUS_CODE_FIELD_LEN);
if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < u2MinPayloadLen) {
DBGLOG(SAA, WARN,
"Rx Auth payload: len[%u] < min expected len[%u]\n",
(prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen),
u2MinPayloadLen);
DBGLOG(SAA, WARN, "=== Dump Rx Auth ===\n");
DBGLOG_MEM8(SAA, WARN, prAuthFrame, prSwRfb->u2PacketLen);
return WLAN_STATUS_SUCCESS;
}
/* 4 <3> Parse the Fixed Fields of Authentication Frame Body. */
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo,
* &u2RxTransactionSeqNum);
*/
#if CFG_SUPPORT_CFG80211_AUTH
u2RxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) +
prAuthFrame->aucAuthData[0];
#else
u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo;
/* NOTE(Kevin): Optimized for ARM */
#endif
if ((u2RxTransactionSeqNum < 0) || (u2RxTransactionSeqNum > 4)) {
DBGLOG(SAA, WARN,
"RX auth with unexpected TransactionSeqNum:%d\n",
u2RxTransactionSeqNum);
return WLAN_STATUS_SUCCESS;
}
#if CFG_SUPPORT_SAE
if (prAuthFrame->u2AuthAlgNum == AUTH_ALGORITHM_NUM_SAE) {
if ((u2RxTransactionSeqNum ==
AUTH_TRANSACTION_SEQ_1) ||
(u2RxTransactionSeqNum ==
AUTH_TRANSACTION_SEQ_2)) {
prStaRec = prSwRfb->prStaRec;
if (prStaRec)
prBssInfo =
GET_BSS_INFO_BY_INDEX(
prAdapter,
prStaRec->ucBssIndex);
else
prBssInfo =
p2pFuncBSSIDFindBssInfo(
prAdapter,
prAuthFrame->aucBSSID);
if (prBssInfo == NULL)
return WLAN_STATUS_SUCCESS;
if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)
saaFsmRunEventRxAuth(prAdapter, prSwRfb);
#if CFG_SUPPORT_AAA
else if (prBssInfo->eCurrentOPMode ==
OP_MODE_ACCESS_POINT)
aaaFsmRunEventRxAuth(prAdapter, prSwRfb);
#endif
else
DBGLOG(SAA, WARN,
"Don't support SAE for non-AIS/P2P network\n");
} else {
DBGLOG(SAA, WARN,
"RX SAE auth with unexpected TransSeqNum:%d\n",
u2RxTransactionSeqNum);
}
} else {
#endif
switch (u2RxTransactionSeqNum) {
case AUTH_TRANSACTION_SEQ_2:
case AUTH_TRANSACTION_SEQ_4:
saaFsmRunEventRxAuth(prAdapter, prSwRfb);
break;
case AUTH_TRANSACTION_SEQ_1:
case AUTH_TRANSACTION_SEQ_3:
#if CFG_SUPPORT_AAA
aaaFsmRunEventRxAuth(prAdapter, prSwRfb);
#endif /* CFG_SUPPORT_AAA */
break;
default:
DBGLOG(SAA, WARN,
"Strange Authentication Packet: Auth Trans Seq No = %d\n",
u2RxTransactionSeqNum);
}
#if CFG_SUPPORT_SAE
}
#endif
return WLAN_STATUS_SUCCESS;
} /* end of authCheckRxAuthFrameTransSeq() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will validate the incoming Authentication Frame and
* take the status code out.
*
* @param[in] prSwRfb Pointer to SW RFB data structure.
* @param[in] u2TransactionSeqNum Transaction Sequence Number
* @param[out] pu2StatusCode Pointer to store the Status Code from
* Authentication.
*
* @retval WLAN_STATUS_FAILURE This is not the frame we should handle
* at current state.
* @retval WLAN_STATUS_SUCCESS This is the frame we should handle.
*/
/*----------------------------------------------------------------------------*/
uint32_t
authCheckRxAuthFrameStatus(IN struct ADAPTER *prAdapter,
IN struct SW_RFB *prSwRfb,
IN uint16_t u2TransactionSeqNum,
OUT uint16_t *pu2StatusCode)
{
struct STA_RECORD *prStaRec;
struct WLAN_AUTH_FRAME *prAuthFrame;
uint16_t u2RxAuthAlgNum;
uint16_t u2RxTransactionSeqNum;
/* UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM */
ASSERT(prSwRfb);
ASSERT(pu2StatusCode);
prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
ASSERT(prStaRec);
if (!prStaRec)
return WLAN_STATUS_INVALID_PACKET;
/* 4 <1> locate the Authentication Frame. */
prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader;
/* 4 <2> Parse the Fixed Fields of Authentication Frame Body. */
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2RxAuthAlgNum); */
u2RxAuthAlgNum = prAuthFrame->u2AuthAlgNum;
/* NOTE(Kevin): Optimized for ARM */
if (u2RxAuthAlgNum != (uint16_t) prStaRec->ucAuthAlgNum) {
DBGLOG(SAA, WARN,
"Discard Auth frame with auth type = %d, current = %d\n",
u2RxAuthAlgNum, prStaRec->ucAuthAlgNum);
*pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED;
return WLAN_STATUS_SUCCESS;
}
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo,
* &u2RxTransactionSeqNum);
*/
#if CFG_SUPPORT_CFG80211_AUTH
u2RxTransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) +
prAuthFrame->aucAuthData[0];
/* Still report to upper layer to let it do the error handling */
if (u2RxTransactionSeqNum < u2TransactionSeqNum) {
DBGLOG(SAA, WARN,
"Rx Auth frame with unexpected Transaction Seq No = %d\n",
u2RxTransactionSeqNum);
*pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ;
return WLAN_STATUS_FAILURE;
}
#else
u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo;
/* NOTE(Kevin): Optimized for ARM */
if (u2RxTransactionSeqNum != u2TransactionSeqNum) {
DBGLOG(SAA, WARN,
"Discard Auth frame with Transaction Seq No = %d\n",
u2RxTransactionSeqNum);
*pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ;
return WLAN_STATUS_FAILURE;
}
#endif
/* 4 <3> Get the Status code */
/* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */
/* *pu2StatusCode = u2RxStatusCode; */
#if CFG_SUPPORT_CFG80211_AUTH
*pu2StatusCode = (prAuthFrame->aucAuthData[3] << 8) +
prAuthFrame->aucAuthData[2];
#else
*pu2StatusCode = prAuthFrame->u2StatusCode;
/* NOTE(Kevin): Optimized for ARM */
#endif
DBGLOG(SAA, INFO,
"Rx Auth frame with auth type = %d, SN = %d, Status Code = %d\n",
u2RxAuthAlgNum, u2RxTransactionSeqNum, *pu2StatusCode);
return WLAN_STATUS_SUCCESS;
} /* end of authCheckRxAuthFrameStatus() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will handle the Challenge Text IE from
* the Authentication frame
*
* @param[in] prSwRfb Pointer to SW RFB data structure.
* @param[in] prIEHdr Pointer to start address of IE
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
void authHandleIEChallengeText(struct ADAPTER *prAdapter,
struct SW_RFB *prSwRfb, struct IE_HDR *prIEHdr)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
struct STA_RECORD *prStaRec;
uint16_t u2TransactionSeqNum;
ASSERT(prSwRfb);
ASSERT(prIEHdr);
prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
ASSERT(prStaRec);
if (!prStaRec)
return;
/* For Management, frame header and payload are in
* a continuous buffer
*/
prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader;
/* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo,
* &u2TransactionSeqNum)
*/
#if CFG_SUPPORT_CFG80211_AUTH
u2TransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) +
prAuthFrame->aucAuthData[0];
#else
u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo;
/* NOTE(Kevin): Optimized for ARM */
#endif
/* Only consider SEQ_2 for Challenge Text */
if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) &&
(prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) {
/* Free previous allocated TCM memory */
if (prStaRec->prChallengeText) {
/* ASSERT(0); */
cnmMemFree(prAdapter, prStaRec->prChallengeText);
prStaRec->prChallengeText =
(struct IE_CHALLENGE_TEXT *)NULL;
}
prStaRec->prChallengeText =
cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr));
if (prStaRec->prChallengeText == NULL)
return;
/* Save the Challenge Text from Auth Seq 2 Frame,
* before sending Auth Seq 3 Frame
*/
COPY_IE(prStaRec->prChallengeText, prIEHdr);
}
return;
} /* end of authAddIEChallengeText() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will parse and process the incoming Authentication
* frame.
*
* @param[in] prSwRfb Pointer to SW RFB data structure.
*
* @retval WLAN_STATUS_SUCCESS This is the frame we should handle.
*/
/*----------------------------------------------------------------------------*/
uint32_t authProcessRxAuth2_Auth4Frame(IN struct ADAPTER *prAdapter,
IN struct SW_RFB *prSwRfb)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
uint8_t *pucIEsBuffer;
uint16_t u2IEsLen;
uint16_t u2Offset;
uint8_t ucIEID;
uint32_t i;
uint16_t u2TransactionSeqNum;
ASSERT(prSwRfb);
prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader;
#if CFG_SUPPORT_CFG80211_AUTH
pucIEsBuffer = (uint8_t *)&prAuthFrame->aucAuthData[0] + 4;
#else
pucIEsBuffer = &prAuthFrame->aucInfoElem[0];
#endif
u2IEsLen = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) -
(AUTH_ALGORITHM_NUM_FIELD_LEN +
AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN);
IE_FOR_EACH(pucIEsBuffer, u2IEsLen, u2Offset) {
ucIEID = IE_ID(pucIEsBuffer);
for (i = 0;
i <
(sizeof(rxAuthIETable) / sizeof(struct HANDLE_IE_ENTRY));
i++) {
if ((ucIEID == rxAuthIETable[i].ucElemID)
&& (rxAuthIETable[i].pfnHandleIE != NULL))
rxAuthIETable[i].pfnHandleIE(prAdapter,
prSwRfb,
(struct IE_HDR *)pucIEsBuffer);
}
}
#if CFG_SUPPORT_CFG80211_AUTH
u2TransactionSeqNum = (prAuthFrame->aucAuthData[1] << 8) +
prAuthFrame->aucAuthData[0];
#else
u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo;
/* NOTE(Kevin): Optimized for ARM */
#endif
if (prAuthFrame->u2AuthAlgNum ==
AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) {
if (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_4) {
/* todo: check MIC, if mic error, return
* WLAN_STATUS_FAILURE
*/
} else if (u2TransactionSeqNum ==
AUTH_TRANSACTION_SEQ_2) {
prAdapter->prGlueInfo->rFtEventParam.ies =
&prAuthFrame->aucInfoElem[0];
prAdapter->prGlueInfo->rFtEventParam.ies_len = u2IEsLen;
}
}
return WLAN_STATUS_SUCCESS;
} /* end of authProcessRxAuth2_Auth4Frame() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will compose the Deauthentication frame
*
* @param[in] pucBuffer Pointer to the frame buffer.
* @param[in] aucPeerMACAddress Given Peer MAC Address.
* @param[in] aucMACAddress Given Our MAC Address.
* @param[in] u2StatusCode Status Code
*
* @return (none)
*/
/*----------------------------------------------------------------------------*/
static __KAL_INLINE__ void
authComposeDeauthFrameHeaderAndFF(IN uint8_t *pucBuffer,
IN uint8_t aucPeerMACAddress[],
IN uint8_t aucMACAddress[],
IN uint8_t aucBssid[],
IN uint16_t u2ReasonCode)
{
struct WLAN_DEAUTH_FRAME *prDeauthFrame;
uint16_t u2FrameCtrl;
ASSERT(pucBuffer);
ASSERT(aucPeerMACAddress);
ASSERT(aucMACAddress);
ASSERT(aucBssid);
prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)pucBuffer;
/* 4 <1> Compose the frame header of the Deauthentication frame. */
/* Fill the Frame Control field. */
u2FrameCtrl = MAC_FRAME_DEAUTH;
/* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */
prDeauthFrame->u2FrameCtrl = u2FrameCtrl;
/* NOTE(Kevin): Optimized for ARM */
/* Fill the DA field with Target BSSID. */
COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress);
/* Fill the SA field with our MAC Address. */
COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress);
/* Fill the BSSID field with Target BSSID. */
COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid);
/* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO,
* so we need to clear it).
*/
prDeauthFrame->u2SeqCtrl = 0;
/* 4 <2> Compose the frame body's fixed field part of
* the Authentication frame.
*/
/* Fill the Status Code field. */
/* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */
prDeauthFrame->u2ReasonCode = u2ReasonCode;
/* NOTE(Kevin): Optimized for ARM */
} /* end of authComposeDeauthFrameHeaderAndFF() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will send the Deauthenticiation frame
*
* @param[in] prStaRec Pointer to the STA_RECORD_T
* @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error.
* @param[in] u2ReasonCode A reason code to indicate why to leave BSS.
* @param[in] pfTxDoneHandler TX Done call back function
*
* @retval WLAN_STATUS_RESOURCES No available resource for frame composing.
* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module
* @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons.
*/
/*----------------------------------------------------------------------------*/
uint32_t
authSendDeauthFrame(IN struct ADAPTER *prAdapter,
IN struct BSS_INFO *prBssInfo,
IN struct STA_RECORD *prStaRec,
IN struct SW_RFB *prClassErrSwRfb, IN uint16_t u2ReasonCode,
IN PFN_TX_DONE_HANDLER pfTxDoneHandler)
{
uint8_t *pucReceiveAddr;
uint8_t *pucTransmitAddr;
uint8_t *pucBssid = NULL;
struct MSDU_INFO *prMsduInfo;
uint16_t u2EstimatedFrameLen;
struct DEAUTH_INFO *prDeauthInfo;
OS_SYSTIME rCurrentTime;
int32_t i4NewEntryIndex, i;
uint8_t ucStaRecIdx = STA_REC_INDEX_NOT_FOUND;
uint8_t ucBssIndex = prAdapter->ucHwBssIdNum;
uint8_t aucBMC[] = BC_MAC_ADDR;
#if CFG_SUPPORT_CFG80211_AUTH
struct WLAN_DEAUTH_FRAME *prDeauthFrame;
uint8_t ucRoleIdx = 0;
struct net_device *prNetDev = NULL;
#endif
DBGLOG(RSN, INFO, "authSendDeauthFrame\n");
/* NOTE(Kevin): The best way to reply the Deauth is according to
* the incoming data frame
*/
/* 4 <1.1> Find the Receiver Address */
if (prClassErrSwRfb) {
u_int8_t fgIsAbleToSendDeauth = FALSE;
uint16_t u2RxFrameCtrl;
struct WLAN_MAC_HEADER_A4 *prWlanMacHeader = NULL;
prWlanMacHeader =
(struct WLAN_MAC_HEADER_A4 *)prClassErrSwRfb->pvHeader;
/* WLAN_GET_FIELD_16(&prWlanMacHeader->u2FrameCtrl,
* &u2RxFrameCtrl);
*/
u2RxFrameCtrl = prWlanMacHeader->u2FrameCtrl;
/* NOTE(Kevin): Optimized for ARM */
/* TODO(Kevin): Currently we won't send Deauth for IBSS node.
* How about DLS ?
*/
if ((prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) == 0)
return WLAN_STATUS_FAILURE;
DBGLOG(SAA, INFO,
"u2FrameCtrl=0x%x, DestAddr=" MACSTR
" srcAddr=" MACSTR " BSSID=" MACSTR
", u2SeqCtrl=0x%x\n",
prWlanMacHeader->u2FrameCtrl,
MAC2STR(prWlanMacHeader->aucAddr1),
MAC2STR(prWlanMacHeader->aucAddr2),
MAC2STR(prWlanMacHeader->aucAddr3),
prWlanMacHeader->u2SeqCtrl);
/* Check if corresponding BSS is able to send Deauth */
for (i = 0; i < prAdapter->ucHwBssIdNum; i++) {
prBssInfo = GET_BSS_INFO_BY_INDEX(prAdapter, i);
if (IS_NET_ACTIVE(prAdapter, i) &&
(EQUAL_MAC_ADDR
(prWlanMacHeader->aucAddr1,
prBssInfo->aucOwnMacAddr))) {
fgIsAbleToSendDeauth = TRUE;
ucBssIndex = (uint8_t) i;
break;
}
}
if (!fgIsAbleToSendDeauth)
return WLAN_STATUS_FAILURE;
pucReceiveAddr = prWlanMacHeader->aucAddr2;
} else if (prStaRec) {
prBssInfo =
GET_BSS_INFO_BY_INDEX(prAdapter, prStaRec->ucBssIndex);
ucStaRecIdx = prStaRec->ucIndex;
ucBssIndex = prBssInfo->ucBssIndex;
pucReceiveAddr = prStaRec->aucMacAddr;
} else if (prBssInfo) {
ucBssIndex = prBssInfo->ucBssIndex;
ucStaRecIdx = STA_REC_INDEX_BMCAST;
pucReceiveAddr = aucBMC;
} else {
DBGLOG(SAA, WARN, "Not to send Deauth, invalid data!\n");
return WLAN_STATUS_INVALID_DATA;
}
/* 4 <1.2> Find Transmitter Address and BSSID. */
pucTransmitAddr = prBssInfo->aucOwnMacAddr;
pucBssid = prBssInfo->aucBSSID;
if (ucStaRecIdx != STA_REC_INDEX_BMCAST) {
/* 4 <2> Check if already send a Deauth frame in
* MIN_DEAUTH_INTERVAL_MSEC
*/
GET_CURRENT_SYSTIME(&rCurrentTime);
i4NewEntryIndex = -1;
for (i = 0; i < MAX_DEAUTH_INFO_COUNT; i++) {
prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i]);
/* For continuously sending Deauth frame, the minimum
* interval is MIN_DEAUTH_INTERVAL_MSEC.
*/
if (CHECK_FOR_TIMEOUT(rCurrentTime,
prDeauthInfo->rLastSendTime,
MSEC_TO_SYSTIME
(MIN_DEAUTH_INTERVAL_MSEC))) {
i4NewEntryIndex = i;
} else
if (EQUAL_MAC_ADDR
(pucReceiveAddr, prDeauthInfo->aucRxAddr)
&& (!pfTxDoneHandler)) {
return WLAN_STATUS_FAILURE;
}
}
/* 4 <3> Update information. */
if (i4NewEntryIndex > 0) {
prDeauthInfo =
&(prAdapter->
rWifiVar.arDeauthInfo[i4NewEntryIndex]);
COPY_MAC_ADDR(prDeauthInfo->aucRxAddr, pucReceiveAddr);
prDeauthInfo->rLastSendTime = rCurrentTime;
} else {
/* NOTE(Kevin): for the case of AP mode, we may
* encounter this case
* if deauth all the associated clients.
*/
DBGLOG(SAA, WARN, "No unused DEAUTH_INFO_T !\n");
}
}
/* 4 <5> Allocate a PKT_INFO_T for Deauthentication Frame */
/* Init with MGMT Header Length + Length of Fixed Fields + IE Length */
u2EstimatedFrameLen =
(MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN +
REASON_CODE_FIELD_LEN);
/* Allocate a MSDU_INFO_T */
prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen);
if (prMsduInfo == NULL) {
DBGLOG(SAA, WARN,
"No PKT_INFO_T for sending Deauth Request.\n");
return WLAN_STATUS_RESOURCES;
}
/* 4 <6> compose Deauthentication frame header and some fixed fields */
authComposeDeauthFrameHeaderAndFF((uint8_t *)
((unsigned long)(prMsduInfo->prPacket)
+ MAC_TX_RESERVED_FIELD),
pucReceiveAddr, pucTransmitAddr,
pucBssid, u2ReasonCode);
#if CFG_SUPPORT_802_11W
/* AP PMF */
if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) {
/* PMF certification 4.3.3.1, 4.3.3.2 send unprotected
* deauth reason 6/7
* if (AP mode & not for PMF reply case) OR (STA PMF)
*/
if (((GET_BSS_INFO_BY_INDEX
(prAdapter,
prStaRec->ucBssIndex)->eCurrentOPMode ==
OP_MODE_ACCESS_POINT)
&& (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE))
||
(GET_BSS_INFO_BY_INDEX
(prAdapter,
prStaRec->ucBssIndex)->eNetworkType ==
(uint8_t) NETWORK_TYPE_AIS)) {
struct WLAN_DEAUTH_FRAME *prDeauthFrame;
prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)(uint8_t *)
((unsigned long)(prMsduInfo->prPacket)
+ MAC_TX_RESERVED_FIELD);
prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME;
DBGLOG(SAA, INFO,
"Reason=%d, DestAddr=" MACSTR
" srcAddr=" MACSTR " BSSID=" MACSTR "\n",
prDeauthFrame->u2ReasonCode,
MAC2STR(prDeauthFrame->aucDestAddr),
MAC2STR(prDeauthFrame->aucSrcAddr),
MAC2STR(prDeauthFrame->aucBSSID));
}
}
#endif
nicTxSetPktLifeTime(prMsduInfo, 100);
nicTxSetPktRetryLimit(prMsduInfo, TX_DESC_TX_COUNT_NO_LIMIT);
/* 4 <7> Update information of MSDU_INFO_T */
TX_SET_MMPDU(prAdapter,
prMsduInfo,
ucBssIndex,
ucStaRecIdx,
WLAN_MAC_MGMT_HEADER_LEN,
WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN,
pfTxDoneHandler, MSDU_RATE_MODE_AUTO);
#if CFG_SUPPORT_802_11W
/* AP PMF */
/* caution: access prStaRec only if true */
if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) {
/* 4.3.3.1 send unprotected deauth reason 6/7 */
if (prStaRec->rPmfCfg.fgRxDeauthResp != TRUE) {
DBGLOG(RSN, INFO,
"Deauth Set MSDU_OPT_PROTECTED_FRAME\n");
nicTxConfigPktOption(prMsduInfo,
MSDU_OPT_PROTECTED_FRAME, TRUE);
}
prStaRec->rPmfCfg.fgRxDeauthResp = FALSE;
}
#endif
#if CFG_SUPPORT_CFG80211_AUTH
prDeauthFrame = (struct WLAN_DEAUTH_FRAME *) (uint8_t *)
((unsigned long) (prMsduInfo->prPacket) +
MAC_TX_RESERVED_FIELD);
DBGLOG(SAA, INFO, "notification of TX deauthentication, %d\n",
prMsduInfo->u2FrameLength);
if (prAdapter->fgIsP2PRegistered &&
IS_BSS_P2P(prBssInfo)) {
ucRoleIdx = (uint8_t)prBssInfo->u4PrivateData;
prNetDev = prAdapter->prGlueInfo->
prP2PInfo[ucRoleIdx]->aprRoleHandler;
} else {
prNetDev = prAdapter->prGlueInfo->prDevHandler;
}
if (prNetDev == NULL) {
DBGLOG(SAA, WARN, "dev get null\n");
prNetDev = prAdapter->prGlueInfo->prDevHandler;
}
kalIndicateTxDeauthToUpperLayer(
prNetDev,
(uint8_t *)prDeauthFrame,
(size_t)prMsduInfo->u2FrameLength);
DBGLOG(SAA, INFO,
"notification of TX deauthentication, Done\n");
#endif
DBGLOG(SAA, INFO, "ucTxSeqNum=%d ucStaRecIndex=%d u2ReasonCode=%d\n",
prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex, u2ReasonCode);
/* 4 <8> Inform TXM to send this Deauthentication frame. */
nicTxEnqueueMsdu(prAdapter, prMsduInfo);
return WLAN_STATUS_SUCCESS;
} /* end of authSendDeauthFrame() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will parse and process the incoming Deauthentication
* frame if the given BSSID is matched.
*
* @param[in] prSwRfb Pointer to SW RFB data structure.
* @param[in] aucBSSID Given BSSID
* @param[out] pu2ReasonCode Pointer to store the Reason Code from
* Deauthentication.
*
* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at
* current state.
* @retval WLAN_STATUS_SUCCESS This is the frame we should handle.
*/
/*----------------------------------------------------------------------------*/
uint32_t authProcessRxDeauthFrame(IN struct SW_RFB *prSwRfb,
IN uint8_t aucBSSID[],
OUT uint16_t *pu2ReasonCode)
{
struct WLAN_DEAUTH_FRAME *prDeauthFrame;
uint16_t u2RxReasonCode;
if (!prSwRfb || !aucBSSID || !pu2ReasonCode) {
DBGLOG(SAA, WARN, "Invalid parameters, ignore pkt!\n");
return WLAN_STATUS_FAILURE;
}
/* 4 <1> locate the Deauthentication Frame. */
prDeauthFrame = (struct WLAN_DEAUTH_FRAME *)prSwRfb->pvHeader;
/* 4 <2> Parse the Header of Deauthentication Frame. */
#if 0 /* Kevin: Seems redundant */
WLAN_GET_FIELD_16(&prDeauthFrame->u2FrameCtrl, &u2RxFrameCtrl)
u2RxFrameCtrl &= MASK_FRAME_TYPE;
if (u2RxFrameCtrl != MAC_FRAME_DEAUTH)
return WLAN_STATUS_FAILURE;
#endif
if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) <
REASON_CODE_FIELD_LEN) {
DBGLOG(SAA, WARN, "Invalid Deauth packet length");
return WLAN_STATUS_FAILURE;
}
/* Check if this Deauth Frame is coming from Target BSSID */
if (UNEQUAL_MAC_ADDR(prDeauthFrame->aucBSSID, aucBSSID)) {
DBGLOG(SAA, LOUD,
"Ignore Deauth Frame from other BSS [" MACSTR "]\n",
MAC2STR(prDeauthFrame->aucSrcAddr));
return WLAN_STATUS_FAILURE;
}
/* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */
WLAN_GET_FIELD_16(&prDeauthFrame->u2ReasonCode, &u2RxReasonCode);
*pu2ReasonCode = u2RxReasonCode;
return WLAN_STATUS_SUCCESS;
} /* end of authProcessRxDeauthFrame() */
/*----------------------------------------------------------------------------*/
/*!
* @brief This function will parse and process the incoming Authentication
* frame.
*
* @param[in] prSwRfb Pointer to SW RFB data structure.
* @param[in] aucExpectedBSSID Given Expected BSSID.
* @param[in] u2ExpectedAuthAlgNum Given Expected Authentication Algorithm
* Number
* @param[in] u2ExpectedTransSeqNum Given Expected Transaction Sequence Number.
* @param[out] pu2ReturnStatusCode Return Status Code.
*
* @retval WLAN_STATUS_SUCCESS This is the frame we should handle.
* @retval WLAN_STATUS_FAILURE The frame we will ignore.
*/
/*----------------------------------------------------------------------------*/
uint32_t
authProcessRxAuth1Frame(IN struct ADAPTER *prAdapter,
IN struct SW_RFB *prSwRfb,
IN uint8_t aucExpectedBSSID[],
IN uint16_t u2ExpectedAuthAlgNum,
IN uint16_t u2ExpectedTransSeqNum,
OUT uint16_t *pu2ReturnStatusCode)
{
struct WLAN_AUTH_FRAME *prAuthFrame;
uint16_t u2RxStatusCode;
uint16_t u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL;
ASSERT(prSwRfb);
ASSERT(aucExpectedBSSID);
ASSERT(pu2ReturnStatusCode);
/* 4 <1> locate the Authentication Frame. */
prAuthFrame = (struct WLAN_AUTH_FRAME *)prSwRfb->pvHeader;
/* 4 <2> Check the BSSID */
if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID))
return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */
/* 4 <3> Check the SA, which should not be MC/BC */
if (prAuthFrame->aucSrcAddr[0] & BIT(0)) {
DBGLOG(P2P, WARN,
"Invalid STA MAC with MC/BC bit set: " MACSTR "\n",
MAC2STR(prAuthFrame->aucSrcAddr));
return WLAN_STATUS_FAILURE;
}
/* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */
#if CFG_SUPPORT_CFG80211_AUTH
u2RxStatusCode = (prAuthFrame->aucAuthData[3] << 8) +
prAuthFrame->aucAuthData[2];
#else
u2RxStatusCode = prAuthFrame->u2StatusCode;
#endif
if (u2RxStatusCode != STATUS_CODE_RESERVED) {
DBGLOG(AAA, LOUD, "Invalid Status code %d\n", u2RxStatusCode);
return WLAN_STATUS_FAILURE;
}
if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum)
u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED;
#if CFG_SUPPORT_CFG80211_AUTH
if (prAuthFrame->aucAuthData[0] != u2ExpectedTransSeqNum)
#else
if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum)
#endif
u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ;
*pu2ReturnStatusCode = u2ReturnStatusCode;
return WLAN_STATUS_SUCCESS;
} /* end of authProcessRxAuth1Frame() */
/* ToDo: authAddRicIE, authHandleFtIEs, authAddTimeoutIE */
void authAddMDIE(IN struct ADAPTER *prAdapter,
IN OUT struct MSDU_INFO *prMsduInfo)
{
struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx;
uint8_t *pucBuffer =
(uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength;
uint8_t ucBssIdx = prMsduInfo->ucBssIndex;
if (!IS_BSS_INDEX_VALID(ucBssIdx) ||
!IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) ||
!prFtIEs->prMDIE)
return;
prMsduInfo->u2FrameLength +=
5; /* IE size for MD IE is fixed, it is 5 */
kalMemCopy(pucBuffer, prFtIEs->prMDIE, 5);
}
uint32_t authCalculateRSNIELen(struct ADAPTER *prAdapter, uint8_t ucBssIdx,
struct STA_RECORD *prStaRec)
{
enum ENUM_PARAM_AUTH_MODE eAuthMode =
prAdapter->rWifiVar.rConnSettings.eAuthMode;
struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx;
if (!IS_BSS_INDEX_VALID(ucBssIdx) ||
!IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) ||
!prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT &&
eAuthMode != AUTH_MODE_WPA2_FT_PSK))
return 0;
return IE_SIZE(prFtIEs->prRsnIE);
}
void authAddRSNIE(IN struct ADAPTER *prAdapter,
IN OUT struct MSDU_INFO *prMsduInfo)
{
enum ENUM_PARAM_AUTH_MODE eAuthMode =
prAdapter->rWifiVar.rConnSettings.eAuthMode;
struct FT_IES *prFtIEs = &prAdapter->prGlueInfo->rFtIeForTx;
uint8_t *pucBuffer =
(uint8_t *)prMsduInfo->prPacket + prMsduInfo->u2FrameLength;
uint32_t ucRSNIeSize = 0;
uint8_t ucBssIdx = prMsduInfo->ucBssIndex;
if (!IS_BSS_INDEX_VALID(ucBssIdx) ||
!IS_BSS_AIS(GET_BSS_INFO_BY_INDEX(prAdapter, ucBssIdx)) ||
!prFtIEs->prRsnIE || (eAuthMode != AUTH_MODE_WPA2_FT &&
eAuthMode != AUTH_MODE_WPA2_FT_PSK))
return;
ucRSNIeSize = IE_SIZE(prFtIEs->prRsnIE);
prMsduInfo->u2FrameLength += ucRSNIeSize;
kalMemCopy(pucBuffer, prFtIEs->prRsnIE, ucRSNIeSize);
}
/*---------------------------------------------------------------------------*/
/*!
* @brief This function will validate the Rx Auth Frame and then return
* the status code to AAA to indicate
* if need to perform following actions
* when the specified conditions were matched.
*
* @param[in] prAdapter Pointer to the Adapter structure.
* @param[in] prSwRfb Pointer to SW RFB data structure.
*
* @retval TRUE Reply the Auth
* @retval FALSE Don't reply the Auth
*/
/*---------------------------------------------------------------------------*/
u_int8_t
authFloodingCheck(IN struct ADAPTER *prAdapter,
IN struct BSS_INFO *prP2pBssInfo,
IN struct SW_RFB *prSwRfb)
{
struct STA_RECORD *prStaRec = (struct STA_RECORD *) NULL;
struct WLAN_AUTH_FRAME *prAuthFrame = (struct WLAN_AUTH_FRAME *) NULL;
DBGLOG(SAA, TRACE, "authFloodingCheck Authentication Frame\n");
prAuthFrame = (struct WLAN_AUTH_FRAME *) prSwRfb->pvHeader;
if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) ||
(prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) {
/* We are not under AP Mode yet. */
DBGLOG(P2P, WARN,
"Current OP mode is not under AP mode. (%d)\n",
prP2pBssInfo->eCurrentOPMode);
return FALSE;
}
prStaRec = cnmGetStaRecByAddress(prAdapter,
prP2pBssInfo->ucBssIndex, prAuthFrame->aucSrcAddr);
if (!prStaRec) {
DBGLOG(SAA, TRACE, "Need reply.\n");
return TRUE;
}
DBGLOG(SAA, WARN, "Auth Flooding Attack, don't reply.\n");
return FALSE;
}