📄 rtusb_data.c
字号:
}/* ======================================================================== Description: This is the completion routine for the USB_RxPacket which submits a URB to USBD for a transmission. Note: Called in process context. ========================================================================*/VOID RTUSBRxPacket( IN unsigned long data){ purbb_t pUrb = (purbb_t)data; PRTMP_ADAPTER pAd; PRX_CONTEXT pRxContext; PRXD_STRUC pRxD;#ifdef BIG_ENDIAN PRXD_STRUC pDestRxD; RXD_STRUC RxD;#endif PHEADER_802_11 pHeader; PUCHAR pData; PUCHAR pDA, pSA; NDIS_STATUS Status; USHORT DataSize, Msdu2Size; UCHAR Header802_3[14]; PCIPHER_KEY pWpaKey;// struct sk_buff *pSkb; BOOLEAN EAPOLFrame; struct net_device *net_dev; wlan_ng_prism2_header *ph; int i; pRxContext = (PRX_CONTEXT)pUrb->context; pAd = pRxContext->pAd; net_dev = pAd->net_dev; Status = pUrb->status; DBGPRINT(RT_DEBUG_TRACE, "--> RTUSBRxPacket len=%d, status=%d\n", pRxContext->pUrb->actual_length, Status); if(Status || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) ) { DBGPRINT(RT_DEBUG_TRACE, "<-- RTUSBRxPacket disconnected\n"); return; } do { if (pRxContext->pUrb->actual_length >= sizeof(RXD_STRUC)+ LENGTH_802_11) { pData = pRxContext->TransferBuffer;#ifndef BIG_ENDIAN pRxD = (PRXD_STRUC) pData;#else pDestRxD = (PRXD_STRUC) pData; RxD = *pDestRxD; pRxD = &RxD; RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD);#endif // Cast to 802.11 header for flags checking pHeader = (PHEADER_802_11) (pData + sizeof(RXD_STRUC) );#ifdef BIG_ENDIAN RTMPFrameEndianChange(pAd, (PUCHAR)pHeader, DIR_READ, FALSE);#endif DBGPRINT(RT_DEBUG_INFO, "- %s: Frame type %d subtype %d\n", __FUNCTION__, pHeader->FC.Type, pHeader->FC.SubType); if (pRxD->DataByteCnt < 4) Status = NDIS_STATUS_FAILURE; else { // Increase Total receive byte counter after real data received no mater any error or not pAd->RalinkCounters.ReceivedByteCount += (pRxD->DataByteCnt - 4); pAd->RalinkCounters.RxCount ++; // Check for all RxD errors Status = RTMPCheckRxDescriptor(pAd, pHeader, pRxD); } /* Only recieve valid packets in to monitor mode */ if (pAd->PortCfg.BssType == BSS_MONITOR && Status == NDIS_STATUS_SUCCESS) { struct sk_buff *skb; if ((skb = __dev_alloc_skb(2048, GFP_DMA|GFP_KERNEL)) != NULL) { if (pAd->bAcceptRFMONTx == TRUE) { if (pAd->ForcePrismHeader != 1) goto rfmontx_80211_receive; } else { if (pAd->ForcePrismHeader == 2) goto rfmontx_80211_receive; } // setup the wlan-ng prismheader if (skb_headroom(skb) < sizeof(wlan_ng_prism2_header)) pskb_expand_head(skb, sizeof(wlan_ng_prism2_header), 0, GFP_KERNEL); ph = (wlan_ng_prism2_header *) skb_push(skb, sizeof(wlan_ng_prism2_header)); memset(ph, 0, sizeof(wlan_ng_prism2_header)); ph->msgcode = DIDmsg_lnxind_wlansniffrm; ph->msglen = sizeof(wlan_ng_prism2_header); strcpy(ph->devname, pAd->net_dev->name); ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime; ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime; ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel; ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi; ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal; ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise; ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate; ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx; ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen; ph->hosttime.len = 4; ph->mactime.len = 4; ph->channel.len = 4; ph->rssi.len = 4; ph->signal.len = 4; ph->noise.len = 4; ph->rate.len = 4; ph->istx.len = 4; ph->frmlen.len = 4; ph->hosttime.data = jiffies; ph->channel.data = pAd->PortCfg.Channel; ph->signal.data = pRxD->PlcpRssi; ph->noise.data = (pAd->BbpWriteLatch[17] > pAd->BbpTuning.R17UpperBoundG) ? pAd->BbpTuning.R17UpperBoundG : ((ULONG) pAd->BbpWriteLatch[17]); ph->rssi.data = ph->signal.data - ph->noise.data; ph->frmlen.data = pRxD->DataByteCnt; if (pRxD->Ofdm == 1) { for (i = 4; i < 12; i++) if (pRxD->PlcpSignal == RateIdToPlcpSignal[i]) ph->rate.data = _11G_RATES[i] * 2; } else ph->rate.data = pRxD->PlcpSignal / 5; // end prismheader setup rfmontx_80211_receive: skb->dev = pAd->net_dev; memcpy(skb_put(skb, pRxD->DataByteCnt), pHeader, pRxD->DataByteCnt); skb_reset_mac_header(skb); skb->pkt_type = PACKET_OTHERHOST; skb->protocol = htons(ETH_P_802_2); skb->ip_summed = CHECKSUM_NONE; netif_rx(skb); } continue; } if (Status == NDIS_STATUS_SUCCESS) { // Apply packet filtering rule based on microsoft requirements. Status = RTMPApplyPacketFilter(pAd, pRxD, pHeader); } // Add receive counters if (Status == NDIS_STATUS_SUCCESS) { // Increase 802.11 counters & general receive counters INC_COUNTER64(pAd->WlanCounters.ReceivedFragmentCount); } else { // Increase general counters pAd->Counters.RxErrors++; } // Check for retry bit, if this bit is on, search the cache with SA & sequence // as index, if matched, discard this frame, otherwise, update cache // This check only apply to unicast data & management frames if ((pRxD->U2M) && (Status == NDIS_STATUS_SUCCESS) && (pHeader->FC.Type != BTYPE_CNTL)) { if (pHeader->FC.Retry) { if (RTMPSearchTupleCache(pAd, pHeader) == TRUE) { // Found retry frame in tuple cache, Discard this frame / fragment // Increase 802.11 counters INC_COUNTER64(pAd->WlanCounters.FrameDuplicateCount); DBGPRINT(RT_DEBUG_INFO, "duplicate frame %d\n", pHeader->Sequence); Status = NDIS_STATUS_FAILURE; } else { RTMPUpdateTupleCache(pAd, pHeader); } } else // Update Tuple Cache { RTMPUpdateTupleCache(pAd, pHeader); } } if ((pRxD->U2M) || ((pHeader->FC.SubType == SUBTYPE_BEACON) && (MAC_ADDR_EQUAL(&pAd->PortCfg.Bssid, &pHeader->Addr2)))) { if ((pAd->Antenna.field.NumOfAntenna == 2) && (pAd->Antenna.field.TxDefaultAntenna == 0) && (pAd->Antenna.field.RxDefaultAntenna == 0)) { COLLECT_RX_ANTENNA_AVERAGE_RSSI(pAd, ConvertToRssi(pAd, (UCHAR)pRxD->PlcpRssi, RSSI_NO_1), 0); //Note: RSSI2 not used on RT73 pAd->PortCfg.NumOfAvgRssiSample ++; } } // // Do RxD release operation for all failure frames // if (Status == NDIS_STATUS_SUCCESS) { do { // pData : Pointer skip the RxD Descriptior and the first 24 bytes, 802.11 HEADER pData += LENGTH_802_11 + sizeof(RXD_STRUC); DataSize = (USHORT) pRxD->DataByteCnt - LENGTH_802_11; // // CASE I. receive a DATA frame // if (pHeader->FC.Type == BTYPE_DATA) { DBGPRINT(RT_DEBUG_INFO, "- %s: data frame\n", __FUNCTION__); // before LINK UP, all DATA frames are rejected if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) { DBGPRINT(RT_DEBUG_TRACE,"RxDone- drop DATA frame before LINK UP(len=%d)\n",pRxD->DataByteCnt); break; } pAd->BulkInDataOneSecCount++; // remove the 2 extra QOS CNTL bytes if (pHeader->FC.SubType & 0x08) { pData += 2; DataSize -= 2; } // remove the 2 extra AGGREGATION bytes Msdu2Size = 0; if (pHeader->FC.Order) { Msdu2Size = *pData + (*(pData+1) << 8); if ((Msdu2Size <= 1536) && (Msdu2Size < DataSize)) { pData += 2; DataSize -= 2; } else Msdu2Size = 0; } // Drop not my BSS frame // // Not drop EAPOL frame, since this have happen on the first time that we link up // And need some more time to set BSSID to asic // So pRxD->MyBss may be 0 // if (RTMPEqualMemory(EAPOL, pData + 6, 2)) EAPOLFrame = TRUE; else EAPOLFrame = FALSE; if ((pRxD->MyBss == 0) && (EAPOLFrame != TRUE)) { DBGPRINT(RT_DEBUG_INFO, "- %s: !MyBss || !EAPOL\n", __FUNCTION__); break; // give up this frame } // Drop NULL (+CF-POLL) (+CF-ACK) data frame if ((pHeader->FC.SubType & 0x04) == 0x04) { DBGPRINT(RT_DEBUG_TRACE,"RxDone- drop NULL frame(subtype=%d)\n",pHeader->FC.SubType); break; } // prepare 802.3 header: DA=addr1; SA=addr3 in INFRA mode, DA=addr2 in ADHOC mode pDA = pHeader->Addr1; if (INFRA_ON(pAd)) pSA = pHeader->Addr3; else pSA = pHeader->Addr2; if (pHeader->FC.Wep) // frame received in encrypted format { if (pRxD->CipherAlg == CIPHER_NONE) // unsupported cipher suite { DBGPRINT(RT_DEBUG_INFO, "- %s: nonsup cipher\n", __FUNCTION__); break; // give up this frame } else if (pAd->SharedKey[pRxD->KeyIndex].KeyLen == 0) { DBGPRINT(RT_DEBUG_INFO, "- %s: keylen=0\n", __FUNCTION__); break; // give up this frame since the keylen is invalid. } } else { // frame received in clear text // encryption in-use but receive a non-EAPOL clear text frame, drop it if (((pAd->PortCfg.WepStatus == Ndis802_11Encryption1Enabled) || (pAd->PortCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->PortCfg.WepStatus == Ndis802_11Encryption3Enabled)) && (pAd->PortCfg.PrivacyFilter == Ndis802_11PrivFilter8021xWEP) && (!NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H))) { DBGPRINT(RT_DEBUG_INFO, "- %s: clear text\n", __FUNCTION__); break; // give up this frame } } // // Case I.1 Process Broadcast & Multicast data frame // if (pRxD->Bcast || pRxD->Mcast) { PUCHAR pRemovedLLCSNAP; INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); // Drop Mcast/Bcast frame with fragment bit on if (pHeader->FC.MoreFrag) { DBGPRINT(RT_DEBUG_INFO, "- %s: mcast w/more\n", __FUNCTION__); break; // give up this frame } // Filter out Bcast frame which AP relayed for us if (pHeader->FC.FrDs && MAC_ADDR_EQUAL(pHeader->Addr3, pAd->CurrentAddress)) { DBGPRINT(RT_DEBUG_INFO, "- %s: relay mcast\n", __FUNCTION__); break; // give up this frame } // build 802.3 header and decide if remove the 8-byte LLC/SNAP encapsulation CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP); REPORT_ETHERNET_FRAME_TO_LLC(pAd,Header802_3, pData, DataSize, pAd->net_dev); DBGPRINT(RT_DEBUG_TRACE, "!!! report BCAST DATA to LLC (len=%d) !!!\n", DataSize); } // // Case I.2 Process unicast-to-me DATA frame // else if (pRxD->U2M) { RECORD_LATEST_RX_DATA_RATE(pAd, pRxD);//#if WPA_SUPPLICANT_SUPPORT if (pAd->PortCfg.WPA_Supplicant == TRUE) { // All EAPoL frames have to pass to upper layer (ex. WPA_SUPPLICANT daemon) // TBD : process fragmented EAPol frames if(NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H)) { PUCHAR pRemovedLLCSNAP; int success = 0; // In 802.1x mode, if the received frame is EAP-SUCCESS packet, turn on the PortSecured variable if ( pAd->PortCfg.IEEE8021X == TRUE && (EAP_CODE_SUCCESS == RTMPCheckWPAframeForEapCode(pAd, pData, DataSize, LENGTH_802_1_H))) { DBGPRINT(RT_DEBUG_TRACE, "Receive EAP-SUCCESS Packet\n"); pAd->PortCfg.PortSecured = WPA_802_1X_PORT_SECURED; success = 1; } // build 802.3 header and decide if remove the 8-byte LLC/SNAP encapsulation CONVERT_TO_802_3(Header802_3, pDA, pSA, pData, DataSize, pRemovedLLCSNAP); REPORT_ETHERNET_FRAME_TO_LLC(pAd, Header802_3, pData, DataSize, net_dev); DBGPRINT(RT_DEBUG_TRACE, "!!! report EAPoL DATA to LLC (len=%d) !!!\n", DataSize); if(success) { // For static wep mode, need to set wep key to Asic again if(pAd->PortCfg.IEEE8021x_required_keys == 0) { int idx; idx = pAd->PortCfg.DefaultKeyId; for (idx=0; idx < 4; idx++) { DBGPRINT(RT_DEBUG_TRACE, "Set WEP key to Asic again =>\n"); if(pAd->PortCfg.DesireSharedKey[idx].KeyLen != 0) { union { char buf[sizeof(NDIS_802_11_WEP)+MAX_LEN_OF_KEY- 1]; NDIS_802_11_WEP keyinfo; } WepKey; int len; memset(&WepKey, 0, sizeof(WepKey)); len =pAd->PortCfg.DesireSharedKey[idx].KeyLen; memcpy(WepKey.keyinfo.KeyMaterial, pAd->PortCfg.DesireSharedKey[idx].Key, pAd->PortCfg.DesireSharedKey[idx].KeyLen); WepKey.keyinfo.KeyIndex = 0x80000000 + idx; WepKey.keyinfo.KeyLength = len; pAd->SharedKey[idx].KeyLen =(UCHAR) (len <= WEP_SMALL_KEY_LEN ? WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN); // need to enqueue cmd to thread RTUSBEnqueueCmdFromNdis(pAd, OID_802_11_ADD_WEP, TRUE, &WepKey, sizeof(WepKey.keyinfo) + len - 1); } } } } break; } } /* End (pAd->PortCfg.WPA_Supplicant == TRUE) */ else {//#else // Special DATA frame that has to pass to MLME // 1. EAPOL handshaking frames when driver supplicant enabled, pass to MLME for special process if (NdisEqualMemory(EAPOL_LLC_SNAP, pData, LENGTH_802_1_H) && (pAd->PortCfg.WpaState != SS_NOTUSE)) { DataSize += LENGTH_802_11; REPORT_MGMT_FRAME_TO_MLME(pAd, pHeader, DataSize, pRxD->PlcpRssi, pRxD->PlcpSignal); DBGPRINT(RT_DEBUG_TRACE, "!!! report EAPOL/AIRONET DATA to MLME (len=%d) !!!\n", DataSize); break; // end of processing this frame }//#endif } if (pHeader->Frag == 0) // First or Only fragment { PUCHAR pRemove
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -