📄 rtmp_data.c
字号:
/* ************************************************************************* * Ralink Tech Inc. * 4F, No. 2 Technology 5th Rd. * Science-based Industrial Park * Hsin-chu, 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 -------- ---------- ---------------------------------------------- John Aug/17/04 major modification for RT2561/2661 Jan Lee Mar/17/06 major modification for RT2860 New Ring Design*/#include "rt_config.h"VOID STARxEAPOLFrameIndicate( IN PRTMP_ADAPTER pAd, IN MAC_TABLE_ENTRY *pEntry, IN RX_BLK *pRxBlk, IN UCHAR FromWhichBSSID){ PRXD_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; MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; DBGPRINT_RAW(RT_DEBUG_TRACE, ("Receive EAP-SUCCESS Packet\n")); pAd->StaCfg.PortSecured = WPA_802_1X_PORT_SECURED; 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) { // Set key material and cipherAlg to Asic AsicAddSharedKeyEntry(pAd, BSS0, idx, CipherAlg, Key, NULL, NULL); // Assign group key info RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, NULL); // Assign pairwise key info RTMPAddWcidAttributeEntry(pAd, BSS0, idx, CipherAlg, pEntry); } } } 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, pRxBlk->pData, pRxBlk->DataSize)) { // 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; } } if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_ARALINK)) { // Normal legacy, AMPDU or AMSDU CmmRxnonRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); } else { // ARALINK CmmRxRalinkFrameIndicate(pAd, pEntry, pRxBlk, FromWhichBSSID); } } else { // 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; PCIPHER_KEY pWpaKey; UCHAR *pDA, *pSA; pWpaKey = &pAd->SharedKey[BSS0][pRxBlk->pRxWI->KeyIndex]; // Minus MIC length DataSize -= 8; 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, 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){ PRXD_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; // 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; } // Drop not my BSS frames if (pRxD->MyBss == 0) { // release packet RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_FAILURE); return; } if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable && (pHeader->FC.SubType & 0x08)) { UCHAR *pData; DBGPRINT(RT_DEBUG_TRACE,("bAPSDCapable\n")); // Qos bit 4 pData = (PUCHAR)pHeader + LENGTH_802_11; if ((*pData >> 4) & 0x01) { DBGPRINT(RT_DEBUG_TRACE,("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; MlmeSetPsmBit(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")); //STA should not send trigger frame, the trigger frame should be level 3. //RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE); } } // 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) 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; } } // // 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); 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); } DBGPRINT(RT_DEBUG_INFO, ("Atheros Problem. Turn on RTS/CTS!!!\n")); } 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); // 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; } // 3. Order bit: A-Ralink or HTC+ if (pHeader->FC.Order) {#ifdef AGGREGATION_SUPPORT if ((pRxWI->PHYMODE < MODE_HTMIX) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED))) { RX_BLK_SET_FLAG(pRxBlk, fRX_ARALINK); } else#endif { RX_BLK_SET_FLAG(pRxBlk, fRX_HTC); // skip HTC contorl field pRxBlk->pData += 4; pRxBlk->DataSize -= 4; } } // 4. skip HW padding if (pRxD->L2PAD) { // just move pData pointer // because DataSize excluding HW padding RX_BLK_SET_FLAG(pRxBlk, fRX_PAD); pRxBlk->pData += 2; } if (pRxD->BA) { RX_BLK_SET_FLAG(pRxBlk, fRX_AMPDU); } // // Case I Process Broadcast & Multicast data frame // if (pRxD->Bcast || pRxD->Mcast) { INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); // Drop Mcast/Bcast frame with fragment bit on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -