/*---------------------------------------------------------------- * p80211_rx_typedrop * * Classifies the frame, increments the appropriate counter, and * returns 0|1|2 indicating whether the driver should handle, ignore, or * drop the frame * * Arguments: * wlandev wlan device structure * fc frame control field * * Returns: * zero if the frame should be handled by the driver, * one if the frame should be ignored * anything else means we drop it. * * Side effects: * * Call context: * interrupt ----------------------------------------------------------------*/ static int p80211_rx_typedrop( wlandevice_t *wlandev, UINT16 fc) { UINT16 ftype; UINT16 fstype; int drop = 0; /* Classify frame, increment counter */ ftype = WLAN_GET_FC_FTYPE(fc); fstype = WLAN_GET_FC_FSTYPE(fc); #if 0 WLAN_LOG_DEBUG(4, "rx_typedrop : ftype=%d fstype=%d.\n", ftype, fstype); #endif switch ( ftype ) { case WLAN_FTYPE_MGMT: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } WLAN_LOG_DEBUG(3, "rx'd mgmt:\n"); wlandev->rx.mgmt++; switch( fstype ) { case WLAN_FSTYPE_ASSOCREQ: /* printk("assocreq"); */ wlandev->rx.assocreq++; break; case WLAN_FSTYPE_ASSOCRESP: /* printk("assocresp"); */ wlandev->rx.assocresp++; break; case WLAN_FSTYPE_REASSOCREQ: /* printk("reassocreq"); */ wlandev->rx.reassocreq++; break; case WLAN_FSTYPE_REASSOCRESP: /* printk("reassocresp"); */ wlandev->rx.reassocresp++; break; case WLAN_FSTYPE_PROBEREQ: /* printk("probereq"); */ wlandev->rx.probereq++; break; case WLAN_FSTYPE_PROBERESP: /* printk("proberesp"); */ wlandev->rx.proberesp++; break; case WLAN_FSTYPE_BEACON: /* printk("beacon"); */ wlandev->rx.beacon++; break; case WLAN_FSTYPE_ATIM: /* printk("atim"); */ wlandev->rx.atim++; break; case WLAN_FSTYPE_DISASSOC: /* printk("disassoc"); */ wlandev->rx.disassoc++; break; case WLAN_FSTYPE_AUTHEN: /* printk("authen"); */ wlandev->rx.authen++; break; case WLAN_FSTYPE_DEAUTHEN: /* printk("deauthen"); */ wlandev->rx.deauthen++; break; default: /* printk("unknown"); */ wlandev->rx.mgmt_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_CTL: if ((wlandev->netdev->flags & IFF_PROMISC) || (wlandev->netdev->flags & IFF_ALLMULTI)) { drop = 1; break; } WLAN_LOG_DEBUG(3, "rx'd ctl:\n"); wlandev->rx.ctl++; switch( fstype ) { case WLAN_FSTYPE_PSPOLL: /* printk("pspoll"); */ wlandev->rx.pspoll++; break; case WLAN_FSTYPE_RTS: /* printk("rts"); */ wlandev->rx.rts++; break; case WLAN_FSTYPE_CTS: /* printk("cts"); */ wlandev->rx.cts++; break; case WLAN_FSTYPE_ACK: /* printk("ack"); */ wlandev->rx.ack++; break; case WLAN_FSTYPE_CFEND: /* printk("cfend"); */ wlandev->rx.cfend++; break; case WLAN_FSTYPE_CFENDCFACK: /* printk("cfendcfack"); */ wlandev->rx.cfendcfack++; break; default: /* printk("unknown"); */ wlandev->rx.ctl_unknown++; break; } /* printk("\n"); */ drop = 2; break; case WLAN_FTYPE_DATA: wlandev->rx.data++; switch( fstype ) { case WLAN_FSTYPE_DATAONLY: wlandev->rx.dataonly++; break; case WLAN_FSTYPE_DATA_CFACK: wlandev->rx.data_cfack++; break; case WLAN_FSTYPE_DATA_CFPOLL: wlandev->rx.data_cfpoll++; break; case WLAN_FSTYPE_DATA_CFACK_CFPOLL: wlandev->rx.data__cfack_cfpoll++; break; case WLAN_FSTYPE_NULL: WLAN_LOG_DEBUG(3, "rx'd data:null\n"); wlandev->rx.null++; break; case WLAN_FSTYPE_CFACK: WLAN_LOG_DEBUG(3, "rx'd data:cfack\n"); wlandev->rx.cfack++; break; case WLAN_FSTYPE_CFPOLL: WLAN_LOG_DEBUG(3, "rx'd data:cfpoll\n"); wlandev->rx.cfpoll++; break; case WLAN_FSTYPE_CFACK_CFPOLL: WLAN_LOG_DEBUG(3, "rx'd data:cfack_cfpoll\n"); wlandev->rx.cfack_cfpoll++; break; default: /* printk("unknown"); */ wlandev->rx.data_unknown++; break; } break; } return drop; }
int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB, unsigned long BytesToIndicate) { struct net_device_stats *pStats = &pDevice->stats; struct sk_buff *skb; struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket; struct ieee80211_hdr *p802_11Header; u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame; u64 *pqwTSFTime; u32 bDeFragRx = false; u32 cbHeaderOffset, cbIVOffset; u32 FrameSize; u16 wEtherType = 0; s32 iSANodeIndex = -1; int ii; u8 *pbyRxSts, *pbyRxRate, *pbySQ, *pby3SQ; u32 cbHeaderSize; PSKeyItem pKey = NULL; u16 wRxTSC15_0 = 0; u32 dwRxTSC47_16 = 0; /* signed long ldBm = 0; */ int bIsWEP = false; int bExtIV = false; u32 dwWbkStatus; struct vnt_rcb *pRCBIndicate = pRCB; u8 *pbyDAddress; u16 *pwPLCP_Length; u8 abyVaildRate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108}; u16 wPLCPwithPadding; struct ieee80211_hdr *pMACHeader; int bRxeapol_key = false; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n"); skb = pRCB->skb; /* [31:16]RcvByteCount ( not include 4-byte Status ) */ dwWbkStatus = *((u32 *)(skb->data)); FrameSize = dwWbkStatus >> 16; FrameSize += 4; if (BytesToIndicate != FrameSize) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n"); pStats->rx_frame_errors++; return false; } if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) { // Frame Size error drop this packet. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n"); pStats->rx_frame_errors++; return false; } pbyDAddress = (u8 *)(skb->data); pbyRxSts = pbyDAddress+4; pbyRxRate = pbyDAddress+5; //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding //if SQ3 the range is 24~27, if no SQ3 the range is 20~23 //real Frame size in PLCPLength field. pwPLCP_Length = (u16 *) (pbyDAddress + 6); //Fix hardware bug => PLCP_Length error if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) || ((BytesToIndicate - (*pwPLCP_Length)) < 24) || (BytesToIndicate < (*pwPLCP_Length)) ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length); pStats->rx_frame_errors++; return false; } for ( ii=RATE_1M;ii<MAX_RATE;ii++) { if ( *pbyRxRate == abyVaildRate[ii] ) { break; } } if ( ii==MAX_RATE ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong RxRate %x\n",(int) *pbyRxRate); return false; } wPLCPwithPadding = ( (*pwPLCP_Length / 4) + ( (*pwPLCP_Length % 4) ? 1:0 ) ) *4; pqwTSFTime = (u64 *)(pbyDAddress + 8 + wPLCPwithPadding); if(pDevice->byBBType == BB_TYPE_11G) { pby3SQ = pbyDAddress + 8 + wPLCPwithPadding + 12; pbySQ = pby3SQ; } else { pbySQ = pbyDAddress + 8 + wPLCPwithPadding + 8; pby3SQ = pbySQ; } pbyNewRsr = pbyDAddress + 8 + wPLCPwithPadding + 9; pbyRSSI = pbyDAddress + 8 + wPLCPwithPadding + 10; pbyRsr = pbyDAddress + 8 + wPLCPwithPadding + 11; FrameSize = *pwPLCP_Length; pbyFrame = pbyDAddress + 8; pMACHeader = (struct ieee80211_hdr *) pbyFrame; //mike add: to judge if current AP is activated? if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) || (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) { if (pMgmt->sNodeDBTable[0].bActive) { if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) { if (pMgmt->sNodeDBTable[0].uInActiveCount != 0) pMgmt->sNodeDBTable[0].uInActiveCount = 0; } } } if (!is_multicast_ether_addr(pMACHeader->addr1)) { if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) { return false; } if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) { return false; } } // Use for TKIP MIC s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader); if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source, pDevice->abyCurrentNetAddr)) return false; if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) { if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) { p802_11Header = (struct ieee80211_hdr *) (pbyFrame); // get SA NodeIndex if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) { pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies; pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0; } } } if (IS_FC_WEP(pbyFrame)) { bool bRxDecryOK = false; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n"); bIsWEP = true; bRxDecryOK = s_bHandleRxEncryption(pDevice, pbyFrame, FrameSize, pbyRsr, pbyNewRsr, &pKey, &bExtIV, &wRxTSC15_0, &dwRxTSC47_16); if (bRxDecryOK) { if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n"); if ( (pMgmt->eAuthenMode == WMAC_AUTH_WPA) || (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) || (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) || (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) || (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) { } return false; } } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n"); return false; } if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP)) FrameSize -= 8; // Message Integrity Code else FrameSize -= 4; // 4 is ICV } // // RX OK // /* remove the FCS/CRC length */ FrameSize -= ETH_FCS_LEN; if ( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) && // unicast address (IS_FRAGMENT_PKT((pbyFrame))) ) { // defragment bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV); if (bDeFragRx) { // defrag complete // TODO skb, pbyFrame skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb; FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength; pbyFrame = skb->data + 8; } else { return false; } } // // Management & Control frame Handle // if ((IS_TYPE_DATA((pbyFrame))) == false) { // Handle Control & Manage Frame if (IS_TYPE_MGMT((pbyFrame))) { u8 * pbyData1; u8 * pbyData2; pRxPacket = &(pRCB->sMngPacket); pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame); pRxPacket->cbMPDULen = FrameSize; pRxPacket->uRSSI = *pbyRSSI; pRxPacket->bySQ = *pbySQ; pRxPacket->qwLocalTSF = cpu_to_le64(*pqwTSFTime); if (bIsWEP) { // strip IV pbyData1 = WLAN_HDR_A3_DATA_PTR(pbyFrame); pbyData2 = WLAN_HDR_A3_DATA_PTR(pbyFrame) + 4; for (ii = 0; ii < (FrameSize - 4); ii++) { *pbyData1 = *pbyData2; pbyData1++; pbyData2++; } } pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate); if ( *pbyRxSts == 0 ) { //Discard beacon packet which channel is 0 if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) || (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) { return false; } } pRxPacket->byRxChannel = (*pbyRxSts) >> 2; // // Insert the RCB in the Recv Mng list // EnqueueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList, pRCBIndicate); pDevice->NumRecvMngList++; if ( bDeFragRx == false) { pRCB->Ref++; } if (pDevice->bIsRxMngWorkItemQueued == false) { pDevice->bIsRxMngWorkItemQueued = true; schedule_work(&pDevice->rx_mng_work_item); } } else { // Control Frame };