sanity.c

来自「台湾RALink公司的 rt2570无线 802.11g 网卡的 驱动的源代码 」· C语言 代码 · 共 957 行 · 第 1/2 页

C
957
字号
	UCHAR				Sanity;

	// Add for 3 necessary EID field check
	Sanity = 0;

    *ExtendedRateIeExist = FALSE;
    *Erp = 0;
	*LengthVIE = 0;					// Set the length of VIE to init value 0
    
    Fr = (MACFRAME *)Msg;
    
    // get subtype from header
    SubType = (UCHAR)Fr->Hdr.SubType;

    // get Addr2 and BSSID from header
    COPY_MAC_ADDR(Addr2, &Fr->Hdr.Addr2);
    COPY_MAC_ADDR(Bssid, &Fr->Hdr.Addr3);
    
    Ptr = Fr->Octet;
    
    // get timestamp from payload and advance the pointer
    NdisMoveMemory(Timestamp, Ptr, TIMESTAMP_LEN);
    Ptr += TIMESTAMP_LEN;

    // get beacon interval from payload and advance the pointer
    NdisMoveMemory(BeaconPeriod, Ptr, 2);
    Ptr += 2;

    // get capability info from payload and advance the pointer
    NdisMoveMemory(CapabilityInfo, Ptr, 2);
    Ptr += 2;
    if (CAP_IS_ESS_ON(*CapabilityInfo)) 
    {
        *BssType = BSS_INFRA;
    } 
    else 
    {
        *BssType = BSS_INDEP;
    }

	// Mask out unnecessary capability information
	*CapabilityInfo &= SUPPORTED_CAPABILITY_INFO;
	
    eid_ptr = (PBEACON_EID_STRUCT) Ptr;

    // get variable fields from payload and advance the pointer
    while(((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
    {
        switch(eid_ptr->Eid)
        {
            case IE_SSID:
				// Already has one SSID EID in this beacon, ignore the second one
				if (Sanity & 0x1)
					break;				
                if(eid_ptr->Len <= MAX_LEN_OF_SSID)
                {
                    NdisMoveMemory(Ssid, eid_ptr->Octet, eid_ptr->Len);
                    *SsidLen = eid_ptr->Len;
					Sanity |= 0x1;
                }
                else
                {
                    DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_SSID (len=%d)\n",eid_ptr->Len);
                    return FALSE;
                }
                break;

            case IE_SUPP_RATES:
                if(eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES)
                {
            		int		index;
            		UCHAR	rate, i;
            		PUCHAR	eid_rate;

            		i = 0;
            		eid_rate = eid_ptr->Octet;
            		for (index = 0; index < eid_ptr->Len; index++)
            		{
            			rate = eid_rate[index] & 0x7f; // Mask out basic rate set bit
            			if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22) ||
            			    (rate == 12) || (rate == 18) || (rate == 24) || (rate == 36) ||
            			    (rate == 48) || (rate == 72) || (rate == 96) || (rate == 108))
            				Rate[i++] = eid_rate[index];	// Save rate with basic rate set bit if exists
            		}
            		*RateLen = i;
					Sanity |= 0x2;
					// Copy supported rate from desired AP's beacon. We are trying to match
					// AP's supported and extended rate settings.
					NdisMoveMemory(SupRate, eid_ptr->Octet, eid_ptr->Len);
					*SupRateLen = eid_ptr->Len;
					// Check against the supported rates
					RTMPCheckRates(pAd, SupRate, SupRateLen);
                }
                else
                {
                    DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_SUPP_RATES (len=%d)\n",eid_ptr->Len);
                    return FALSE;
                }
                break;

            case IE_FH_PARM:
                DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity(IE_FH_PARM) \n");
                break;

            case IE_DS_PARM:
                if(eid_ptr->Len == 1)
                {
                    *Channel = *eid_ptr->Octet;                    
                    if (ChannelSanity(pAd, *Channel) == 0)
                    {
                        DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (ch=%d)\n",*Channel);
                        return FALSE;
                    }
					Sanity |= 0x4;
                }
                else
                {
                    DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_DS_PARM (len=%d)\n",eid_ptr->Len);
                    return FALSE;
                }
                break;

            case IE_CF_PARM:
                if(eid_ptr->Len == 6)
                {
                    *CfExist = TRUE;
                    NdisMoveMemory(CfParm, eid_ptr->Octet, eid_ptr->Len);
                }
                else
                {
                    DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_CF_PARM\n");
                    return FALSE;
                }
                break;

            case IE_IBSS_PARM:
                if(eid_ptr->Len == 2)
                {
                    NdisMoveMemory(AtimWin, eid_ptr->Octet, eid_ptr->Len);
                }
                else
                {
                    DBGPRINT(RT_DEBUG_TRACE, "PeerBeaconAndProbeRspSanity - wrong IE_IBSS_PARM\n");
                    return FALSE;
                }
                break;

            case IE_TIM:
                if(INFRA_ON(pAd) && SubType == SUBTYPE_BEACON)
                {
                    GetTimBit((PUCHAR)eid_ptr, pAd->PortCfg.Aid, &TimLen, BcastFlag, DtimCount, DtimPeriod, MessageToMe);
                }
                break;

			// New for WPA
			case IE_WPA:
				// Check the OUI version, filter out non-standard usage
				if (RTMPEqualMemory(eid_ptr->Octet, WPA_OUI, 4))
				{
					// Copy to pVIE which will report to microsoft bssid list.
					Ptr = (PUCHAR) pVIE;
					NdisMoveMemory(Ptr + *LengthVIE, &eid_ptr->Eid, eid_ptr->Len + 2);
					*LengthVIE += (eid_ptr->Len + 2);
				}
				DBGPRINT(RT_DEBUG_INFO, "PeerBeaconAndProbeRspSanity - Receive IE_WPA\n");
				break;

			case IE_EXT_SUPP_RATES:
			    // concatenate all extended rates to Rates[] and RateLen
			    *ExtendedRateIeExist = TRUE;
                if (eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES)
                {
            		int		index;
            		UCHAR	rate, i;
            		PUCHAR	eid_rate;

            		i = *RateLen;
            		eid_rate = eid_ptr->Octet;
            		for (index = 0; index < eid_ptr->Len; index++)
            		{
            			rate = eid_rate[index] & 0x7f; // Mask out basic rate set bit
            			if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22) ||
            			    (rate == 12) || (rate == 18) || (rate == 24) || (rate == 36) ||
            			    (rate == 48) || (rate == 72) || (rate == 96) || (rate == 108))
            				Rate[i++] = eid_rate[index];	// Save rate with basic rate set bit if exists

            		    if (i >= MAX_LEN_OF_SUPPORTED_RATES)
            		        break;
            		}
            		*RateLen = i;
					// Copy extended rate from desired AP's beacon. We are trying to match
					// AP's supported and extended rate settings.
					NdisMoveMemory(ExtRate, eid_ptr->Octet, eid_ptr->Len);
					*ExtRateLen = eid_ptr->Len;
					// Check against the supported rates
					RTMPCheckRates(pAd, ExtRate, ExtRateLen);
				}
			    break;

            case IE_ERP:
                if (eid_ptr->Len == 1)
                {
                    *Erp = (UCHAR)eid_ptr->Octet[0];
                }
                break;
                
			// WPA2 & 802.11i RSN
			case IE_RSN:
				// There is no OUI for version anymore, check the group cipher OUI before copying
				if (RTMPEqualMemory(eid_ptr->Octet + 2, RSN_OUI, 3))
				{
					// Copy to pVIE which will report to microsoft bssid list.
					Ptr = (PUCHAR) pVIE;
					NdisMoveMemory(Ptr + *LengthVIE, &eid_ptr->Eid, eid_ptr->Len + 2);
					*LengthVIE += (eid_ptr->Len + 2);
				}
                DBGPRINT(RT_DEBUG_INFO, "IE_RSN length = %d\n", eid_ptr->Len);
                break;
				
            default:
                DBGPRINT(RT_DEBUG_INFO, "PeerBeaconAndProbeRspSanity - unrecognized EID = %d\n", eid_ptr->Eid);
                break;
        }
        
        eid_ptr = (PBEACON_EID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);        
    }

    // in 802.11a band, AP may skip this DS IE in their BEACON
    if ((pAd->PortCfg.Channel > 14) && ((Sanity & 0x04)==0))
    {
        *Channel = pAd->PortCfg.Channel;
        Sanity |= 0x04;
    }
    
    if (Sanity != 0x7)
    {
        DBGPRINT(RT_DEBUG_WARN, "PeerBeaconAndProbeRspSanity - missing field, Sanity=0x%02x\n", Sanity);
        return FALSE;
    }
    else
    {
        return TRUE;
    }

}

/* 
    ==========================================================================
    Description:
        
	IRQL = DISPATCH_LEVEL

    ==========================================================================
 */
BOOLEAN GetTimBit(
    IN CHAR *Ptr, 
    IN USHORT Aid, 
    OUT UCHAR *TimLen, 
    OUT UCHAR *BcastFlag, 
    OUT UCHAR *DtimCount, 
    OUT UCHAR *DtimPeriod,
    OUT UCHAR *MessageToMe) 
{
    UCHAR          BitCntl, N1, N2, MyByte, MyBit;
    CHAR          *IdxPtr;

    IdxPtr = Ptr;
    
    IdxPtr ++;
    *TimLen = *IdxPtr;
    
    // get DTIM Count from TIM element
    IdxPtr ++;
    *DtimCount = *IdxPtr;
    
    // get DTIM Period from TIM element
    IdxPtr++;
    *DtimPeriod = *IdxPtr;
        
    // get Bitmap Control from TIM element
    IdxPtr++;
    BitCntl = *IdxPtr;

    if ((*DtimCount == 0) && (BitCntl & 0x01)) 
        *BcastFlag = TRUE;
    else 
        *BcastFlag = FALSE;
    
    // Parse Partial Virtual Bitmap from TIM element
    N1 = BitCntl & 0xfe;    // N1 is the first bitmap byte#
    N2 = *TimLen - 4 + N1;  // N2 is the last bitmap byte#
    
    if ((Aid < (N1 << 3)) || (Aid >= ((N2 + 1) << 3)))
        *MessageToMe = FALSE;
    else
    {
        MyByte = (Aid >> 3) - N1;                       // my byte position in the bitmap byte-stream
        MyBit = Aid % 16 - ((MyByte & 0x01)? 8:0);

        IdxPtr += (MyByte + 1);

        //if (*IdxPtr)
        //    DBGPRINT(RT_DEBUG_WARN, ("TIM bitmap = 0x%02x\n", *IdxPtr));
            
        if (*IdxPtr & (0x01 << MyBit))
            *MessageToMe = TRUE;
        else 
            *MessageToMe = FALSE;
    }

    return TRUE;
}

/*!
 *  \brief Get legacy bit, right now for 11b it is always 0
 *  \param
 *  \return TRUE if the parameters are OK, FALSE otherwise. Always return TRUE
 *  \pre
 *  \post
 */
BOOLEAN GetLegacy(
    IN CHAR *Ptr, 
    OUT UCHAR *Legacy) 
{
    *Legacy = 0;
    return TRUE;
}

// IRQL = DISPATCH_LEVEL
UCHAR ChannelSanity(
    IN PRT2570ADAPTER pAd, 
    IN UCHAR channel)
{
    UCHAR index;

    for (index = 0; index < pAd->PortCfg.ChannelListNum; index ++)
    {
        if (channel == pAd->PortCfg.ChannelList[index])
            return 1;
    }
    return 0;
}

/*
	========================================================================
	Routine Description:
		Sanity check NetworkType (11b, 11g or 11a)
		
	Arguments:
		pBss - Pointer to BSS table.

	Return Value:
        Ndis802_11DS .......(11b)
        Ndis802_11OFDM24....(11g)
        Ndis802_11OFDM5.....(11a)
        
	IRQL = DISPATCH_LEVEL
	
	========================================================================
*/
NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(
    IN PBSS_ENTRY pBss)
{
	NDIS_802_11_NETWORK_TYPE	NetWorkType = Ndis802_11DS;
	UCHAR						rate, i;

	if (pBss->Channel <= 14)
	{
		for (i = 0; i < pBss->RatesLen; i++)
		{
			rate = pBss->Rates[i] & 0x7f; // Mask out basic rate set bit		
			if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
			{
				//
				// basic rate means Ndis802_11DS
				//
				NetWorkType = Ndis802_11DS;
				continue;
			}
			else
			{
				//
				// Otherwise (even rate > 108) means Ndis802_11OFDM24
				//
				NetWorkType = Ndis802_11OFDM24;
				break;
			}	
		}
	}
	else
	{
		NetWorkType = Ndis802_11OFDM5;
	}

	return NetWorkType;
}

/*
	========================================================================
	Routine Description:
		Sanity check pairwise key on pAdapter->PortCfg.AuthMode < Ndis802_11AuthModeWPA
		
	Arguments:
		pAdapter - Pointer to our adapter
		pBuf 	 - Pointer to NDIS_802_11_KEY structure

	Return Value:
		NDIS_STATUS_SUCCESS
		NDIS_STATUS_INVALID_DATA
        
	IRQL = DISPATCH_LEVEL

	Note:
		For OID_802_11_ADD_KEY setting, on old wep stuff also need to verify
		the structure of NIDS_802_11_KEY
	========================================================================
*/
NDIS_STATUS	RTMPWPAWepKeySanity(
	IN	PRT2570ADAPTER	pAdapter,
	IN	PVOID			pBuf)
{
	PNDIS_802_11_KEY	pKey;
	ULONG				KeyIdx;
	NDIS_STATUS			Status = NDIS_STATUS_SUCCESS;
	BOOLEAN 			bTxKey; 		// Set the key as transmit key
	BOOLEAN 			bPairwise;		// Indicate the key is pairwise key

	pKey = (PNDIS_802_11_KEY) pBuf;
	KeyIdx = pKey->KeyIndex & 0x0fffffff;
	// Bit 31 of Add-key, Tx Key
	bTxKey		   = (pKey->KeyIndex & 0x80000000) ? TRUE : FALSE;
	// Bit 30 of Add-key PairwiseKey
	bPairwise	   = (pKey->KeyIndex & 0x40000000) ? TRUE : FALSE;

	// 1. Check Group / Pairwise Key
	if (bPairwise)	// Pairwise Key
	{
		// 1. Check KeyIdx 
		// it is a shared key
		if (KeyIdx > 4)
			return (-EINVAL);

		// 2. Check bTx, it must be true, otherwise, return NDIS_STATUS_INVALID_DATA
		if (bTxKey == FALSE)
			return (-EINVAL);

		// 3. If BSSID is not all 0xff, return NDIS_STATUS_INVALID_DATA
		if (NdisEqualMemory(pKey->BSSID, BCAST, 6))
			return (-EINVAL);

		// check key length
		if ((pKey->KeyLength != 5) && (pKey->KeyLength != 13))
			return (-EINVAL);
	}
	else
	{
		// Group Key
		// 1. Check BSSID, if not current BSSID or Bcast, return NDIS_STATUS_INVALID_DATA
		if ((!NdisEqualMemory(&pKey->BSSID, &BCAST, 6)) &&
			(!NdisEqualMemory(&pKey->BSSID, &pAdapter->PortCfg.Bssid, 6)))
			return (-EINVAL);
		// 2. Check Key index for supported Group Key
		if (KeyIdx > 4)
			return (-EINVAL);
	}

	pAdapter->PortCfg.SharedKey[KeyIdx].KeyLen = (UCHAR) pKey->KeyLength;
	NdisMoveMemory(pAdapter->PortCfg.SharedKey[KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength);
	if (pKey->KeyIndex & 0x80000000)
	{
		// Default key for tx (shared key)
		pAdapter->PortCfg.DefaultKeyId = (UCHAR) KeyIdx;
	}	

	return (Status);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?