📄 rtmp_data.c
字号:
/* ************************************************************************* * Ralink Tech Inc. * 5F., No.36, Taiyuan St., Jhubei City, * Hsinchu County 302, * Taiwan, R.O.C. * * (c) Copyright 2002-2007, Ralink Technology, Inc. * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * 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 the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * ************************************************************************* Module Name: rtmp_data.c Abstract: Data path subroutines Revision History: Who When What -------- ---------- ----------------------------------------------*/#include "rt_config.h"VOID STARxEAPOLFrameIndicate( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); PRXWI_STRUC pRxWI = pRxBlk->pRxWI; UCHAR *pTmpBuf;#ifdef WPA_SUPPLICANT_SUPPORT if (pAd->StaCfg.WpaSupplicantUP) { // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) // TBD : process fragmented EAPol frames { // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable if ( pAd->StaCfg.IEEE8021X == TRUE && (EAP_CODE_SUCCESS == WpaCheckEapCode(pAd, pRxBlk->pData, pRxBlk->DataSize, LENGTH_802_1_H))) { PUCHAR Key; UCHAR CipherAlg; int idx = 0; DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); //pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; STA_PORT_SECURED(pAd); if (pAd->StaCfg.IEEE8021x_required_keys == FALSE) { idx = pAd->StaCfg.DesireSharedKeyId; CipherAlg = pAd->StaCfg.DesireSharedKey[idx].CipherAlg; Key = pAd->StaCfg.DesireSharedKey[idx].Key; if (pAd->StaCfg.DesireSharedKey[idx].KeyLen > 0) {#ifdef RTMP_MAC_USB union { char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1]; NDIS_802_11_WEP keyinfo; } WepKey; int len; NdisZeroMemory(&WepKey, sizeof(WepKey)); len =pAd->StaCfg.DesireSharedKey[idx].KeyLen; NdisMoveMemory(WepKey.keyinfo.KeyMaterial, pAd->StaCfg.DesireSharedKey[idx].Key, pAd->StaCfg.DesireSharedKey[idx].KeyLen); WepKey.keyinfo.KeyIndex = 0x80000000 + idx; WepKey.keyinfo.KeyLength = len; pAd->SharedKey[BSS0][idx].KeyLen =(UCHAR) (len <= 5 ? 5 : 13); pAd->IndicateMediaState = NdisMediaStateConnected; pAd->ExtraInfo = GENERAL_LINK_UP; // need to enqueue cmd to thread RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1); #endif // RTMP_MAC_USB // // For Preventing ShardKey Table is cleared by remove key procedure. pAd->SharedKey[BSS0][idx].CipherAlg = CipherAlg; pAd->SharedKey[BSS0][idx].KeyLen = pAd->StaCfg.DesireSharedKey[idx].KeyLen; NdisMoveMemory(pAd->SharedKey[BSS0][idx].Key, pAd->StaCfg.DesireSharedKey[idx].Key, pAd->StaCfg.DesireSharedKey[idx].KeyLen); } } } Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID); return; } } else#endif // WPA_SUPPLICANT_SUPPORT // { // Special DATA frame that has to pass to MLME // 1. Cisco Aironet frames for CCX2. We need pass it to MLME for special process // 2. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process { pTmpBuf = pRxBlk->pData - LENGTH_802_11; NdisMoveMemory(pTmpBuf, pRxBlk->pHeader, LENGTH_802_11); REPORT_MGMT_FRAME_TO_MLME(pAd, pRxWI->WirelessCliID, pTmpBuf, pRxBlk->DataSize + LENGTH_802_11, pRxWI->RSSI0, pRxWI->RSSI1, pRxWI->RSSI2, pRxD->PlcpSignal); DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", pRxBlk->DataSize)); } } RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return;}VOID STARxDataFrameAnnounce( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ // non-EAP frame if (!RTMPCheckWPAframe(pAd, pEntry, pRxBlk->pData, pRxBlk->DataSize, FromWhichBSSID)) { { // drop all non-EAP DATA frame before // this client's Port-Access-Control is secured if (pRxBlk->pHeader->FC.Wep) { // unsupported cipher suite if (pAd->StaCfg.WepStatus == Ndis802_11EncryptionDisabled) { // release packet RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return; } } else { // encryption in-use but receive a non-EAPOL clear text frame, drop it if ((pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled) && (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)) { // release packet RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return; } } } RX_BLK_CLEAR_FLAG(pRxBlk, fRX_EAP); if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) { // Normal legacy, AMPDU or AMSDU CmmRxnonRalinkFrameIndicate(pAd, pRxBlk, FromWhichBSSID); } else { // ARALINK CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); }#ifdef QOS_DLS_SUPPORT RX_BLK_CLEAR_FLAG(pRxBlk, fRX_DLS);#endif // QOS_DLS_SUPPORT // } else { RX_BLK_SET_FLAG(pRxBlk, fRX_EAP);#ifdef DOT11_N_SUPPORT if (RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU) && (pAd->CommonCfg.bDisableReordering == 0)) { Indicate_AMPDU_Packet(pAd, pRxBlk, FromWhichBSSID); } else#endif // DOT11_N_SUPPORT // { // Determin the destination of the EAP frame // to WPA state machine or upper layer STARxEAPOLFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); } }}// For TKIP frame, calculate the MIC value BOOLEAN STACheckTkipMICValue( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry, IN RX_BLK *pRxBlk){ PHEADER_802_11 pHeader = pRxBlk->pHeader; UCHAR *pData = pRxBlk->pData; USHORT DataSize = pRxBlk->DataSize; UCHAR UserPriority = pRxBlk->UserPriority; PCIPHER_KEY pWpaKey; UCHAR *pDA, *pSA; pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; pDA = pHeader->Addr1; if (RX_BLK_TEST_FLAG(pRxBlk, fRX_INFRA)) { pSA = pHeader->Addr3; } else { pSA = pHeader->Addr2; } if (RTMPTkipCompareMICValue(pAd, pData, pDA, pSA, pWpaKey->RxMic, UserPriority, DataSize) == FALSE) { DBGPRINT_RAW(RT_DEBUG_ERROR,("Rx MIC Value error 2\n"));#ifdef WPA_SUPPLICANT_SUPPORT if (pAd->StaCfg.WpaSupplicantUP) { WpaSendMicFailureToWpaSupplicant(pAd, (pWpaKey->Type == PAIRWISEKEY) ? TRUE : FALSE); } else #endif // WPA_SUPPLICANT_SUPPORT // { RTMPReportMicError(pAd, pWpaKey); } // release packet RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); return FALSE; } return TRUE;}//// All Rx routines use RX_BLK structure to hande rx events// It is very important to build pRxBlk attributes// 1. pHeader pointer to 802.11 Header// 2. pData pointer to payload including LLC (just skip Header)// 3. set payload size including LLC to DataSize// 4. set some flags with RX_BLK_SET_FLAG()// VOID STAHandleRxDataFrame( IN PRTMP_ADAPTER pAd, IN RX_BLK *pRxBlk){ PRT28XX_RXD_STRUC pRxD = &(pRxBlk->RxD); PRXWI_STRUC pRxWI = pRxBlk->pRxWI; PHEADER_802_11 pHeader = pRxBlk->pHeader; PNDIS_PACKET pRxPacket = pRxBlk->pRxPacket; BOOLEAN bFragment = FALSE; MAC_TABLE_ENTRY *pEntry = NULL; UCHAR FromWhichBSSID = BSS0; UCHAR UserPriority = 0; { // before LINK UP, all DATA frames are rejected if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; }#ifdef QOS_DLS_SUPPORT //if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) if (RTMPRcvFrameDLSCheck(pAd, pHeader, pRxWI->MPDUtotalByteCount, pRxD)) { return; }#endif // QOS_DLS_SUPPORT // // Drop not my BSS frames if (pRxD->MyBss == 0) { { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } } pAd->RalinkCounters.RxCountSinceLastNULL++; if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) { UCHAR *pData; DBGPRINT(RT_DEBUG_INFO,("bAPSDCapable\n")); // Qos bit 4 pData = (PUCHAR)pHeader + LENGTH_802_11; if ((*pData >> 4) & 0x01) { DBGPRINT(RT_DEBUG_INFO,("RxDone- Rcv EOSP frame, driver may fall into sleep\n")); pAd->CommonCfg.bInServicePeriod = FALSE; // Force driver to fall into sleep mode when rcv EOSP frame if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) { USHORT TbttNumToNextWakeUp; USHORT NextDtim = pAd->StaCfg.DtimPeriod; ULONG Now; NdisGetSystemUpTime(&Now); NextDtim -= (USHORT)(Now - pAd->StaCfg.LastBeaconRxTime)/pAd->CommonCfg.BeaconPeriod; TbttNumToNextWakeUp = pAd->StaCfg.DefaultListenCount; if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM) && (TbttNumToNextWakeUp > NextDtim)) TbttNumToNextWakeUp = NextDtim; RTMP_SET_PSM_BIT(pAd, PWR_SAVE); // if WMM-APSD is failed, try to disable following line AsicSleepThenAutoWakeup(pAd, TbttNumToNextWakeUp); } } if ((pHeader->FC.MoreData) && (pAd->CommonCfg.bInServicePeriod)) { DBGPRINT(RT_DEBUG_TRACE,("Sending another trigger frame when More Data bit is set to 1\n")); } } // Drop NULL, CF-ACK(no data), CF-POLL(no data), and CF-ACK+CF-POLL(no data) data frame if ((pHeader->FC.SubType & 0x04)) // bit 2 : no DATA { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } // Drop not my BSS frame (we can not only check the MyBss bit in RxD)#ifdef QOS_DLS_SUPPORT if (!pAd->CommonCfg.bDLSCapable) {#endif // QOS_DLS_SUPPORT // if (INFRA_ON(pAd)) { // Infrastructure mode, check address 2 for BSSID if (!RTMPEqualMemory(&pHeader->Addr2, &pAd->CommonCfg.Bssid, 6)) { // Receive frame not my BSSID // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } } else // Ad-Hoc mode or Not associated { // Ad-Hoc mode, check address 3 for BSSID if (!RTMPEqualMemory(&pHeader->Addr3, &pAd->CommonCfg.Bssid, 6)) { // Receive frame not my BSSID // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } }#ifdef QOS_DLS_SUPPORT }#endif // QOS_DLS_SUPPORT // // // find pEntry // if (pRxWI->WirelessCliID < MAX_LEN_OF_MAC_TABLE) { pEntry = &pAd->MacTab.Content[pRxWI->WirelessCliID]; } else { // 1. release packet if infra mode // 2. new a pEntry if ad-hoc mode RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } // infra or ad-hoc if (INFRA_ON(pAd)) { RX_BLK_SET_FLAG(pRxBlk, fRX_INFRA);#ifdef QOS_DLS_SUPPORT if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 0)) RX_BLK_SET_FLAG(pRxBlk, fRX_DLS); else#endif // QOS_DLS_SUPPORT // ASSERT(pRxWI->WirelessCliID == BSSID_WCID); } // check Atheros Client if ((pEntry->bIAmBadAtheros == FALSE) && (pRxD->AMPDU == 1) && (pHeader->FC.Retry )) { pEntry->bIAmBadAtheros = TRUE; pAd->CommonCfg.IOTestParm.bCurrentAtheros = TRUE; pAd->CommonCfg.IOTestParm.bLastAtheros = TRUE; if (!STA_AES_ON(pAd)) { AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, TRUE, FALSE); } } } pRxBlk->pData = (UCHAR *)pHeader; // // update RxBlk->pData, DataSize // 802.11 Header, QOS, HTC, Hw Padding // // 1. skip 802.11 HEADER { pRxBlk->pData += LENGTH_802_11; pRxBlk->DataSize -= LENGTH_802_11; } // 2. QOS if (pHeader->FC.SubType & 0x08) { RX_BLK_SET_FLAG(pRxBlk, fRX_QOS); UserPriority = *(pRxBlk->pData) & 0x0f; // bit 7 in QoS Control field signals the HT A-MSDU format if ((*pRxBlk->pData) & 0x80) { RX_BLK_SET_FLAG(pRxBlk, fRX_AMSDU); } // skip QOS contorl field pRxBlk->pData += 2; pRxBlk->DataSize -=2; } pRxBlk->UserPriority = UserPriority; /* check if need to resend PS Poll when received packet with MoreData = 1 */ if ((pAd->StaCfg.Psm == PWR_SAVE) && (pHeader->FC.MoreData == 1)) { if ((((UserPriority == 0) || (UserPriority == 3)) && pAd->CommonCfg.bAPSDAC_BE == 0) || (((UserPriority == 1) || (UserPriority == 2)) && pAd->CommonCfg.bAPSDAC_BK == 0) || (((UserPriority == 4) || (UserPriority == 5)) && pAd->CommonCfg.bAPSDAC_VI == 0) || (((UserPriority == 6) || (UserPriority == 7)) && pAd->CommonCfg.bAPSDAC_VO == 0)) { /* non-UAPSD delivery-enabled AC */ RTMP_PS_POLL_ENQUEUE(pAd); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -