void	MngWorkItem(void *Context)
{
	PSRxMgmtPacket			pRxMgmtPacket;
	PSDevice	pDevice =  (PSDevice) Context;

	spin_lock_irq(&pDevice->lock);
	while (pDevice->rxManeQueue.packet_num != 0) {
		pRxMgmtPacket =  DeQueue(pDevice);
		vMgrRxManagePacket(pDevice, pDevice->pMgmt, pRxMgmtPacket);
	}
	spin_unlock_irq(&pDevice->lock);
}
Exemple #2
0
bool
device_receive_frame(
	PSDevice pDevice,
	PSRxDesc pCurrRD
)
{
	PDEVICE_RD_INFO  pRDInfo = pCurrRD->pRDInfo;
	struct net_device_stats *pStats = &pDevice->stats;
	struct sk_buff *skb;
	PSMgmtObject    pMgmt = pDevice->pMgmt;
	PSRxMgmtPacket  pRxPacket = &(pDevice->pMgmt->sRxPacket);
	PS802_11Header  p802_11Header;
	unsigned char *pbyRsr;
	unsigned char *pbyNewRsr;
	unsigned char *pbyRSSI;
	PQWORD          pqwTSFTime;
	unsigned short *pwFrameSize;
	unsigned char *pbyFrame;
	bool bDeFragRx = false;
	bool bIsWEP = false;
	unsigned int cbHeaderOffset;
	unsigned int FrameSize;
	unsigned short wEtherType = 0;
	int             iSANodeIndex = -1;
	int             iDANodeIndex = -1;
	unsigned int ii;
	unsigned int cbIVOffset;
	bool bExtIV = false;
	unsigned char *pbyRxSts;
	unsigned char *pbyRxRate;
	unsigned char *pbySQ;
	unsigned int cbHeaderSize;
	PSKeyItem       pKey = NULL;
	unsigned short wRxTSC15_0 = 0;
	unsigned long dwRxTSC47_16 = 0;
	SKeyItem        STempKey;
	// 802.11h RPI
	unsigned long dwDuration = 0;
	long            ldBm = 0;
	long            ldBmThreshold = 0;
	PS802_11Header pMACHeader;
	bool bRxeapol_key = false;

	skb = pRDInfo->skb;

//PLICE_DEBUG->
	pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma,
			 pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE);
//PLICE_DEBUG<-
	pwFrameSize = (unsigned short *)(skb->data + 2);
	FrameSize = cpu_to_le16(pCurrRD->m_rd1RD1.wReqCount) - cpu_to_le16(pCurrRD->m_rd0RD0.wResCount);

	// Max: 2312Payload + 30HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
	// Min (ACK): 10HD +4CRC + 2Padding + 4Len + 8TSF + 4RSR
	if ((FrameSize > 2364) || (FrameSize <= 32)) {
		// Frame Size error drop this packet.
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 1\n");
		return false;
	}

	pbyRxSts = (unsigned char *)(skb->data);
	pbyRxRate = (unsigned char *)(skb->data + 1);
	pbyRsr = (unsigned char *)(skb->data + FrameSize - 1);
	pbyRSSI = (unsigned char *)(skb->data + FrameSize - 2);
	pbyNewRsr = (unsigned char *)(skb->data + FrameSize - 3);
	pbySQ = (unsigned char *)(skb->data + FrameSize - 4);
	pqwTSFTime = (PQWORD)(skb->data + FrameSize - 12);
	pbyFrame = (unsigned char *)(skb->data + 4);

	// get packet size
	FrameSize = cpu_to_le16(*pwFrameSize);

	if ((FrameSize > 2346)|(FrameSize < 14)) { // Max: 2312Payload + 30HD +4CRC
		// Min: 14 bytes ACK
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n");
		return false;
	}
//PLICE_DEBUG->
	// update receive statistic counter
	STAvUpdateRDStatCounter(&pDevice->scStatistic,
				*pbyRsr,
				*pbyNewRsr,
				*pbyRxRate,
				pbyFrame,
				FrameSize);

	pMACHeader = (PS802_11Header)((unsigned char *)(skb->data) + 8);
//PLICE_DEBUG<-
	if (pDevice->bMeasureInProgress) {
		if ((*pbyRsr & RSR_CRCOK) != 0)
			pDevice->byBasicMap |= 0x01;

		dwDuration = (FrameSize << 4);
		dwDuration /= acbyRxRate[*pbyRxRate%MAX_RATE];
		if (*pbyRxRate <= RATE_11M) {
			if (*pbyRxSts & 0x01) {
				// long preamble
				dwDuration += 192;
			} else {
				// short preamble
				dwDuration += 96;
			}
		} else {
			dwDuration += 16;
		}
		RFvRSSITodBm(pDevice, *pbyRSSI, &ldBm);
		ldBmThreshold = -57;
		for (ii = 7; ii > 0;) {
			if (ldBm > ldBmThreshold)
				break;

			ldBmThreshold -= 5;
			ii--;
		}
		pDevice->dwRPIs[ii] += dwDuration;
		return false;
	}

	if (!is_multicast_ether_addr(pbyFrame)) {
		if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (PS802_11Header)(skb->data + 4))) {
			pDevice->s802_11Counter.FrameDuplicateCount++;
			return false;
		}
	}

	// Use for TKIP MIC
	s_vGetDASA(skb->data+4, &cbHeaderSize, &pDevice->sRxEthHeader);

	// filter packet send from myself
	if (ether_addr_equal(pDevice->sRxEthHeader.abySrcAddr,
			     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 = (PS802_11Header)(pbyFrame);
			// get SA NodeIndex
			if (BSSDBbIsSTAInNodeDB(pMgmt, (unsigned char *)(p802_11Header->abyAddr2), &iSANodeIndex)) {
				pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies;
				pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0;
			}
		}
	}

	if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
		if (s_bAPModeRxCtl(pDevice, pbyFrame, iSANodeIndex))
			return false;
	}

	if (IS_FC_WEP(pbyFrame)) {
		bool bRxDecryOK = false;

		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "rx WEP pkt\n");
		bIsWEP = true;
		if ((pDevice->bEnableHostWEP) && (iSANodeIndex >= 0)) {
			pKey = &STempKey;
			pKey->byCipherSuite = pMgmt->sNodeDBTable[iSANodeIndex].byCipherSuite;
			pKey->dwKeyIndex = pMgmt->sNodeDBTable[iSANodeIndex].dwKeyIndex;
			pKey->uKeyLength = pMgmt->sNodeDBTable[iSANodeIndex].uWepKeyLength;
			pKey->dwTSC47_16 = pMgmt->sNodeDBTable[iSANodeIndex].dwTSC47_16;
			pKey->wTSC15_0 = pMgmt->sNodeDBTable[iSANodeIndex].wTSC15_0;
			memcpy(pKey->abyKey,
			       &pMgmt->sNodeDBTable[iSANodeIndex].abyWepKey[0],
			       pKey->uKeyLength
);

			bRxDecryOK = s_bHostWepRxEncryption(pDevice,
							    pbyFrame,
							    FrameSize,
							    pbyRsr,
							    pMgmt->sNodeDBTable[iSANodeIndex].bOnFly,
							    pKey,
							    pbyNewRsr,
							    &bExtIV,
							    &wRxTSC15_0,
							    &dwRxTSC47_16);
		} else {
			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 ((pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
				    (pDevice->pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
					if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_TKIP))
						pDevice->s802_11Counter.TKIPICVErrors++;
					else if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP))
						pDevice->s802_11Counter.CCMPDecryptErrors++;
				}
				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 CRC length
	FrameSize -= ETH_FCS_LEN;

	if ((!(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI))) && // unicast address
	    (IS_FRAGMENT_PKT((skb->data+4)))
) {
		// defragment
		bDeFragRx = WCTLbHandleFragment(pDevice, (PS802_11Header)(skb->data+4), FrameSize, bIsWEP, bExtIV);
		pDevice->s802_11Counter.ReceivedFragmentCount++;
		if (bDeFragRx) {
			// defrag complete
			skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb;
			FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength;

		} else {
			return false;
		}
	}

// Management & Control frame Handle
	if ((IS_TYPE_DATA((skb->data+4))) == false) {
		// Handle Control & Manage Frame

		if (IS_TYPE_MGMT((skb->data+4))) {
			unsigned char *pbyData1;
			unsigned char *pbyData2;

			pRxPacket->p80211Header = (PUWLAN_80211HDR)(skb->data+4);
			pRxPacket->cbMPDULen = FrameSize;
			pRxPacket->uRSSI = *pbyRSSI;
			pRxPacket->bySQ = *pbySQ;
			HIDWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(HIDWORD(*pqwTSFTime));
			LODWORD(pRxPacket->qwLocalTSF) = cpu_to_le32(LODWORD(*pqwTSFTime));
			if (bIsWEP) {
				// strip IV
				pbyData1 = WLAN_HDR_A3_DATA_PTR(skb->data+4);
				pbyData2 = WLAN_HDR_A3_DATA_PTR(skb->data+4) + 4;
				for (ii = 0; ii < (FrameSize - 4); ii++) {
					*pbyData1 = *pbyData2;
					pbyData1++;
					pbyData2++;
				}
			}
			pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate);
			pRxPacket->byRxChannel = (*pbyRxSts) >> 2;

			vMgrRxManagePacket((void *)pDevice, pDevice->pMgmt, pRxPacket);

			// hostap Deamon handle 802.11 management
			if (pDevice->bEnableHostapd) {
				skb->dev = pDevice->apdev;
				skb->data += 4;
				skb->tail += 4;
				skb_put(skb, FrameSize);
				skb_reset_mac_header(skb);
				skb->pkt_type = PACKET_OTHERHOST;
				skb->protocol = htons(ETH_P_802_2);
				memset(skb->cb, 0, sizeof(skb->cb));
				netif_rx(skb);
				return true;
			}
		}

		return false;
	} else {