📄 rtusb_data.c
字号:
USHORT AckDuration = 0; USHORT EncryptionOverhead = 0; UCHAR CipherAlg; BOOLEAN bAckRequired; UCHAR RetryMode = SHORT_RETRY; UCHAR UserPriority; UCHAR MpduRequired, RtsRequired; UCHAR TxRate; PCIPHER_KEY pKey = NULL ; PUCHAR pSrcBufVA = NULL; ULONG SrcBufLen; PUCHAR pExtraLlcSnapEncap = NULL; // NULL: no extra LLC/SNAP is required UCHAR KeyIdx; PUCHAR pWirelessPacket; ULONG NextMpduSize; BOOLEAN bRTS_CTSFrame = FALSE; unsigned long flags; // For 'Ndis' spin lock if ((pAd->PortCfg.bIEEE80211H == 1) && (pAd->PortCfg.RadarDetect.RDMode != RD_NORMAL_MODE)) { DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit --> radar detect not in normal mode !!!\n"); return (NDIS_STATUS_FAILURE); } if (pAd->PortCfg.BssType == BSS_MONITOR && pAd->bAcceptRFMONTx == TRUE) { DBGPRINT(RT_DEBUG_INFO,"==>INJECT\n"); pTxContext = &pAd->TxContext[QueIdx][pAd->NextTxIndex[QueIdx]]; if (pAd->TxRingTotalNumber[QueIdx] >= TX_RING_SIZE) { //Modified by Thomas DBGPRINT_ERR("RTUSBHardTransmit: TX RING full\n"); //pAd->RalinkCounters.TxRingErrCount++; //return (NDIS_STATUS_RESOURCES); return (NDIS_STATUS_RINGFULL); } pTxContext->InUse = TRUE; pTxContext->LastOne = TRUE; // Increase & maintain Tx Ring Index pAd->NextTxIndex[QueIdx]++; if (pAd->NextTxIndex[QueIdx] >= TX_RING_SIZE) { pAd->NextTxIndex[QueIdx] = 0; }#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;#else pDestTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);#endif memset(pTxD, 0, sizeof(TXD_STRUC)); pWirelessPacket = pTxContext->TransferBuffer->WirelessPacket; memcpy( pWirelessPacket, pSkb->data, pSkb->len ); TxSize = pSkb->len; //+FCS /*for (i=0; i<TxSize; i++) DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit --> byte %u is %x\n", i, pWirelessPacket[i]);*/ RTUSBWriteTxDescriptor(pAd, pTxD, CIPHER_NONE /*CipherAlg*/, 0, 0xff /*KeyIdx*/, FALSE /*bAckRequired*/, FALSE, FALSE, 4 /*RetryMode*/, IFS_BACKOFF /*FrameGap*/, RTMP_GET_PACKET_TXRATE(pSkb) /*TxRate*/, TxSize, QueIdx, 0, FALSE /*bRTS_CTSFrame*/); TransferBufferLength = TxSize + sizeof(TXD_STRUC); if ((TransferBufferLength % 4) == 1) TransferBufferLength += 3; else if ((TransferBufferLength % 4) == 2) TransferBufferLength += 2; else if ((TransferBufferLength % 4) == 3) TransferBufferLength += 1; if ((TransferBufferLength % pAd->BulkOutMaxPacketSize) == 0) TransferBufferLength += 4; pTxContext->BulkOutSize = TransferBufferLength; pTxContext->bWaitingBulkOut = TRUE; RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << QueIdx)); pAd->TxRingTotalNumber[QueIdx]++; // sync. to PendingTx RELEASE_NDIS_PACKET(pAd, pSkb); return (NDIS_STATUS_SUCCESS); } TxRate = RTMP_GET_PACKET_TXRATE(pSkb); MpduRequired = RTMP_GET_PACKET_FRAGMENTS(pSkb); RtsRequired = RTMP_GET_PACKET_RTS(pSkb); UserPriority = RTMP_GET_PACKET_UP(pSkb); // // Prepare packet information structure which will be query for buffer descriptor // pSrcBufVA = (PVOID)pSkb->data; SrcBufLen = pSkb->len; // Check for virtual address allocation, it might fail !!! if (pSrcBufVA == NULL) { DBGPRINT(RT_DEBUG_TRACE, "pSrcBufVA == NULL\n"); return(NDIS_STATUS_RESOURCES); } if (SrcBufLen < 14) { DBGPRINT(RT_DEBUG_ERROR, "RTUSBHardTransmit --> Skb buffer error !!!\n"); return (NDIS_STATUS_FAILURE); } // // If DHCP datagram or ARP datagram , we need to send it as Low rates. // if (pAd->PortCfg.Channel <= 14) { // // Case 802.11 b/g // basic channel means that we can use CCKM's low rate as RATE_1. // if ((TxRate != RATE_1) && RTMPCheckDHCPFrame(pAd, pSkb)) TxRate = RATE_1; } else { // // Case 802.11a // We must used OFDM's low rate as RATE_6, note RATE_1 is not allow // Only OFDM support on Channel > 14 // if ((TxRate != RATE_6) && RTMPCheckDHCPFrame(pAd, pSkb)) TxRate = RATE_6; } // ------------------------------------------ // STEP 0.1 Add 802.1x protocol check. // ------------------------------------------ // For non-WPA network, 802.1x message should not encrypt even privacy is on. if (NdisEqualMemory(EAPOL, pSrcBufVA + 12, 2)) { bEAPOLFrame = TRUE; if (pAd->PortCfg.MicErrCnt >= 2) pAd->PortCfg.MicErrCnt++; } else bEAPOLFrame = FALSE; // // WPA 802.1x secured port control - drop all non-802.1x frame before port secured // if (((pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPAPSK) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->PortCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)#if WPA_SUPPLICANT_SUPPORT || (pAd->PortCfg.IEEE8021X == TRUE)#endif ) && ((pAd->PortCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) || (pAd->PortCfg.MicErrCnt >= 2)) && (bEAPOLFrame == FALSE)) { DBGPRINT(RT_DEBUG_INFO, "RTUSBHardTransmit --> Drop packet before port secured !!!\n"); return (NDIS_STATUS_FAILURE); } if (*pSrcBufVA & 0x01) // Multicast or Broadcast { bAckRequired = FALSE; INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); Cipher = pAd->PortCfg.GroupCipher; // Cipher for Multicast or Broadcast } else { bAckRequired = TRUE; Cipher = pAd->PortCfg.PairCipher; // Cipher for Unicast } // 1. traditional TX burst if (pAd->PortCfg.bEnableTxBurst && (pAd->Sequence & 0x7)) FrameGap = IFS_SIFS; // 2. frame belonging to AC that has non-zero TXOP else if (pAd->PortCfg.APEdcaParm.bValid && pAd->PortCfg.APEdcaParm.Txop[QueIdx]) FrameGap = IFS_SIFS; // 3. otherwise, always BACKOFF before transmission else FrameGap = IFS_BACKOFF; // Default frame gap mode Protocol = *(pSrcBufVA + 12) * 256 + *(pSrcBufVA + 13); // if orginal Ethernet frame contains no LLC/SNAP, then an extra LLC/SNAP encap is required if (Protocol > 1500) { pExtraLlcSnapEncap = SNAP_802_1H; if (NdisEqualMemory(IPX, pSrcBufVA + 12, 2) || NdisEqualMemory(APPLE_TALK, pSrcBufVA + 12, 2)) { pExtraLlcSnapEncap = SNAP_BRIDGE_TUNNEL; } } else pExtraLlcSnapEncap = NULL; // Update software power save state OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_DOZE); pAd->PortCfg.Psm = PWR_ACTIVE; // ----------------------------------------------------------------- // STEP 2. MAKE A COMMON 802.11 HEADER SHARED BY ENTIRE FRAGMENT BURST. // ----------------------------------------------------------------- pAd->Sequence = ((pAd->Sequence) + 1) & (MAX_SEQ_NUMBER); MAKE_802_11_HEADER(pAd, Header_802_11, pSrcBufVA, pAd->Sequence);#if 0 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) Header_802_11.FC.SubType = SUBTYPE_QDATA;#endif // -------------------------------------------------------- // STEP 3. FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM // Find the WPA key, either Group or Pairwise Key // LEAP + TKIP also use WPA key. // -------------------------------------------------------- // Decide WEP bit and cipher suite to be used. Same cipher suite should be used for whole fragment burst // In Cisco CCX 2.0 Leap Authentication // WepStatus is Ndis802_11Encryption1Enabled but the key will use PairwiseKey // Instead of the SharedKey, SharedKey Length may be Zero. KeyIdx = 0xff; if (bEAPOLFrame) { ASSERT(pAd->SharedKey[0].CipherAlg <= CIPHER_CKIP128); if ((pAd->SharedKey[0].CipherAlg) && (pAd->SharedKey[0].KeyLen) ) { CipherAlg = pAd->SharedKey[0].CipherAlg; KeyIdx = 0; } } else if (Cipher == Ndis802_11Encryption1Enabled) { // standard WEP64 or WEP128 KeyIdx = pAd->PortCfg.DefaultKeyId; } else if ((Cipher == Ndis802_11Encryption2Enabled) || (Cipher == Ndis802_11Encryption3Enabled)) { if (Header_802_11.Addr1[0] & 0x01) // multicast KeyIdx = pAd->PortCfg.DefaultKeyId; else if (pAd->SharedKey[0].KeyLen) KeyIdx = 0; else KeyIdx = pAd->PortCfg.DefaultKeyId; } if (KeyIdx == 0xff) CipherAlg = CIPHER_NONE; else if (pAd->SharedKey[KeyIdx].KeyLen == 0) CipherAlg = CIPHER_NONE; else { Header_802_11.FC.Wep = 1; CipherAlg = pAd->SharedKey[KeyIdx].CipherAlg; pKey = &pAd->SharedKey[KeyIdx]; } DBGPRINT(RT_DEBUG_INFO,"RTUSBHardTransmit(bEAP=%d) - %s key#%d, KeyLen=%d\n", bEAPOLFrame, CipherName[CipherAlg], KeyIdx, pAd->SharedKey[KeyIdx].KeyLen); // STEP 3.1 if TKIP is used and fragmentation is required. Driver has to // append TKIP MIC at tail of the scatter buffer (This must be the // ONLY scatter buffer in the skb buffer). // MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC if ((MpduRequired > 1) && (CipherAlg == CIPHER_TKIP)) { pSkb->len += 8; CipherAlg = CIPHER_TKIP_NO_MIC; } // ---------------------------------------------------------------- // STEP 4. Make RTS frame or CTS-to-self frame if required // ---------------------------------------------------------------- // // calcuate the overhead bytes that encryption algorithm may add. This // affects the calculate of "duration" field // if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) EncryptionOverhead = 8; //WEP: IV[4] + ICV[4]; else if (CipherAlg == CIPHER_TKIP_NO_MIC) EncryptionOverhead = 12;//TKIP: IV[4] + EIV[4] + ICV[4], MIC will be added to TotalPacketLength else if (CipherAlg == CIPHER_TKIP) EncryptionOverhead = 20;//TKIP: IV[4] + EIV[4] + ICV[4] + MIC[8] else if (CipherAlg == CIPHER_AES) EncryptionOverhead = 16; // AES: IV[4] + EIV[4] + MIC[8] else EncryptionOverhead = 0; // decide how much time an ACK/CTS frame will consume in the air AckDuration = RTMPCalcDuration(pAd, pAd->PortCfg.ExpectedACKRate[TxRate], 14); // If fragment required, MPDU size is maximum fragment size // Else, MPDU size should be frame with 802.11 header & CRC if (MpduRequired > 1) NextMpduSize = pAd->PortCfg.FragmentThreshold; else { NextMpduSize = pSkb->len + LENGTH_802_11 + LENGTH_CRC - LENGTH_802_3; if (pExtraLlcSnapEncap) NextMpduSize += LENGTH_802_1_H; } if (RtsRequired || OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_RTS_PROTECTION_ENABLE)) { RTMPSendRTSCTSFrame(pAd, Header_802_11.Addr1, NextMpduSize + EncryptionOverhead, TxRate, pAd->PortCfg.RtsRate, AckDuration, QueIdx, FrameGap, SUBTYPE_RTS); // RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS RetryMode = LONG_RETRY; FrameGap = IFS_SIFS; bRTS_CTSFrame = TRUE; if (RtsRequired) NumberRequired--; } else if ((pAd->PortCfg.TxRate >= RATE_FIRST_OFDM_RATE) && OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) { RTMPSendRTSCTSFrame(pAd, Header_802_11.Addr1, NextMpduSize + EncryptionOverhead, TxRate, pAd->PortCfg.RtsRate, AckDuration, QueIdx, FrameGap, SUBTYPE_CTS); // RTS/CTS-protected frame should use LONG_RETRY (=4) and SIFS RetryMode = LONG_RETRY; FrameGap = IFS_SIFS; bRTS_CTSFrame = TRUE; } // -------------------------------------------------------- // STEP 5. START MAKING MPDU(s) // Start Copy Ndis Packet into Ring buffer. // For frame required more than one ring buffer (fragment), all ring buffers // have to be filled before kicking start tx bit. // Make sure TX ring resource won't be used by other threads // -------------------------------------------------------- SrcRemainingBytes = pSkb->len - LENGTH_802_3; SrcBufLen -= LENGTH_802_3; // skip 802.3 header StartOfFrame = TRUE; MICFrag = FALSE; // Flag to indicate MIC shall spread into two MPDUs // Start Copy Ndis Packet into Ring buffer. // For frame required more than one ring buffer (fragment), all ring buffers // have to be filled before kicking start tx bit. do { // // STEP 5.1 Get the Tx Ring descriptor & Dma Buffer address // pTxContext = &pAd->TxContext[QueIdx][pAd->NextTxIndex[QueIdx]]; if ((pTxContext->bWaitingBulkOut == TRUE) || (pTxContext->InUse == TRUE) || (pAd->TxRingTotalNumber[QueIdx] >= TX_RING_SIZE)) { //Modified by Thomas DBGPRINT_ERR("RTUSBHardTransmit: TX RING full\n"); //pAd->RalinkCounters.TxRingErrCount++; //return (NDIS_STATUS_RESOURCES); return (NDIS_STATUS_RINGFULL); } pTxContext->InUse = TRUE; // Increase & maintain Tx Ring Index pAd->NextTxIndex[QueIdx]++; if (pAd->NextTxIndex[QueIdx] >= TX_RING_SIZE) { pAd->NextTxIndex[QueIdx] = 0; }#ifndef BIG_ENDIAN pTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc;#else pDestTxD = (PTXD_STRUC) &pTxContext->TransferBuffer->TxDesc; TxD = *pDestTxD; pTxD = &TxD; RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD);#endif memset(pTxD, 0, sizeof(TXD_STRUC)); pWirelessPacket = pTxContext->TransferBuffer->WirelessPacket; // // STEP 5.2 PUT IVOFFSET, IV, EIV INTO TXD // pTxD->IvOffset = LENGTH_802_11;#if 0 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)) pTxD->IvOffset += 2; // add QOS CONTROL bytes#endif if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128)) { PUCHAR pTmp; pTmp = (PUCHAR) &pTxD->Iv; *pTmp = RandomByte(pAd); *(pTmp + 1) = RandomByte(pAd); *(pTmp + 2) = RandomByte(pAd); *(pTmp + 3) = (KeyIdx << 6); } else if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC)) { RTMPInitTkipEngine( pAd, pKey->Key, KeyIdx, // This might cause problem when using peer key Header_802_11.Addr2, pKey->TxMic, pKey->TxTsc, &Iv16, &Iv32); memcpy(&pTxD->Iv, &Iv16, 4); // Copy IV memcpy(&pTxD->Eiv, &Iv32, 4); // Copy EIV INC_TX_TSC(pKey->TxTsc); // Increase TxTsc for next transmission
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -