Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/common/mesh_sanity.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

1418 lines
40 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
mesh_link_mng.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Fonchi 2007-07-23 For mesh (802.11s) support.
*/
#ifdef MESH_SUPPORT
#include "rt_config.h"
#include "mesh_def.h"
#include "mesh_sanity.h"
BOOLEAN MeshPeerBeaconAndProbeSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *Msg,
IN ULONG MsgLen,
OUT PUCHAR pHostName,
OUT PUCHAR pHostNameLen,
OUT PUCHAR pMeshId,
OUT PUCHAR pMeshIdLen,
OUT PMESH_CONFIGURAION_IE pMeshConfiguration)
{
CHAR *Ptr;
PFRAME_802_11 pFrame;
PEID_STRUCT pEid;
UCHAR SubType;
ULONG Length = 0;
pFrame = (PFRAME_802_11)Msg;
/* get subtype from header */
SubType = (UCHAR)pFrame->Hdr.FC.SubType;
/*hex_dump("Beacon", Msg, MsgLen); */
Ptr = (PCHAR)pFrame->Octet;
Length += LENGTH_802_11;
/* skip timestamp from payload and advance the pointer */
Ptr += TIMESTAMP_LEN;
Length += TIMESTAMP_LEN;
/* skip beacon interval from payload and advance the pointer */
Ptr += 2;
Length += 2;
/* skip capability info from payload and advance the pointer */
Ptr += 2;
Length += 2;
pEid = (PEID_STRUCT) Ptr;
/* get variable fields from payload and advance the pointer */
while ((Length + 2 + pEid->Len) <= MsgLen)
{
switch(pEid->Eid)
{
case IE_VENDOR_SPECIFIC:
if (NdisEqualMemory(pEid->Octet, MeshOUI, 3))
{
PUCHAR ptr = (PUCHAR)(pEid->Octet + 3);
*pHostNameLen = pEid->Len -3;
NdisMoveMemory(pHostName, ptr, *pHostNameLen);
}
break;
case IE_MESH_ID:
NdisMoveMemory(pMeshId, pEid->Octet, pEid->Len);
*pMeshIdLen = pEid->Len;
break;
case IE_MESH_CONFIGURATION:
{
PUCHAR ptr;
NdisMoveMemory(&pMeshConfiguration->Version, pEid->Octet, 1);
if (RTMPEqualMemory(pEid->Octet + 1, MeshOUI, 3))
NdisMoveMemory(&pMeshConfiguration->PathSelProtocolId, pEid->Octet + 4, 1);
if (RTMPEqualMemory(pEid->Octet + 5, MeshOUI, 3))
NdisMoveMemory(&pMeshConfiguration->PathSelMetricId, pEid->Octet + 8, 1);
ptr = (PUCHAR)&pEid->Octet[0];
NdisMoveMemory(&pMeshConfiguration->CPI, ptr + 13, 4);
pMeshConfiguration->CPI = le2cpu32(*(UINT32 *)(&pMeshConfiguration->CPI));
NdisMoveMemory(&pMeshConfiguration->MeshCapability.word, ptr + 17, 2);
pMeshConfiguration->MeshCapability.word = le2cpu16(*(UINT16 *)(&pMeshConfiguration->MeshCapability.word));
}
break;
default:
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("MeshPeerBeaconAndProbeSanity - unrecognized EID = %d\n", pEid->Eid));
#endif /* RELEASE_EXCLUDE */
break;
}
Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */
pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
}
return TRUE;
}
BOOLEAN MeshLinkMngOpenSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT16 *pCapabilityInfo,
OUT UCHAR SupRate[],
OUT PUCHAR pSupRateLen,
OUT PUCHAR pMeshIdLen,
OUT PUCHAR pMeshId,
OUT PUCHAR pMeshSelPathId,
OUT PUCHAR pMeshSelMetricId,
OUT UINT32 *pCPI,
OUT PMESH_CAPABILITY pMeshCapabilty,
OUT UINT16 *pPeerLinkId,
OUT PMESH_SECURITY_CAPABILITY_IE pMscIe,
OUT PUCHAR pMsaIe,
OUT PUCHAR pMsaIeLen,
OUT PUCHAR pRsnIe,
OUT PUCHAR pRsnIeLen,
OUT BOOLEAN *pbWmmCapable,
OUT HT_CAPABILITY_IE *pHtCapability,
OUT UCHAR *pHtCapabilityLen)
{
PEID_STRUCT eid_ptr;
UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01};
UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
*pMsaIeLen = 0;
*pRsnIeLen = 0;
NdisMoveMemory(pCapabilityInfo, pMsg, 2);
pMsg += 2;
MsgLen -= 2;
*pbWmmCapable = FALSE;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_SUPP_RATES:
if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
{
NdisMoveMemory(SupRate, eid_ptr->Octet, eid_ptr->Len);
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n", __FUNCTION__, eid_ptr->Len, SupRate[0]));
DBGPRINT(RT_DEBUG_INFO, ("SupRate[1]=%x %x %x %x %x %x %x\n",
SupRate[1], SupRate[2], SupRate[3], SupRate[4], SupRate[5], SupRate[6], SupRate[7]));
#endif /* RELEASE_EXCLUDE */
*pSupRateLen = eid_ptr->Len;
}
else
{
/* HT rate not ready yet. return true temporarily. */
/*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */
*pSupRateLen = 8;
SupRate[0] = 0x82;
SupRate[1] = 0x84;
SupRate[2] = 0x8b;
SupRate[3] = 0x96;
SupRate[4] = 0x12;
SupRate[5] = 0x24;
SupRate[6] = 0x48;
SupRate[7] = 0x6c;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("PeerAssocReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
#endif /* RELEASE_EXCLUDE */
/*return FALSE; */
}
break;
case IE_EXT_SUPP_RATES:
if (eid_ptr->Len + *pSupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
{
NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, eid_ptr->Len);
*pSupRateLen = (*pSupRateLen) + eid_ptr->Len;
}
else
{
NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pSupRateLen));
*pSupRateLen = MAX_LEN_OF_SUPPORTED_RATES;
}
break;
case IE_WPA:
case IE_WPA2:
if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7))
{
*pbWmmCapable = TRUE;
break;
}
if (pAd->MeshTab.wdev.AuthMode < Ndis802_11AuthModeWPA)
{
DBGPRINT(RT_DEBUG_TRACE, ("The AuthMode isn't WPA!!!%d \n",pAd->MeshTab.wdev.AuthMode));
break;
}
/* If this IE did not begins with "0x00:0x50:0xf2:0x01" or "0x00:0x0f:0xac", it would be proprietary. So we ignore it. */
if (!NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI))
&& !NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI)))
{
DBGPRINT(RT_DEBUG_TRACE, ("Not RSN IE, maybe proprietary IE!!!\n"));
break;
}
if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) && */(eid_ptr->Len > MIN_LEN_OF_RSNIE))
{
NdisMoveMemory(pRsnIe, eid_ptr, eid_ptr->Len + 2);
*pRsnIeLen = eid_ptr->Len + 2;
}
else
{
*pRsnIeLen = 0;
DBGPRINT(RT_DEBUG_TRACE, ("The received the length(%d) of RSN_IE is invalid\n",eid_ptr->Len));
break;
}
DBGPRINT(RT_DEBUG_TRACE, ("Link Msg - RSNIE(%d), and its len(%d)!!!\n", eid_ptr->Eid, *pRsnIeLen));
break;
case IE_MESH_ID:
if (eid_ptr->Len < MAX_MESH_ID_LEN)
NdisMoveMemory(pMeshId, eid_ptr->Octet, eid_ptr->Len);
break;
case IE_MESH_CONFIGURATION:
if (NdisEqualMemory(eid_ptr->Octet + 1, MeshOUI, 3))
NdisMoveMemory(pMeshSelPathId, eid_ptr->Octet + 4, 1);
if (NdisEqualMemory(eid_ptr->Octet + 5, MeshOUI, 3))
NdisMoveMemory(pMeshSelMetricId, eid_ptr->Octet + 8, 1);
NdisMoveMemory(pCPI, eid_ptr->Octet + 13, 4);
*pCPI = le2cpu32(*(UINT32 *)pCPI);
NdisMoveMemory(&pMeshCapabilty->word, eid_ptr->Octet + 17, 2);
pMeshCapabilty->word = le2cpu16(*(UINT16 *)(&pMeshCapabilty->word));
break;
case IE_MESH_PEER_LINK_MANAGEMENT:
if ((*eid_ptr->Octet == SUBTYPE_PEER_LINK_OPEN) /* subtype 1 means Peer-Link-Open frame. */
&& (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_OPEN])) /* Length of Peer-Link-open must be 3. */
{
NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 1, 2);
*pPeerLinkId = le2cpu16(*pPeerLinkId);
}
break;
case IE_MESH_MSCIE:
if (eid_ptr->Len == 7) /* its Length MUST be 7 */
{
NdisMoveMemory(pMscIe, eid_ptr->Octet, eid_ptr->Len);
}
break;
case IE_MESH_MSAIE:
if (eid_ptr->Len >= sizeof(MSA_HANDSHAKE_IE))
{
NdisMoveMemory(pMsaIe, eid_ptr->Octet, eid_ptr->Len);
*pMsaIeLen = eid_ptr->Len;
}
break;
case IE_HT_CAP:
if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
{
NdisMoveMemory(pHtCapability, eid_ptr->Octet, SIZE_HT_CAP_IE);
*(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
*(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
*pHtCapabilityLen = SIZE_HT_CAP_IE;
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_HT_CAP\n"));
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshLinkMngCfnSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT16 *pCapabilityInfo,
OUT UINT16 *pStatusCode,
OUT UINT16 *pAid,
OUT UCHAR SupRate[],
OUT PUCHAR pSupRateLen,
OUT PUCHAR pMeshIdLen,
OUT PUCHAR pMeshId,
OUT PUCHAR pMeshSelPathId,
OUT PUCHAR pMeshSelMetricId,
OUT UINT32 *pCPI,
OUT PMESH_CAPABILITY pMeshCapabilty,
OUT UINT16 *pLocalLinkId,
OUT UINT16 *pPeerLinkId,
OUT PMESH_SECURITY_CAPABILITY_IE pMscIe,
OUT PUCHAR pMsaIe,
OUT PUCHAR pMsaIeLen,
OUT PUCHAR pRsnIe,
OUT PUCHAR pRsnIeLen,
OUT HT_CAPABILITY_IE *pHtCapability,
OUT UCHAR *pHtCapabilityLen)
{
PEID_STRUCT eid_ptr;
UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01};
UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
*pMsaIeLen = 0;
*pRsnIeLen = 0;
NdisMoveMemory(pCapabilityInfo, pMsg, 2);
pMsg += 2;
MsgLen -= 2;
NdisMoveMemory(pStatusCode, pMsg, 2);
pMsg += 2;
MsgLen -= 2;
NdisMoveMemory(pAid, pMsg, 2);
pMsg += 2;
MsgLen -= 2;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_SUPP_RATES:
if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && (eid_ptr->Len > 0))
{
NdisMoveMemory(SupRate, eid_ptr->Octet, eid_ptr->Len);
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s - IE_SUPP_RATES., Len=%d. Rates[0]=%x\n", __FUNCTION__, eid_ptr->Len, SupRate[0]));
DBGPRINT(RT_DEBUG_INFO, ("SupRate[1]=%x %x %x %x %x %x %x\n",
SupRate[1], SupRate[2], SupRate[3], SupRate[4], SupRate[5], SupRate[6], SupRate[7]));
#endif /* RELEASE_EXCLUDE */
*pSupRateLen = eid_ptr->Len;
}
else
{
/* HT rate not ready yet. return true temporarily. */
/*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */
*pSupRateLen = 8;
SupRate[0] = 0x82;
SupRate[1] = 0x84;
SupRate[2] = 0x8b;
SupRate[3] = 0x96;
SupRate[4] = 0x12;
SupRate[5] = 0x24;
SupRate[6] = 0x48;
SupRate[7] = 0x6c;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("PeerAssocReqSanity - wrong IE_SUPP_RATES., Len=%d\n",eid_ptr->Len));
#endif /* RELEASE_EXCLUDE */
/*return FALSE; */
}
break;
case IE_EXT_SUPP_RATES:
if (eid_ptr->Len + *pSupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
{
NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, eid_ptr->Len);
*pSupRateLen = (*pSupRateLen) + eid_ptr->Len;
}
else
{
NdisMoveMemory(&SupRate[*pSupRateLen], eid_ptr->Octet, MAX_LEN_OF_SUPPORTED_RATES - (*pSupRateLen));
*pSupRateLen = MAX_LEN_OF_SUPPORTED_RATES;
}
break;
case IE_WPA:
case IE_WPA2:
if (pAd->MeshTab.wdev.AuthMode < Ndis802_11AuthModeWPA)
break;
/* If this IE did not begins with "0x00:0x50:0xf2:0x01" or "0x00:0x0f:0xac", it would be proprietary. So we ignore it. */
if (!NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI))
&& !NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI)))
{
DBGPRINT(RT_DEBUG_TRACE, ("Not RSN IE, maybe proprietary IE!!!\n"));
break;
}
if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) && */(eid_ptr->Len > MIN_LEN_OF_RSNIE))
{
NdisMoveMemory(pRsnIe, eid_ptr, eid_ptr->Len + 2);
*pRsnIeLen = eid_ptr->Len + 2;
}
else
{
*pRsnIeLen = 0;
DBGPRINT(RT_DEBUG_TRACE, ("The received the length(%d) of RSN_IE is invalid\n",eid_ptr->Len));
break;
}
break;
case IE_MESH_ID:
if (eid_ptr->Len < MAX_MESH_ID_LEN)
NdisMoveMemory(pMeshId, eid_ptr->Octet, eid_ptr->Len);
break;
case IE_MESH_CONFIGURATION:
if (NdisEqualMemory(eid_ptr->Octet + 1, MeshOUI, 3))
{
*pMeshSelPathId = eid_ptr->Octet[4];
}
if (NdisEqualMemory(eid_ptr->Octet + 5, MeshOUI, 3))
{
*pMeshSelMetricId = eid_ptr->Octet[8];
}
NdisMoveMemory(pCPI, eid_ptr->Octet + 13, 4);
*pCPI = le2cpu32(*pCPI);
NdisMoveMemory(&pMeshCapabilty->word, eid_ptr->Octet + 17, 2);
pMeshCapabilty->word = le2cpu16(pMeshCapabilty->word);
break;
case IE_MESH_PEER_LINK_MANAGEMENT:
{
if ((eid_ptr->Octet[0] == SUBTYPE_PEER_LINK_CONFIRM) /* subtype 1 means Peer-Link-Confirm frame. */
&& (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_CONFIRM])) /* Length of Peer-Link-close must be 3. */
{
NdisMoveMemory(pLocalLinkId, eid_ptr->Octet + 1, 2);
*pLocalLinkId = le2cpu16(*(UINT16 *)(pLocalLinkId));
NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 3, 2);
*pPeerLinkId = le2cpu16(*(UINT16 *)(pPeerLinkId));
}
}
break;
case IE_MESH_MSCIE:
if (eid_ptr->Len == 7) /* its Length MUST be 7 */
{
NdisMoveMemory(pMscIe,eid_ptr->Octet, eid_ptr->Len);
}
break;
case IE_MESH_MSAIE:
if (eid_ptr->Len >= sizeof(MSA_HANDSHAKE_IE))
{
NdisMoveMemory(pMsaIe,eid_ptr->Octet, eid_ptr->Len);
*pMsaIeLen = eid_ptr->Len;
}
break;
case IE_HT_CAP:
if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
{
NdisMoveMemory(pHtCapability, eid_ptr->Octet, SIZE_HT_CAP_IE);
*(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
*(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
*pHtCapabilityLen = SIZE_HT_CAP_IE;
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_HT_CAP\n"));
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshLinkMngClsSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT16 *pLocalLinkId,
OUT UINT16 *pPeerLinkId,
OUT UINT16 *pReasonCode)
{
PEID_STRUCT eid_ptr;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_PEER_LINK_MANAGEMENT:
{
if ((eid_ptr->Octet[0] == SUBTYPE_PEER_LINK_CLOSE) /* subtype 1 means Peer-Link-Close frame. */
&& (eid_ptr->Len == LenPeerLinkMngIE[SUBTYPE_PEER_LINK_CLOSE])) /* Length of Peer-Link-close must be 7. */
{
NdisMoveMemory(pLocalLinkId, eid_ptr->Octet + 1, 2);
*pLocalLinkId = le2cpu16(*(UINT16 *)(pLocalLinkId));
NdisMoveMemory(pPeerLinkId, eid_ptr->Octet + 3, 2);
*pPeerLinkId = le2cpu16(*(UINT16 *)(pPeerLinkId));
NdisMoveMemory(pReasonCode, eid_ptr->Octet + 5, 2);
*pReasonCode = le2cpu16(*(UINT16 *)(pReasonCode));
}
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshPathSelMultipathNoticeSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT8 *pFlag,
OUT PUCHAR pMeshSA)
{
PEID_STRUCT eid_ptr;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_MULITI_PATH_NOTICE_IE:
{
if (eid_ptr->Len == 7) /* Length must be 7. */
{
NdisMoveMemory(pFlag, eid_ptr->Octet, 1);
NdisMoveMemory(pMeshSA, eid_ptr->Octet + 1, MAC_ADDR_LEN);
}
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshChannelSwitchAnnouncementSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT8 *pChSwMode,
OUT UINT8 *pNewCh,
OUT UINT32 *pNewCPI,
OUT UINT8 *pChSwCnt,
OUT PUCHAR pMeshSA)
{
PEID_STRUCT eid_ptr;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_CHANNEL_SWITCH_ANNOUNCEMENT:
{
if (eid_ptr->Len == 13) /* Length must be 7. */
{
NdisMoveMemory(pChSwMode, eid_ptr->Octet, 1);
NdisMoveMemory(pNewCh, eid_ptr->Octet + 1, 1);
NdisMoveMemory(pNewCPI, eid_ptr->Octet + 2, 4);
*pNewCPI = le2cpu32(*pNewCPI);
NdisMoveMemory(pChSwCnt, eid_ptr->Octet + 6, 1);
NdisMoveMemory(pMeshSA, eid_ptr->Octet + 7, MAC_ADDR_LEN);
}
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
/*
==========================================================================
Description:
Check sanity RSN IE and get PMKID offset.
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN MeshValidateRSNIE(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pRsnIe,
IN USHORT peerRsnIeLen,
OUT UCHAR *PureRsnLen,
OUT UCHAR *PmkIdLen)
{
PEID_STRUCT eid_ptr;
PUCHAR pBufTmp;
USHORT Count;
UCHAR offset = 0;
BOOLEAN isValid = FALSE;
BOOLEAN RsnEid = IE_WPA;
/* Check if both MPs are RSNIE */
if (pAd->MeshTab.wdev.AuthMode < Ndis802_11AuthModeWPA)
{
if (peerRsnIeLen == 0)
{
/* Don't check it */
return TRUE;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the local MP has no RSNIE \n"));
return FALSE;
}
}
else
{
if (peerRsnIeLen == 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the peer MP has no RSNIE \n"));
return FALSE;
}
}
/* hex_dump("Peer RSNIE", pRsnIe, peerRsnIeLen); */
eid_ptr = (PEID_STRUCT)pRsnIe;
if (pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK ||
pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA2
#ifdef WPA3_SUPPORT
|| (pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA3SAE)
#endif
)
RsnEid = IE_WPA2;
if (eid_ptr->Eid != IE_WPA && eid_ptr->Eid != IE_WPA2)
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE has unknown element ID(%d) \n", eid_ptr->Eid));
return FALSE;
}
if (eid_ptr->Len < sizeof(RSNIE2))
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, its length is too short(%d)\n", eid_ptr->Len));
return FALSE;
}
*PureRsnLen = 0;
*PmkIdLen = 0;
/* Store STA RSN_IE capability */
pBufTmp = (PUCHAR)&eid_ptr->Octet[0];
#ifdef RELEASE_EXCLUDE
/* the offset of group cipher */
/* If WPA2, skip version(2-bytes) */
/* If WPA, skip OUI(4-bytes) and version(2-bytes) */
#endif /* RELEASE_EXCLUDE */
offset = (eid_ptr->Eid == IE_WPA2) ? 2 : 6;
/* Check group cipher */
if (MeshCheckGroupCipher(pAd, pBufTmp + offset, RsnEid))
{
/* skip group cipher, then point to pairwise-cipher-count */
offset += 4;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the group cipher isn't supported\n"));
return FALSE;
}
/* Store pairwise-cipher-count */
NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
if (Count > 0)
{
/* skip pairwise-cipher-count, then point to pairwise-cipher-suite-list */
offset += sizeof(USHORT);
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the count of piarwise-cipher is invalid(%d)\n", Count));
return FALSE;
}
/* clear this flag */
isValid = FALSE;
while (Count > 0)
{
if ((isValid == FALSE) && (MeshCheckPairwiseCipher(pAd, pBufTmp + offset, RsnEid)))
{
isValid = TRUE;
}
offset += 4;
Count--;
}
if (!isValid)
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the pairwise cipher isn't supported\n"));
return FALSE;
}
/* Store AKM-suite-count */
NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
if (Count > 0)
{
/* skip AKM-suite-count, then pointer to AKM-suite-list */
offset += sizeof(USHORT);
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the count of AKM-suite is invalid(%d)\n", Count));
return FALSE;
}
/* clear this flag */
isValid = FALSE;
while (Count > 0)
{
if ((isValid == FALSE) && (MeshCheckAKMSuite(pAd, pBufTmp + offset, RsnEid)))
{
isValid = TRUE;
}
offset += 4;
Count--;
}
if (!isValid)
{
DBGPRINT(RT_DEBUG_ERROR, ("MeshValidateRSNIE, the AKM suite isn't supported\n"));
return FALSE;
}
DBGPRINT(RT_DEBUG_TRACE, ("MeshValidateRSNIE is completed \n"));
/* Check if the remaining length is larger than the size of RSN capability(2-bytes). */
if (eid_ptr->Len - offset >= 2)
{
/* skip RSN capability(2-bytes) */
offset += sizeof(USHORT);
}
*PureRsnLen = offset; /* the length is the RSNIE except elementID, length and PMKID */
#ifdef RELEASE_EXCLUDE
/* decide PMKID length */
/* If PMKID exists, the remaining length shall be */
/* 18 = PMKID_count(2-bytes) + one PMKID(16-bytes) or */
/* 34 = PMKID_count(2-bytes) + two PMKIDs(32-bytes) */
#endif /* RELEASE_EXCLUDE */
if (eid_ptr->Len - offset >= 2)
{
NdisMoveMemory(&Count, pBufTmp + offset, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
offset += sizeof(USHORT);
if (Count == 2 && (eid_ptr->Len - offset == (2*LEN_PMKID)))
*PmkIdLen = 2*LEN_PMKID;
else if (Count == 1 && (eid_ptr->Len - offset == LEN_PMKID))
*PmkIdLen = LEN_PMKID;
else
*PmkIdLen = 0;
if (*PmkIdLen > 0)
{
DBGPRINT(RT_DEBUG_TRACE, ("MeshValidateRSNIE, %d PMKID exist and its len is %d \n", Count, (eid_ptr->Len - offset)));
}
}
return TRUE;
}
/*
==========================================================================
Description:
Check sanity of group cipher selector
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN MeshCheckGroupCipher(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData,
IN UCHAR Eid)
{
/* WPA and WPA2 format not the same in RSN_IE */
if (Eid == IE_WPA2)
{
/* skip version(2-bytes) */
if (NdisEqualMemory(pData, &pAd->MeshTab.RSN_IE[2], 4))
return TRUE;
}
else if (Eid == IE_WPA)
{
/* skip OUI(4-bytes) and version(2-bytes) */
if (NdisEqualMemory(pData, &pAd->MeshTab.RSN_IE[6], 4))
return TRUE;
}
return FALSE;
}
/*
==========================================================================
Description:
Check sanity of unicast cipher selector.
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN MeshCheckPairwiseCipher(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData,
IN UCHAR Eid)
{
PUCHAR pTmp;
USHORT Count;
pTmp = &pAd->MeshTab.RSN_IE[0];
if(Eid == IE_WPA2)
/* skip Version(2),Multicast cipter(4) 2+4==6 */
pTmp += 6;
else
/*skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */
pTmp += 10;/*point to number of unicast */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
pTmp += sizeof(USHORT);/*pointer to unicast cipher */
while (Count > 0)
{
if(RTMPEqualMemory(pData, pTmp, 4))
return TRUE;
else
{
pTmp += 4;
Count--;
}
}
return FALSE;/* do not match the unicast cipher */
}
/*
==========================================================================
Description:
Check invalidity of authentication method selection.
Return:
TRUE if match
FALSE otherwise
==========================================================================
*/
BOOLEAN MeshCheckAKMSuite(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData,
IN UCHAR Eid)
{
PUCHAR pTmp;
USHORT Count;
pTmp = &pAd->MeshTab.RSN_IE[0];
if(Eid == IE_WPA2)
/* skip Version(2),Multicast cipter(4) 2+4==6 */
pTmp +=6;
else
/*skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */
pTmp += 10;/*point to number of unicast */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
pTmp += sizeof(USHORT);/*pointer to unicast cipher */
/* Skip all unicast cipher suite */
while (Count > 0)
{
/* Skip OUI */
pTmp += 4;
Count--;
}
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
#ifdef RT_BIG_ENDIAN
Count = SWAP16(Count);
#endif
pTmp += sizeof(USHORT);/*pointer to AKM cipher */
while (Count > 0)
{
if(RTMPEqualMemory(pData, pTmp, 4))
return TRUE;
else
{
pTmp += 4;
Count--;
}
}
return FALSE;/* do not match the AKM */
}
UINT16 MeshValidateOpenAndCfnPeerLinkMsg(
IN PRTMP_ADAPTER pAd,
IN UCHAR state,
IN PMESH_LINK_ENTRY pMeshLinkEntry,
IN PUCHAR pRcvdMscIe,
IN PUCHAR pRcvdMsaIe,
IN UCHAR RcvdMsaIeLen,
IN PUCHAR pRcvdRsnIe,
IN UCHAR RcvdRsnIeLen,
IN UCHAR pure_rsn_len,
IN UCHAR pmkid_len)
{
#ifdef RELEASE_EXCLUDE
/* MSCIE is identical to the MSCIE included in the peer link */
/* open (or confirm) frame received from the candidate peer MP. */
#endif /* RELEASE_EXCLUDE */
if (!RTMPEqualMemory(pRcvdMscIe, (PUCHAR)&pMeshLinkEntry->RcvdMscIe, sizeof(MESH_SECURITY_CAPABILITY_IE)))
{
DBGPRINT(RT_DEBUG_ERROR, ("The MSCIE is different between peer link open and confirm frame \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
#ifdef RELEASE_EXCLUDE
/* The Handshake Control field of MSAIE is identical to that */
/* included in the received peer link open (or confirm) frame. */
#endif /* RELEASE_EXCLUDE */
if (!RTMPEqualMemory(pRcvdMsaIe, pMeshLinkEntry->RcvdMsaIe, sizeof(MESH_HANDSHAKE_CONTROL)))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Handshake Control field of MSAIE is different between peer link open and confirm frame \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
if (pAd->MeshTab.wdev.AuthMode >= Ndis802_11AuthModeWPA)
{
#ifdef RELEASE_EXCLUDE
/* RSNIE is identical to the RSNIE included in the peer link */
/* confirm frame received from the candidate peer MP, except the PMKID list. */
#endif /* RELEASE_EXCLUDE */
if (pure_rsn_len != pMeshLinkEntry->RcvdRSNIE_Len ||
!RTMPEqualMemory(pRcvdRsnIe + 2, pMeshLinkEntry->RcvdRSNIE, pure_rsn_len))
{
DBGPRINT(RT_DEBUG_ERROR, ("The RSNIE is different between candidate MP's link open and confirm frame \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
#ifdef RELEASE_EXCLUDE
/* the local MP shall verify that the PMK-MAName value contained in the received */
/* peer link confirm frame identifies the key chosen by the key selection procedure, */
/* or is empty if Initial MSA Authentication shall occur. */
#endif /* RELEASE_EXCLUDE */
if (pmkid_len > 0 && pMeshLinkEntry->RcvdPMKID_Len > 0)
{
UCHAR pmkid_offset = RcvdRsnIeLen - pmkid_len;
if (pmkid_len != pMeshLinkEntry->RcvdPMKID_Len ||
!NdisEqualMemory(pRcvdRsnIe + pmkid_offset, pMeshLinkEntry->RcvdPMKID, pmkid_len))
{
DBGPRINT(RT_DEBUG_ERROR, ("The result of Key Selection is different between candidate MP's link open and confirm frame\n"));
hex_dump("Receive PMKID ", pRcvdRsnIe + pmkid_offset, pmkid_len);
hex_dump("Desired PMKID ", pMeshLinkEntry->RcvdPMKID, pMeshLinkEntry->RcvdPMKID_Len);
return MESH_SECURITY_FAILED_VERIFICATION;
}
}
else if (pmkid_len == 0 && pMeshLinkEntry->RcvdPMKID_Len == 0)
{
;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("The PMKID is different between candidate MP's link open and confirm frame\n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
#ifdef RELEASE_EXCLUDE
/* If the candidate peer MP is the selector MP, the values in the Selected AKM Suite and */
/* Selected Pairwise Cipher Suite fields are identical to the values received in peer link frame. */
#endif /* RELEASE_EXCLUDE */
if (!pMeshLinkEntry->bValidLocalMpAsSelector)
{
UCHAR akm_offset = 0, cipher_offset = 0;
#ifdef RELEASE_EXCLUDE
/* the Selected AKM offset - */
/* skip the Handshake Control field(1) + MA_ID(6) */
#endif /* RELEASE_EXCLUDE */
akm_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN;
#ifdef RELEASE_EXCLUDE
/* the Selected Pairwise-cipher offset - */
/* skip the Handshake Control field(1) + MA_ID(6) + Selected_AKM(4) */
#endif /* RELEASE_EXCLUDE */
cipher_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN + LEN_OUI_SUITE;
if (!RTMPEqualMemory(pRcvdMsaIe + akm_offset, &pMeshLinkEntry->RcvdMsaIe[akm_offset], LEN_OUI_SUITE))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM Suite of MSAIE is different between peer link open and confirm frame \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
if (!RTMPEqualMemory(pRcvdMsaIe + cipher_offset, &pMeshLinkEntry->RcvdMsaIe[cipher_offset], LEN_OUI_SUITE))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher Suite of MSAIE is different between peer link open and confirm frame \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
}
}
#ifdef RELEASE_EXCLUDE
/* the local MP shall verify that the MA-ID value received in the peer link confirm */
/* frame matches the result of the 802.1X role selection procedure. */
#endif /* RELEASE_EXCLUDE */
{
UCHAR LocalMaAddr[MAC_ADDR_LEN];
UCHAR PeerMaAddr[MAC_ADDR_LEN];
if (pMeshLinkEntry->bValidLocalMpAsAuthenticator)
NdisMoveMemory(LocalMaAddr, pAd->MeshTab.wdev.if_addr, MAC_ADDR_LEN);
else
NdisMoveMemory(LocalMaAddr, pMeshLinkEntry->PeerMacAddr, MAC_ADDR_LEN);
if (state == SUBTYPE_PEER_LINK_CONFIRM)
NdisMoveMemory(PeerMaAddr, pRcvdMsaIe + 1, MAC_ADDR_LEN);
else
NdisMoveMemory(PeerMaAddr, &pMeshLinkEntry->RcvdMsaIe[1], MAC_ADDR_LEN);
if (!NdisEqualMemory(LocalMaAddr, PeerMaAddr, MAC_ADDR_LEN))
{
DBGPRINT(RT_DEBUG_ERROR, ("The MA-ID of MSAIE doesn't match \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
}
return MLME_SUCCESS;
}
UINT16 MeshCheckPeerMsaIeCipherValidity(
IN PRTMP_ADAPTER pAd,
IN UCHAR state,
IN PMESH_LINK_ENTRY pMeshLinkEntry,
IN PUCHAR pRcvdMsaIe)
{
if (pAd->MeshTab.wdev.AuthMode >= Ndis802_11AuthModeWPA)
{
UCHAR akm_offset = 0, cipher_offset = 0;
#ifdef RELEASE_EXCLUDE
/* the Selected AKM offset - */
/* skip the Handshake Control field(1) + MA_ID(6) */
#endif /* RELEASE_EXCLUDE */
akm_offset = sizeof(MESH_HANDSHAKE_CONTROL) + MAC_ADDR_LEN;
#ifdef RELEASE_EXCLUDE
/* the Selected Pairwise-cipher offset - */
/* skip the Handshake Control field(1) + MA_ID(6) + Selected_AKM(4) */
#endif /* RELEASE_EXCLUDE */
cipher_offset = akm_offset + LEN_OUI_SUITE;
#ifdef RELEASE_EXCLUDE
/* Verify that the AKM suite and pairwise cipher suite selected */
/* in the MSAIE are among those supported by the local MP if */
/* 1. the local MP is not the Selector MP and received peer link open frame */
/* 2. received peer link confirm frame */
#endif /* RELEASE_EXCLUDE */
if (((state == SUBTYPE_PEER_LINK_OPEN) && (!pMeshLinkEntry->bValidLocalMpAsSelector)) ||
(state == SUBTYPE_PEER_LINK_CONFIRM))
{
UCHAR RsnEid = IE_WPA;
if (pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA2PSK ||
pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA2
#ifdef WPA3_SUPPORT
|| (pAd->MeshTab.wdev.AuthMode == Ndis802_11AuthModeWPA3SAE)
#endif
)
RsnEid = IE_WPA2;
if (!MeshCheckPairwiseCipher(pAd, &pRcvdMsaIe[cipher_offset], RsnEid))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher isn't supported by local MP\n"));
return MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS;
}
if (!MeshCheckAKMSuite(pAd, &pRcvdMsaIe[akm_offset], RsnEid))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM isn't supported by local MP \n"));
return MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS;
}
/* verify peer AKM and pairwise-cipher OK, update them to local MSAIE */
if (state == SUBTYPE_PEER_LINK_OPEN)
NdisMoveMemory(&pMeshLinkEntry->LocalMsaIe[akm_offset], &pRcvdMsaIe[akm_offset], 2*LEN_OUI_SUITE);
}
#ifdef RELEASE_EXCLUDE
/* Upon reception of a peer link confirm frame, */
/* If the local MP is the selector MP, it shall verify that the selected AKM suite and pairwise cipher */
/* suite values match its selections that have been sent to the candidate peer MP in the peer link open */
/* frame. */
#endif /* RELEASE_EXCLUDE */
if ((state == SUBTYPE_PEER_LINK_CONFIRM) && (pMeshLinkEntry->bValidLocalMpAsSelector))
{
if (!NdisEqualMemory(&pRcvdMsaIe[akm_offset], &pMeshLinkEntry->LocalMsaIe[akm_offset], LEN_OUI_SUITE))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected AKM in P.L. confirm frame isn't supported by local Selector MP \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
if (!NdisEqualMemory(&pRcvdMsaIe[cipher_offset], &pMeshLinkEntry->LocalMsaIe[cipher_offset], LEN_OUI_SUITE))
{
DBGPRINT(RT_DEBUG_ERROR, ("The Selected Pairwise Cipher in P.L. confirm frame isn't supported by local Selector MP \n"));
return MESH_SECURITY_FAILED_VERIFICATION;
}
}
}
return MLME_SUCCESS;
}
BOOLEAN MeshPathRequestSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT8 *pFlag,
OUT UINT8 *pHopCount,
OUT UINT8 *pTTL,
OUT UINT32 *pID,
OUT PUCHAR pOrigMac,
OUT UINT32 *pOrigDsn,
OUT PUCHAR pProxyMac,
OUT UINT32 *pLifeTime,
OUT UINT32 *pMetric,
OUT UINT8 *pDestCount,
OUT PMESH_DEST_ENTRY pDestEntry)
{
PEID_STRUCT eid_ptr;
UINT8 VarOffset = 0;
UINT8 EntryCount = 0;
MESH_PREQ_FLAG PreqFlag;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_PREQ:
{
NdisMoveMemory(pFlag, eid_ptr->Octet, 1);
VarOffset += 1;
NdisMoveMemory(pHopCount, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
NdisMoveMemory(pTTL, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
NdisMoveMemory(pID, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pID = le2cpu32(*pID);
NdisMoveMemory(pOrigMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN);
VarOffset += MAC_ADDR_LEN;
NdisMoveMemory(pOrigDsn, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pOrigDsn = le2cpu32(*pOrigDsn);
PreqFlag = (MESH_PREQ_FLAG)(*pFlag);
if (PreqFlag.field.AE == 1)
{
NdisMoveMemory(pProxyMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN);
VarOffset += MAC_ADDR_LEN;
}
NdisMoveMemory(pLifeTime, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pLifeTime = le2cpu32(*pLifeTime);
NdisMoveMemory(pMetric, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pMetric = le2cpu32(*pMetric);
NdisMoveMemory(pDestCount, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
EntryCount = (*pDestCount);
if (EntryCount >= 1)
NdisMoveMemory(pDestEntry, eid_ptr->Octet + VarOffset, 11*EntryCount);
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshPathResponseSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT8 *pFlag,
OUT UINT8 *pHopCount,
OUT UINT8 *pTTL,
OUT PUCHAR pDestMac,
OUT UINT32 *pDesDsn,
OUT PUCHAR pProxyMac,
OUT UINT32 *pLifeTime,
OUT UINT32 *pMetric,
OUT PUCHAR pOrigMac,
OUT UINT32 *pOrigDsn,
OUT UINT8 *pDependMPCount,
OUT PMESH_DEPENDENT_ENTRY pDependEntry)
{
PEID_STRUCT eid_ptr;
UINT8 VarOffset = 0;
UINT8 EntryCount = 0;
MESH_PREP_FLAG PrepFlag;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_PREP:
{
NdisMoveMemory(pFlag, eid_ptr->Octet, 1);
VarOffset += 1;
NdisMoveMemory(pHopCount, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
NdisMoveMemory(pTTL, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
NdisMoveMemory(pDestMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN);
VarOffset += MAC_ADDR_LEN;
NdisMoveMemory(pDesDsn, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pDesDsn = le2cpu32(*pDesDsn);
PrepFlag = (MESH_PREP_FLAG)(*pFlag);
if (PrepFlag.field.AE == 1)
{
NdisMoveMemory(pProxyMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN);
VarOffset += MAC_ADDR_LEN;
}
NdisMoveMemory(pLifeTime, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pLifeTime = le2cpu32(*pLifeTime);
NdisMoveMemory(pMetric, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pMetric = le2cpu32(*pMetric);
NdisMoveMemory(pOrigMac, eid_ptr->Octet + VarOffset, MAC_ADDR_LEN);
VarOffset += MAC_ADDR_LEN;
NdisMoveMemory(pOrigDsn, eid_ptr->Octet + VarOffset, 4);
VarOffset += 4;
*pOrigDsn = le2cpu32(*pOrigDsn);
NdisMoveMemory(pDependMPCount, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
EntryCount = (*pDependMPCount);
if (EntryCount >= 1)
NdisMoveMemory(pDependEntry, eid_ptr->Octet + VarOffset, 10*EntryCount);
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshPathErrorSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT UINT8 *pFlag,
OUT UINT8 *pDestNum,
OUT PMESH_PERR_ENTRY pErrorEntry)
{
PEID_STRUCT eid_ptr;
UINT8 VarOffset = 0;
UINT8 EntryCount = 0;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_PREP:
{
NdisMoveMemory(pFlag, eid_ptr->Octet, 1);
VarOffset += 1;
NdisMoveMemory(pDestNum, eid_ptr->Octet + VarOffset, 1);
VarOffset += 1;
EntryCount = (*pDestNum);
if (EntryCount >= 1)
NdisMoveMemory(pErrorEntry, eid_ptr->Octet + VarOffset, 10*EntryCount);
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
BOOLEAN MeshLinkMetricReportSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT PUINT32 pLinkMetric)
{
PEID_STRUCT eid_ptr;
UINT32 LinkMetric;
eid_ptr = (PEID_STRUCT)pMsg;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pMsg + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MESH_LINK_METRIC_REPORT:
{
if (eid_ptr->Len == 4)
{
NdisMoveMemory(&LinkMetric, eid_ptr->Octet, eid_ptr->Len);
*pLinkMetric = le2cpu32(LinkMetric);
}
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return TRUE;
}
#endif /* MESH_SUPPORT */