summaryrefslogtreecommitdiff
path: root/cleopatre/devkit/mt7601udrv/ap/ap_wpa.c
diff options
context:
space:
mode:
authorFisher Cheng2013-05-24 16:54:08 +0800
committerJulien Lacour2013-10-01 12:12:48 +0200
commit8c1eb022607c0aba81d93b961abbfb47a2dcc325 (patch)
tree13b1cd55172e93b3d1e5baa7141ba259fd71b0af /cleopatre/devkit/mt7601udrv/ap/ap_wpa.c
parent9e4d9d72dcac9686f1b4720e46e3bb88f6375a1e (diff)
cleo/devkit: add MTK MT7601U drv source code, refs #4011
- Enable Wireless LAN and Wireless extension in linux26.config
Diffstat (limited to 'cleopatre/devkit/mt7601udrv/ap/ap_wpa.c')
-rw-r--r--cleopatre/devkit/mt7601udrv/ap/ap_wpa.c1614
1 files changed, 1614 insertions, 0 deletions
diff --git a/cleopatre/devkit/mt7601udrv/ap/ap_wpa.c b/cleopatre/devkit/mt7601udrv/ap/ap_wpa.c
new file mode 100644
index 0000000000..fd90e914c2
--- /dev/null
+++ b/cleopatre/devkit/mt7601udrv/ap/ap_wpa.c
@@ -0,0 +1,1614 @@
+/*
+ ***************************************************************************
+ * Ralink Tech Inc.
+ * 4F, No. 2 Technology 5th Rd.
+ * Science-based Industrial Park
+ * Hsin-chu, Taiwan, R.O.C.
+ *
+ * (c) Copyright 2002, 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:
+ wpa.c
+
+ Abstract:
+
+ Revision History:
+ Who When What
+ -------- ---------- ----------------------------------------------
+ Jan Lee 03-07-22 Initial
+ Rory Chen 04-11-29 Add WPA2PSK
+*/
+#include "rt_config.h"
+
+extern UCHAR EAPOL[];
+
+/*
+ ==========================================================================
+ Description:
+ Port Access Control Inquiry function. Return entry's Privacy and Wpastate.
+ Return:
+ pEntry
+ ==========================================================================
+*/
+MAC_TABLE_ENTRY *PACInquiry(
+ IN PRTMP_ADAPTER pAd,
+ IN ULONG Wcid)
+{
+
+ MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY*)NULL;
+
+/* *Privacy = Ndis802_11PrivFilterAcceptAll; */
+/* *WpaState = AS_NOTUSE; */
+
+ if (Wcid < MAX_LEN_OF_MAC_TABLE)
+ {
+ pEntry = &(pAd->MacTab.Content[Wcid]);
+
+ /*if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[Wcid])) */
+
+ /*ASSERT(IS_ENTRY_CLIENT(&pAd->MacTab.Content[Wcid])); */
+ /*ASSERT(pEntry->Sst == SST_ASSOC); */
+
+/* *Privacy = pEntry->PrivacyFilter; */
+/* *WpaState = pEntry->WpaState; */
+ }
+
+ return pEntry;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check sanity of multicast cipher selector in RSN IE.
+ Return:
+ TRUE if match
+ FALSE otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckMcast(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ UCHAR apidx;
+
+
+ ASSERT(pEntry);
+ ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum);
+
+ apidx = pEntry->apidx;
+
+ pEntry->AuthMode = pAd->ApCfg.MBSSID[apidx].AuthMode;
+
+ if (eid_ptr->Len >= 6)
+ {
+ /* WPA and WPA2 format not the same in RSN_IE */
+ if (eid_ptr->Eid == IE_WPA)
+ {
+ if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2)
+ pEntry->AuthMode = Ndis802_11AuthModeWPA;
+ else if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ pEntry->AuthMode = Ndis802_11AuthModeWPAPSK;
+
+ if (NdisEqualMemory(&eid_ptr->Octet[6], &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][6], 4))
+ return TRUE;
+ }
+ else if (eid_ptr->Eid == IE_WPA2)
+ {
+ UCHAR IE_Idx = 0;
+
+ /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */
+ if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+ (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ IE_Idx = 1;
+
+ if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2)
+ pEntry->AuthMode = Ndis802_11AuthModeWPA2;
+ else if (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK;
+
+ if (NdisEqualMemory(&eid_ptr->Octet[2], &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][2], 4))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check sanity of unicast cipher selector in RSN IE.
+ Return:
+ TRUE if match
+ FALSE otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckUcast(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ PUCHAR pStaTmp;
+ USHORT Count;
+ UCHAR apidx;
+
+ ASSERT(pEntry);
+ ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum);
+
+ apidx = pEntry->apidx;
+
+ pEntry->WepStatus = pAd->ApCfg.MBSSID[apidx].WepStatus;
+
+ if (eid_ptr->Len < 16)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len));
+ return FALSE;
+ }
+
+ /* Store STA RSN_IE capability */
+ pStaTmp = (PUCHAR)&eid_ptr->Octet[0];
+ if(eid_ptr->Eid == IE_WPA2)
+ {
+ /* skip Version(2),Multicast cipter(4) 2+4==6 */
+ /* point to number of unicast */
+ pStaTmp +=6;
+ }
+ else if (eid_ptr->Eid == IE_WPA)
+ {
+ /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */
+ /* point to number of unicast */
+ pStaTmp += 10;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : invalid IE=%d\n", eid_ptr->Eid));
+ return FALSE;
+ }
+
+ /* Store unicast cipher count */
+ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT));
+ Count = cpu2le16(Count);
+
+
+ /* pointer to unicast cipher */
+ pStaTmp += sizeof(USHORT);
+
+ if (eid_ptr->Len >= 16)
+ {
+ if (eid_ptr->Eid == IE_WPA)
+ {
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled)
+ {/* multiple cipher (TKIP/CCMP) */
+
+ while (Count > 0)
+ {
+ /* TKIP */
+ if (MIX_CIPHER_WPA_TKIP_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher))
+ {
+ /* Compare if peer STA uses the TKIP as its unicast cipher */
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption2Enabled;
+ return TRUE;
+ }
+
+ /* Our AP uses the AES as the secondary cipher */
+ /* Compare if the peer STA use AES as its unicast cipher */
+ if (MIX_CIPHER_WPA_AES_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher))
+ {
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption3Enabled;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ /* AES */
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption3Enabled;
+ return TRUE;
+ }
+ }
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ else
+ {/* single cipher */
+ while (Count > 0)
+ {
+ if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4))
+ return TRUE;
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ }
+ else if (eid_ptr->Eid == IE_WPA2)
+ {
+ UCHAR IE_Idx = 0;
+
+ /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */
+ if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) || (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ IE_Idx = 1;
+
+ if (pAd->ApCfg.MBSSID[apidx].WepStatus == Ndis802_11Encryption4Enabled)
+ {/* multiple cipher (TKIP/CCMP) */
+
+ while (Count > 0)
+ {
+ /* WPA2 TKIP */
+ if (MIX_CIPHER_WPA2_TKIP_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher))
+ {
+ /* Compare if peer STA uses the TKIP as its unicast cipher */
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption2Enabled;
+ return TRUE;
+ }
+
+ /* Our AP uses the AES as the secondary cipher */
+ /* Compare if the peer STA use AES as its unicast cipher */
+ if (MIX_CIPHER_WPA2_AES_ON(pAd->ApCfg.MBSSID[apidx].WpaMixPairCipher))
+ {
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption3Enabled;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ /* AES */
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4))
+ {
+ pEntry->WepStatus = Ndis802_11Encryption3Enabled;
+ return TRUE;
+ }
+ }
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ else
+ {/* single cipher */
+ while (Count > 0)
+ {
+ if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4))
+ return TRUE;
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Check invalidity of authentication method selection in RSN IE.
+ Return:
+ TRUE if match
+ FALSE otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckAKM(PUCHAR sta_akm, PUCHAR ap_rsn_ie, INT iswpa2)
+{
+ PUCHAR pTmp;
+ USHORT Count;
+
+ pTmp = ap_rsn_ie;
+
+ if(iswpa2)
+ /* 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));
+ Count = cpu2le16(Count);
+
+ 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));
+ Count = cpu2le16(Count);
+
+ pTmp += sizeof(USHORT);/*pointer to AKM cipher */
+ while (Count > 0)
+ {
+ /*rtmp_hexdump(RT_DEBUG_TRACE,"MBSS WPA_IE AKM ",pTmp,4); */
+ if(RTMPEqualMemory(sta_akm,pTmp,4))
+ return TRUE;
+ else
+ {
+ pTmp += 4;
+ Count--;
+ }
+ }
+ return FALSE;/* do not match the AKM */
+
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Check sanity of authentication method selector in RSN IE.
+ Return:
+ TRUE if match
+ FALSE otherwise
+ ==========================================================================
+*/
+BOOLEAN RTMPCheckAUTH(
+ IN PRTMP_ADAPTER pAd,
+ IN PEID_STRUCT eid_ptr,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ PUCHAR pStaTmp;
+ USHORT Count;
+ UCHAR apidx;
+
+ ASSERT(pEntry);
+ ASSERT(pEntry->apidx < pAd->ApCfg.BssidNum);
+
+ apidx = pEntry->apidx;
+
+ if (eid_ptr->Len < 16)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> WPAIE len is too short(%d) \n", eid_ptr->Len));
+ return FALSE;
+ }
+
+ /* Store STA RSN_IE capability */
+ pStaTmp = (PUCHAR)&eid_ptr->Octet[0];
+ if(eid_ptr->Eid == IE_WPA2)
+ {
+ /* skip Version(2),Multicast cipter(4) 2+4==6 */
+ /* point to number of unicast */
+ pStaTmp +=6;
+ }
+ else if (eid_ptr->Eid == IE_WPA)
+ {
+ /* skip OUI(4),Vesrion(2),Multicast cipher(4) 4+2+4==10 */
+ /* point to number of unicast */
+ pStaTmp += 10;
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> Unknown WPAIE, WPAIE=%d\n", eid_ptr->Eid));
+ return FALSE;
+ }
+
+ /* Store unicast cipher count */
+ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT));
+ Count = cpu2le16(Count);
+
+ /* pointer to unicast cipher */
+ pStaTmp += sizeof(USHORT);
+
+ /* Skip all unicast cipher suite */
+ while (Count > 0)
+ {
+ /* Skip OUI */
+ pStaTmp += 4;
+ Count--;
+ }
+
+ /* Store AKM count */
+ NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT));
+ Count = cpu2le16(Count);
+
+ /*pointer to AKM cipher */
+ pStaTmp += sizeof(USHORT);
+
+ if (eid_ptr->Len >= 16)
+ {
+ if (eid_ptr->Eid == IE_WPA)
+ {
+ while (Count > 0)
+ {
+ if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0],0))
+ return TRUE;
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ else if (eid_ptr->Eid == IE_WPA2)
+ {
+ UCHAR IE_Idx = 0;
+
+ /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */
+ if ((pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1WPA2) ||
+ (pAd->ApCfg.MBSSID[apidx].AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK))
+ IE_Idx = 1;
+
+ while (Count > 0)
+ {
+ if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][0],1))
+ return TRUE;
+
+ pStaTmp += 4;
+ Count--;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ ==========================================================================
+ Description:
+ Check validity of the received RSNIE.
+
+ Return:
+ status code
+ ==========================================================================
+*/
+UINT APValidateRSNIE(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN PUCHAR pRsnIe,
+ IN UCHAR rsnie_len)
+{
+ UINT StatusCode = MLME_SUCCESS;
+ PEID_STRUCT eid_ptr;
+ INT apidx;
+ PMULTISSID_STRUCT pMbss;
+
+ if (rsnie_len == 0)
+ return MLME_SUCCESS;
+
+ eid_ptr = (PEID_STRUCT)pRsnIe;
+ if ((eid_ptr->Len + 2) != rsnie_len)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : the len is invalid !!!\n"));
+ return MLME_UNSPECIFY_FAIL;
+ }
+
+ apidx = pEntry->apidx;
+ pMbss = &pAd->ApCfg.MBSSID[apidx];
+
+#ifdef WAPI_SUPPORT
+ if (eid_ptr->Eid == IE_WAPI)
+ return MLME_SUCCESS;
+#endif /* WAPI_SUPPORT */
+
+ /* check group cipher */
+ if (!RTMPCheckMcast(pAd, eid_ptr, pEntry))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid group cipher !!!\n"));
+ StatusCode = MLME_INVALID_GROUP_CIPHER;
+ }
+ /* Check pairwise cipher */
+ else if (!RTMPCheckUcast(pAd, eid_ptr, pEntry))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid pairwise cipher !!!\n"));
+ StatusCode = MLME_INVALID_PAIRWISE_CIPHER;
+ }
+ /* Check AKM */
+ else if (!RTMPCheckAUTH(pAd, eid_ptr, pEntry))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid AKM !!!\n"));
+ StatusCode = MLME_INVALID_AKMP;
+ }
+
+ if (StatusCode != MLME_SUCCESS)
+ {
+ /* send wireless event - for RSN IE sanity check fail */
+ RTMPSendWirelessEvent(pAd, IW_RSNIE_SANITY_FAIL_EVENT_FLAG, pEntry->Addr, 0, 0);
+ DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid status code(%d) !!!\n", __FUNCTION__, StatusCode));
+ }
+ else
+ {
+ UCHAR CipherAlg = CIPHER_NONE;
+
+ if (pEntry->WepStatus == Ndis802_11Encryption1Enabled)
+ CipherAlg = CIPHER_WEP64;
+ else if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
+ CipherAlg = CIPHER_TKIP;
+ else if (pEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ CipherAlg = CIPHER_AES;
+ DBGPRINT(RT_DEBUG_TRACE, ("%s : (AID#%d WepStatus=%s)\n", __FUNCTION__, pEntry->Aid, CipherName[CipherAlg]));
+ }
+
+
+
+ return StatusCode;
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Function to handle countermeasures active attack. Init 60-sec timer if necessary.
+ Return:
+ ==========================================================================
+*/
+VOID HandleCounterMeasure(
+ IN PRTMP_ADAPTER pAd,
+ IN MAC_TABLE_ENTRY *pEntry)
+{
+ INT i;
+ BOOLEAN Cancelled;
+
+ if (!pEntry)
+ return;
+
+ /* Todo by AlbertY - Not support currently in ApClient-link */
+ if (IS_ENTRY_APCLI(pEntry))
+ return;
+
+ /* if entry not set key done, ignore this RX MIC ERROR */
+ if ((pEntry->WpaState < AS_PTKINITDONE) || (pEntry->GTKState != REKEY_ESTABLISHED))
+ return;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("HandleCounterMeasure ===> \n"));
+
+ /* record which entry causes this MIC error, if this entry sends disauth/disassoc, AP doesn't need to log the CM */
+ pEntry->CMTimerRunning = TRUE;
+ pAd->ApCfg.MICFailureCounter++;
+
+ /* send wireless event - for MIC error */
+ RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0);
+
+ if (pAd->ApCfg.CMTimerRunning == TRUE)
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Receive CM Attack Twice within 60 seconds ====>>> \n"));
+
+ /* send wireless event - for counter measures */
+ RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pEntry->Addr, 0, 0);
+ ApLogEvent(pAd, pEntry->Addr, EVENT_COUNTER_M);
+
+ /* renew GTK */
+ GenRandom(pAd, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, pAd->ApCfg.MBSSID[pEntry->apidx].GNonce);
+
+ /* Cancel CounterMeasure Timer */
+ RTMPCancelTimer(&pAd->ApCfg.CounterMeasureTimer, &Cancelled);
+ pAd->ApCfg.CMTimerRunning = FALSE;
+
+ for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ /* happened twice within 60 sec, AP SENDS disaccociate all associated STAs. All STA's transition to State 2 */
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]))
+ {
+ MlmeDeAuthAction(pAd, &pAd->MacTab.Content[i], REASON_MIC_FAILURE, FALSE);
+ }
+ }
+
+ /* Further, ban all Class 3 DATA transportation for a period 0f 60 sec */
+ /* disallow new association , too */
+ pAd->ApCfg.BANClass3Data = TRUE;
+
+ /* check how many entry left... should be zero */
+ /*pAd->ApCfg.MBSSID[pEntry->apidx].GKeyDoneStations = pAd->MacTab.Size; */
+ /*DBGPRINT(RT_DEBUG_TRACE, ("GKeyDoneStations=%d \n", pAd->ApCfg.MBSSID[pEntry->apidx].GKeyDoneStations)); */
+ }
+
+ RTMPSetTimer(&pAd->ApCfg.CounterMeasureTimer, 60 * MLME_TASK_EXEC_INTV * MLME_TASK_EXEC_MULTIPLE);
+ pAd->ApCfg.CMTimerRunning = TRUE;
+ pAd->ApCfg.PrevaMICFailTime = pAd->ApCfg.aMICFailTime;
+ RTMP_GetCurrentSystemTime(&pAd->ApCfg.aMICFailTime);
+}
+
+/*
+ ==========================================================================
+ Description:
+ countermeasures active attack timer execution
+ Return:
+ ==========================================================================
+*/
+VOID CMTimerExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ UINT i,j=0;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
+
+ pAd->ApCfg.BANClass3Data = FALSE;
+ for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i])
+ && (pAd->MacTab.Content[i].CMTimerRunning == TRUE))
+ {
+ pAd->MacTab.Content[i].CMTimerRunning =FALSE;
+ j++;
+ }
+ }
+ if (j > 1)
+ DBGPRINT(RT_DEBUG_ERROR, ("Find more than one entry which generated MIC Fail .. \n"));
+
+ pAd->ApCfg.CMTimerRunning = FALSE;
+}
+
+VOID WPARetryExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext;
+
+ if ((pEntry) && IS_ENTRY_CLIENT(pEntry))
+ {
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
+
+ pEntry->ReTryCounter++;
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec---> ReTryCounter=%d, WpaState=%d \n", pEntry->ReTryCounter, pEntry->WpaState));
+
+ switch (pEntry->AuthMode)
+ {
+ case Ndis802_11AuthModeWPA:
+ case Ndis802_11AuthModeWPAPSK:
+ case Ndis802_11AuthModeWPA2:
+ case Ndis802_11AuthModeWPA2PSK:
+ /* 1. GTK already retried, give up and disconnect client. */
+ if (pEntry->ReTryCounter > (GROUP_MSG1_RETRY_TIMER_CTR + 1))
+ {
+ /* send wireless event - for group key handshaking timeout */
+ RTMPSendWirelessEvent(pAd, IW_GROUP_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::Group Key HS exceed retry count, Disassociate client, pEntry->ReTryCounter %d\n", pEntry->ReTryCounter));
+ MlmeDeAuthAction(pAd, pEntry, REASON_GROUP_KEY_HS_TIMEOUT, FALSE);
+ }
+ /* 2. Retry GTK. */
+ else if (pEntry->ReTryCounter > GROUP_MSG1_RETRY_TIMER_CTR)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry 2-way group-key Handshake \n"));
+ if (pEntry->GTKState == REKEY_NEGOTIATING)
+ {
+ WPAStart2WayGroupHS(pAd, pEntry);
+ RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV);
+ }
+ }
+ /* 3. 4-way message 1 retried more than three times. Disconnect client */
+ else if (pEntry->ReTryCounter > (PEER_MSG1_RETRY_TIMER_CTR + 3))
+ {
+ /* send wireless event - for pairwise key handshaking timeout */
+ RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, pEntry->apidx, 0);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::MSG1 timeout, pEntry->ReTryCounter = %d\n", pEntry->ReTryCounter));
+ MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE);
+ }
+ /* 4. Retry 4 way message 1, the last try, the timeout is 3 sec for EAPOL-Start */
+ else if (pEntry->ReTryCounter == (PEER_MSG1_RETRY_TIMER_CTR + 3))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::Retry MSG1, the last try\n"));
+ WPAStart4WayHS(pAd , pEntry, PEER_MSG3_RETRY_EXEC_INTV);
+ }
+ /* 4. Retry 4 way message 1 */
+ else if (pEntry->ReTryCounter < (PEER_MSG1_RETRY_TIMER_CTR + 3))
+ {
+ if ((pEntry->WpaState == AS_PTKSTART) || (pEntry->WpaState == AS_INITPSK) || (pEntry->WpaState == AS_INITPMK))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry MSG1 of 4-way Handshake\n"));
+ WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+#ifdef APCLI_SUPPORT
+ else if ((pEntry) && IS_ENTRY_APCLI(pEntry))
+ {
+ if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)
+ {
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
+
+ if (pEntry->MatchAPCLITabIdx < MAX_APCLI_NUM)
+ {
+ UCHAR ifIndex = pEntry->MatchAPCLITabIdx;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex));
+ MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex);
+ }
+ }
+ }
+#endif /* APCLI_SUPPORT */
+}
+
+
+/*
+ ==========================================================================
+ Description:
+ Timer execution function for periodically updating group key.
+ Return:
+ ==========================================================================
+*/
+VOID GREKEYPeriodicExec(
+ IN PVOID SystemSpecific1,
+ IN PVOID FunctionContext,
+ IN PVOID SystemSpecific2,
+ IN PVOID SystemSpecific3)
+{
+ UINT i, apidx;
+ ULONG temp_counter = 0;
+ PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
+ PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3;
+ PMULTISSID_STRUCT pMbss = NULL;
+
+
+ for (apidx=0; apidx<pAd->ApCfg.BssidNum; apidx++)
+ {
+ if (&pAd->ApCfg.MBSSID[apidx].REKEYTimer == pTimer)
+ break;
+ }
+
+ if (apidx == pAd->ApCfg.BssidNum)
+ return;
+ else
+ pMbss = &pAd->ApCfg.MBSSID[apidx];
+
+ if (pMbss->AuthMode < Ndis802_11AuthModeWPA ||
+ pMbss->AuthMode > Ndis802_11AuthModeWPA1PSKWPA2PSK)
+ return;
+
+ if ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) && (pMbss->REKEYCOUNTER < 0xffffffff))
+ temp_counter = (++pMbss->REKEYCOUNTER);
+ /* REKEYCOUNTER is incremented every MCAST packets transmitted, */
+ /* But the unit of Rekeyinterval is 1K packets */
+ else if (pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY)
+ temp_counter = pMbss->REKEYCOUNTER/1000;
+ else
+ {
+ return;
+ }
+
+ if (temp_counter > (pMbss->WPAREKEY.ReKeyInterval))
+ {
+ pMbss->REKEYCOUNTER = 0;
+ pMbss->RekeyCountDown = 3;
+ DBGPRINT(RT_DEBUG_TRACE, ("Rekey Interval Excess, GKeyDoneStations=%d\n", pMbss->StaCount));
+
+ /* take turn updating different groupkey index, */
+ if ((pMbss->StaCount) > 0)
+ {
+ /* change key index */
+ pMbss->DefaultKeyId = (pMbss->DefaultKeyId == 1) ? 2 : 1;
+
+ /* Generate GNonce randomly */
+ GenRandom(pAd, pMbss->Bssid, pMbss->GNonce);
+
+ /* Update GTK */
+ WpaDeriveGTK(pMbss->GMK,
+ (UCHAR*)pMbss->GNonce,
+ pMbss->Bssid, pMbss->GTK, LEN_TKIP_GTK);
+
+ /* Process 2-way handshaking */
+ for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
+ {
+ MAC_TABLE_ENTRY *pEntry;
+
+ pEntry = &pAd->MacTab.Content[i];
+ if (IS_ENTRY_CLIENT(pEntry) &&
+ (pEntry->WpaState == AS_PTKINITDONE) &&
+ (pEntry->apidx == apidx))
+ {
+ pEntry->GTKState = REKEY_NEGOTIATING;
+
+ WPAStart2WayGroupHS(pAd, pEntry);
+ DBGPRINT(RT_DEBUG_TRACE, ("Rekey interval excess, Update Group Key for %x %x %x %x %x %x , DefaultKeyId= %x \n",\
+ pEntry->Addr[0],pEntry->Addr[1],\
+ pEntry->Addr[2],pEntry->Addr[3],\
+ pEntry->Addr[4],pEntry->Addr[5],\
+ pMbss->DefaultKeyId));
+ }
+ }
+ }
+ }
+
+ /* Use countdown to ensure the 2-way handshaking had completed */
+ if (pMbss->RekeyCountDown > 0)
+ {
+ pMbss->RekeyCountDown--;
+ if (pMbss->RekeyCountDown == 0)
+ {
+ USHORT Wcid;
+
+ /* Get a specific WCID to record this MBSS key attribute */
+ GET_GroupKey_WCID(pAd, Wcid, apidx);
+
+ /* Install shared key table */
+ WPAInstallSharedKey(pAd,
+ pMbss->GroupKeyWepStatus,
+ apidx,
+ pMbss->DefaultKeyId,
+ Wcid,
+ TRUE,
+ pMbss->GTK,
+ LEN_TKIP_GTK);
+ }
+ }
+
+}
+
+
+#ifdef DOT1X_SUPPORT
+/*
+ ========================================================================
+
+ Routine Description:
+ Sending EAP Req. frame to station in authenticating state.
+ These frames come from Authenticator deamon.
+
+ Arguments:
+ pAdapter Pointer to our adapter
+ pPacket Pointer to outgoing EAP frame body + 8023 Header
+ Len length of pPacket
+
+ Return Value:
+ None
+ ========================================================================
+*/
+VOID WpaSend(
+ IN PRTMP_ADAPTER pAdapter,
+ IN PUCHAR pPacket,
+ IN ULONG Len)
+{
+ PEAP_HDR pEapHdr;
+ UCHAR Addr[MAC_ADDR_LEN];
+ UCHAR Header802_3[LENGTH_802_3];
+ MAC_TABLE_ENTRY *pEntry;
+ PUCHAR pData;
+
+
+ NdisMoveMemory(Addr, pPacket, 6);
+ NdisMoveMemory(Header802_3, pPacket, LENGTH_802_3);
+ pEapHdr = (EAP_HDR*)(pPacket + LENGTH_802_3);
+ pData = (pPacket + LENGTH_802_3);
+
+ if ((pEntry = MacTableLookup(pAdapter, Addr)) == NULL)
+ {
+
+ return;
+ }
+
+ /* Send EAP frame to STA */
+ if (((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEapHdr->ProType != EAPOLKey)) ||
+ (pAdapter->ApCfg.MBSSID[pEntry->apidx].IEEE8021X == TRUE))
+ RTMPToWirelessSta(pAdapter,
+ pEntry,
+ Header802_3,
+ LENGTH_802_3,
+ pData,
+ Len - LENGTH_802_3,
+ (pEntry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE);
+
+
+ if (RTMPEqualMemory((pPacket+12), EAPOL, 2))
+ {
+ switch (pEapHdr->code)
+ {
+ case EAP_CODE_REQUEST:
+ if ((pEntry->WpaState >= AS_PTKINITDONE) && (pEapHdr->ProType == EAPPacket))
+ {
+ pEntry->WpaState = AS_AUTHENTICATION;
+ DBGPRINT(RT_DEBUG_TRACE, ("Start to re-authentication by 802.1x daemon\n"));
+ }
+ break;
+
+ /* After receiving EAP_SUCCESS, trigger state machine */
+ case EAP_CODE_SUCCESS:
+ if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEapHdr->ProType != EAPOLKey))
+ {
+ DBGPRINT(RT_DEBUG_TRACE,("Send EAP_CODE_SUCCESS\n\n"));
+ if (pEntry->Sst == SST_ASSOC)
+ {
+ pEntry->WpaState = AS_INITPMK;
+ /* Only set the expire and counters */
+ pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR;
+ WPAStart4WayHS(pAdapter, pEntry, PEER_MSG1_RETRY_EXEC_INTV);
+ }
+ }
+ else
+ {
+ pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
+ pEntry->WpaState = AS_PTKINITDONE;
+ pAdapter->ApCfg.MBSSID[pEntry->apidx].PortSecured = WPA_802_1X_PORT_SECURED;
+ pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
+#ifdef WSC_AP_SUPPORT
+ if (pAdapter->ApCfg.MBSSID[pEntry->apidx].WscControl.WscConfMode != WSC_DISABLE)
+ WscInformFromWPA(pEntry);
+#endif /* WSC_AP_SUPPORT */
+ DBGPRINT(RT_DEBUG_TRACE,("IEEE8021X-WEP : Send EAP_CODE_SUCCESS\n\n"));
+ }
+ break;
+
+ case EAP_CODE_FAILURE:
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("Send Deauth, Reason : REASON_NO_LONGER_VALID\n"));
+ MlmeDeAuthAction(pAdapter, pEntry, REASON_NO_LONGER_VALID, FALSE);
+ }
+}
+
+VOID RTMPAddPMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN PUCHAR pAddr,
+ IN UCHAR *PMKID,
+ IN UCHAR *PMK)
+{
+ INT i, CacheIdx;
+
+ /* Update PMKID status */
+ if ((CacheIdx = RTMPSearchPMKIDCache(pAd, apidx, pAddr)) != -1)
+ {
+ NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].RefreshTime));
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].PMKID, PMKID, LEN_PMKID);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[CacheIdx].PMK, PMK, PMK_LEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache update %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], CacheIdx, apidx));
+
+ return;
+ }
+
+ /* Add a new PMKID */
+ for (i = 0; i < MAX_PMKID_COUNT; i++)
+ {
+ if (!pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid)
+ {
+ pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid = TRUE;
+ NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime));
+ COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMKID, PMKID, LEN_PMKID);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMK, PMK, PMK_LEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], i, apidx));
+ break;
+ }
+ }
+
+ if (i == MAX_PMKID_COUNT)
+ {
+ ULONG timestamp = 0, idx = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache(IF(%d) Cache full\n", apidx));
+ for (i = 0; i < MAX_PMKID_COUNT; i++)
+ {
+ if (pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid)
+ {
+ if (((timestamp == 0) && (idx == 0)) || ((timestamp != 0) && timestamp < pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime))
+ {
+ timestamp = pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime;
+ idx = i;
+ }
+ }
+ }
+ pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].Valid = TRUE;
+ NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].RefreshTime));
+ COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].MAC, pAddr);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMKID, PMKID, LEN_PMKID);
+ NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMK, PMK, PMK_LEN);
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%ld) from IF(ra%d)\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], idx, apidx));
+ }
+}
+
+INT RTMPSearchPMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN PUCHAR pAddr)
+{
+ INT i = 0;
+
+ for (i = 0; i < MAX_PMKID_COUNT; i++)
+ {
+ if ((pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid)
+ && MAC_ADDR_EQUAL(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr))
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n",
+ pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], i, apidx));
+ break;
+ }
+ }
+
+ if (i == MAX_PMKID_COUNT)
+ {
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache - IF(%d) not found\n", apidx));
+ return -1;
+ }
+
+ return i;
+}
+
+VOID RTMPDeletePMKIDCache(
+ IN PRTMP_ADAPTER pAd,
+ IN INT apidx,
+ IN INT idx)
+{
+ PAP_BSSID_INFO pInfo = &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx];
+
+ if (pInfo->Valid)
+ {
+ pInfo->Valid = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPDeletePMKIDCache(IF(%d), del PMKID CacheIdx=%d\n", apidx, idx));
+ }
+}
+
+VOID RTMPMaintainPMKIDCache(
+ IN PRTMP_ADAPTER pAd)
+{
+ INT i, j;
+ ULONG Now;
+ for (i = 0; i < MAX_MBSSID_NUM(pAd); i++)
+ {
+ PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[i];
+
+ for (j = 0; j < MAX_PMKID_COUNT; j++)
+ {
+ PAP_BSSID_INFO pBssInfo = &pMbss->PMKIDCache.BSSIDInfo[j];
+
+ NdisGetSystemUpTime(&Now);
+
+ if ((pBssInfo->Valid)
+ && /*((Now - pBssInfo->RefreshTime) >= pMbss->PMKCachePeriod)*/
+ (RTMP_TIME_AFTER(Now, (pBssInfo->RefreshTime + pMbss->PMKCachePeriod))))
+ {
+ RTMPDeletePMKIDCache(pAd, i, j);
+ }
+ }
+ }
+}
+#endif /* DOT1X_SUPPORT */
+
+VOID RTMPGetTxTscFromAsic(
+ IN PRTMP_ADAPTER pAd,
+ IN UCHAR apidx,
+ OUT PUCHAR pTxTsc)
+{
+ USHORT Wcid;
+ USHORT offset;
+ UCHAR IvEiv[8];
+ int i;
+
+ /* Sanity check of apidx */
+ if (apidx >= MAX_MBSSID_NUM(pAd))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("RTMPGetTxTscFromAsic : invalid apidx(%d)\n", apidx));
+ return;
+ }
+
+ /* Initial value */
+ NdisZeroMemory(IvEiv, 8);
+ NdisZeroMemory(pTxTsc, 6);
+
+ /* Get apidx for this BSSID */
+ GET_GroupKey_WCID(pAd, Wcid, apidx);
+
+ /* When the group rekey action is triggered, a count-down(3 seconds) is started.
+ During the count-down, use the initial PN as TSC.
+ Otherwise, get the IVEIV from ASIC. */
+ if (pAd->ApCfg.MBSSID[apidx].RekeyCountDown > 0)
+ {
+ /*
+ In IEEE 802.11-2007 8.3.3.4.3 described :
+ The PN shall be implemented as a 48-bit monotonically incrementing
+ non-negative integer, initialized to 1 when the corresponding
+ temporal key is initialized or refreshed. */
+ IvEiv[0] = 1;
+ }
+ else
+ {
+ UINT32 temp1, temp2;
+ /* Read IVEIV from Asic */
+ offset = MAC_IVEIV_TABLE_BASE + (Wcid * HW_IVEIV_ENTRY_SIZE);
+
+ /* Use Read32 to avoid endian problem */
+ RTMP_IO_READ32(pAd, offset, &temp1);
+ RTMP_IO_READ32(pAd, offset+4, &temp2);
+ for ( i=0; i<4; i++)
+ {
+ IvEiv[i] = (UCHAR)(temp1 >> (i*8));
+ IvEiv[i+4] = (UCHAR)(temp2 >> (i*8));
+ }
+ }
+
+ /* Record current TxTsc */
+ if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11Encryption3Enabled)
+ { /* AES */
+ *pTxTsc = IvEiv[0];
+ *(pTxTsc+1) = IvEiv[1];
+ *(pTxTsc+2) = IvEiv[4];
+ *(pTxTsc+3) = IvEiv[5];
+ *(pTxTsc+4) = IvEiv[6];
+ *(pTxTsc+5) = IvEiv[7];
+ }
+ else
+ { /* TKIP */
+ *pTxTsc = IvEiv[2];
+ *(pTxTsc+1) = IvEiv[0];
+ *(pTxTsc+2) = IvEiv[4];
+ *(pTxTsc+3) = IvEiv[5];
+ *(pTxTsc+4) = IvEiv[6];
+ *(pTxTsc+5) = IvEiv[7];
+ }
+ DBGPRINT(RT_DEBUG_TRACE, ("RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n",
+ Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5)));
+
+
+}
+
+/*
+ ==========================================================================
+ Description:
+ Set group re-key timer
+
+ Return:
+
+ ==========================================================================
+*/
+VOID WPA_APSetGroupRekeyAction(
+ IN PRTMP_ADAPTER pAd)
+{
+ UINT8 apidx = 0;
+
+ for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
+ {
+ PMULTISSID_STRUCT pMbss = &pAd->ApCfg.MBSSID[apidx];
+
+ if ((pMbss->WepStatus == Ndis802_11Encryption2Enabled) ||
+ (pMbss->WepStatus == Ndis802_11Encryption3Enabled) ||
+ (pMbss->WepStatus == Ndis802_11Encryption4Enabled))
+ {
+ /* Group rekey related */
+ if ((pMbss->WPAREKEY.ReKeyInterval != 0)
+ && ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) || (
+ pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY)))
+ {
+ /* Regularly check the timer */
+ if (pMbss->REKEYTimerRunning == FALSE)
+ {
+ RTMPSetTimer(&pMbss->REKEYTimer, GROUP_KEY_UPDATE_EXEC_INTV);
+
+ pMbss->REKEYTimerRunning = TRUE;
+ pMbss->REKEYCOUNTER = 0;
+ }
+ DBGPRINT(RT_DEBUG_TRACE, (" %s : Group rekey method= %ld , interval = 0x%lx\n",
+ __FUNCTION__, pMbss->WPAREKEY.ReKeyMethod,
+ pMbss->WPAREKEY.ReKeyInterval));
+ }
+ else
+ pMbss->REKEYTimerRunning = FALSE;
+ }
+ }
+}
+
+#ifdef QOS_DLS_SUPPORT
+VOID RTMPHandleSTAKey(
+ IN PRTMP_ADAPTER pAd,
+ IN PMAC_TABLE_ENTRY pEntry,
+ IN MLME_QUEUE_ELEM *Elem)
+{
+ extern UCHAR OUI_WPA2_WEP40[];
+ ULONG FrameLen = 0;
+ PUCHAR pOutBuffer = NULL;
+ UCHAR Header802_3[14];
+ UCHAR *mpool;
+ PEAPOL_PACKET pOutPacket;
+ PEAPOL_PACKET pSTAKey;
+ PHEADER_802_11 pHeader;
+ UCHAR Offset = 0;
+ ULONG MICMsgLen;
+ UCHAR DA[MAC_ADDR_LEN];
+ UCHAR Key_Data[512];
+ UCHAR key_length;
+ UCHAR mic[LEN_KEY_DESC_MIC];
+ UCHAR rcv_mic[LEN_KEY_DESC_MIC];
+ UCHAR digest[80];
+ UCHAR temp[64];
+ PMAC_TABLE_ENTRY pDaEntry;
+
+ /*Benson add for big-endian 20081016--> */
+ KEY_INFO peerKeyInfo;
+ /*Benson add 20081016 <-- */
+
+ DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleSTAKey\n"));
+
+ if (!pEntry)
+ return;
+
+ if ((pEntry->WpaState != AS_PTKINITDONE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here"));
+ return;
+ }
+
+ pHeader = (PHEADER_802_11) Elem->Msg;
+
+ /* QoS control field (2B) is took off */
+/* if (pHeader->FC.SubType & 0x08) */
+/* Offset += 2; */
+
+ pSTAKey = (PEAPOL_PACKET)&Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H + Offset];
+ /*Benson add for big-endian 20081016--> */
+ NdisZeroMemory((PUCHAR)&peerKeyInfo, sizeof(peerKeyInfo));
+ NdisMoveMemory((PUCHAR)&peerKeyInfo, (PUCHAR)&pSTAKey->KeyDesc.KeyInfo, sizeof(KEY_INFO));
+ *((USHORT *)&peerKeyInfo) = cpu2le16(*((USHORT *)&peerKeyInfo));
+ /*Benson add 20081016 <-- */
+
+ /* Check Replay Counter */
+ if (!RTMPEqualMemory(pSTAKey->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Replay Counter Different in STAKey handshake!! \n"));
+ DBGPRINT(RT_DEBUG_ERROR, ("Receive : %d %d %d %d \n",
+ pSTAKey->KeyDesc.ReplayCounter[0],
+ pSTAKey->KeyDesc.ReplayCounter[1],
+ pSTAKey->KeyDesc.ReplayCounter[2],
+ pSTAKey->KeyDesc.ReplayCounter[3]));
+ DBGPRINT(RT_DEBUG_ERROR, ("Current : %d %d %d %d \n",
+ pEntry->R_Counter[4],pEntry->R_Counter[5],
+ pEntry->R_Counter[6],pEntry->R_Counter[7]));
+ return;
+ }
+
+ /* Check MIC, if not valid, discard silently */
+ NdisMoveMemory(DA, &pSTAKey->KeyDesc.KeyData[6], MAC_ADDR_LEN);
+
+ if (peerKeyInfo.KeyMic && peerKeyInfo.Secure && peerKeyInfo.Request)/*Benson add for big-endian 20081016 --> */
+ {
+ pEntry->bDlsInit = TRUE;
+ DBGPRINT(RT_DEBUG_TRACE, ("STAKey Initiator: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]));
+ }
+
+
+ MICMsgLen = pSTAKey->Body_Len[1] | ((pSTAKey->Body_Len[0]<<8) && 0xff00);
+ MICMsgLen += LENGTH_EAPOL_H;
+ if (MICMsgLen > (Elem->MsgLen - LENGTH_802_11 - LENGTH_802_1_H))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Receive wrong format EAPOL packets \n"));
+ return;
+ }
+
+ /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */
+ NdisZeroMemory(temp, 64);
+ NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, sizeof(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK));
+ NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+
+ WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, temp,
+ pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK);
+ DBGPRINT(RT_DEBUG_TRACE, ("PTK-%x %x %x %x %x %x %x %x \n",
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7]));
+
+
+ /* Record the received MIC for check later */
+ NdisMoveMemory(rcv_mic, pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ NdisZeroMemory(pSTAKey->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
+ if (pEntry->WepStatus == Ndis802_11Encryption2Enabled)
+ {
+ RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, mic, MD5_DIGEST_SIZE);
+ }
+ else
+ {
+ RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, (PUCHAR)pSTAKey, MICMsgLen, digest, SHA1_DIGEST_SIZE);
+ NdisMoveMemory(mic, digest, LEN_KEY_DESC_MIC);
+ }
+
+ if (!RTMPEqualMemory(rcv_mic, mic, LEN_KEY_DESC_MIC))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in STAKey handshake!! \n"));
+ return;
+ }
+ else
+ DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in STAKey handshake!! \n"));
+
+ /* Receive init STA's STAKey Message-2, and terminate the handshake */
+ /*if (pEntry->bDlsInit && !pSTAKey->KeyDesc.KeyInfo.Request) */
+ if (pEntry->bDlsInit && !peerKeyInfo.Request) /*Benson add for big-endian 20081016 --> */
+ {
+ pEntry->bDlsInit = FALSE;
+ DBGPRINT(RT_DEBUG_TRACE, ("Receive init STA's STAKey Message-2, STAKey handshake finished \n"));
+ return;
+ }
+
+ /* Receive init STA's STAKey Message-2, and terminate the handshake */
+ if (RTMPEqualMemory(&pSTAKey->KeyDesc.KeyData[2], OUI_WPA2_WEP40, 3))
+ {
+ DBGPRINT(RT_DEBUG_WARN, ("Receive a STAKey message which not support currently, just drop it \n"));
+ return;
+ }
+
+ do
+ {
+ pDaEntry = MacTableLookup(pAd, DA);
+ if (!pDaEntry)
+ break;
+
+ if ((pDaEntry->WpaState != AS_PTKINITDONE))
+ {
+ DBGPRINT(RT_DEBUG_ERROR, ("Not expect calling STAKey hand shaking here \n"));
+ break;
+ }
+
+ MlmeAllocateMemory(pAd, (PUCHAR *)&pOutBuffer); /* allocate memory */
+ if(pOutBuffer == NULL)
+ break;
+
+ MAKE_802_3_HEADER(Header802_3, pDaEntry->Addr, pAd->ApCfg.MBSSID[pDaEntry->apidx].Bssid, EAPOL);
+
+ /* Increment replay counter by 1 */
+ ADD_ONE_To_64BIT_VAR(pDaEntry->R_Counter);
+
+ /* Allocate memory for output */
+ os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER);
+ if (mpool == NULL)
+ {
+ MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+ DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__));
+ return;
+ }
+
+ pOutPacket = (PEAPOL_PACKET)mpool;
+ NdisZeroMemory(pOutPacket, TX_EAPOL_BUFFER);
+
+ /* 0. init Packet and Fill header */
+ pOutPacket->ProVer = EAPOL_VER;
+ pOutPacket->ProType = EAPOLKey;
+ pOutPacket->Body_Len[1] = 0x5f;
+
+ /* 1. Fill replay counter */
+/* NdisMoveMemory(pDaEntry->R_Counter, pAd->ApCfg.R_Counter, sizeof(pDaEntry->R_Counter)); */
+ NdisMoveMemory(pOutPacket->KeyDesc.ReplayCounter, pDaEntry->R_Counter, LEN_KEY_DESC_REPLAY);
+
+ /* 2. Fill key version, keyinfo, key len */
+ pOutPacket->KeyDesc.KeyInfo.KeyDescVer= GROUP_KEY;
+ pOutPacket->KeyDesc.KeyInfo.KeyType = GROUPKEY;
+ pOutPacket->KeyDesc.KeyInfo.Install = 1;
+ pOutPacket->KeyDesc.KeyInfo.KeyAck = 1;
+ pOutPacket->KeyDesc.KeyInfo.KeyMic = 1;
+ pOutPacket->KeyDesc.KeyInfo.Secure = 1;
+ pOutPacket->KeyDesc.KeyInfo.EKD_DL = 1;
+ DBGPRINT(RT_DEBUG_TRACE, ("STAKey handshake for peer STA %02x:%02x:%02x:%02x:%02x:%02x\n",
+ DA[0], DA[1], DA[2], DA[3], DA[4], DA[5]));
+
+ if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
+ {
+ pOutPacket->KeyDesc.Type = WPA1_KEY_DESC;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA/WPAPSK\n"));
+ }
+ else if ((pDaEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pDaEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
+ {
+ pOutPacket->KeyDesc.Type = WPA2_KEY_DESC;
+ pOutPacket->KeyDesc.KeyDataLen[1] = 0;
+
+ DBGPRINT(RT_DEBUG_TRACE, ("pDaEntry->AuthMode == Ndis802_11AuthModeWPA2/WPA2PSK\n"));
+ }
+
+ pOutPacket->KeyDesc.KeyLength[1] = LEN_TKIP_TK;
+ pOutPacket->KeyDesc.KeyDataLen[1] = LEN_TKIP_TK;
+ pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_TKIP;
+ if (pDaEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ pOutPacket->KeyDesc.KeyLength[1] = LEN_AES_TK;
+ pOutPacket->KeyDesc.KeyDataLen[1] = LEN_AES_TK;
+ pOutPacket->KeyDesc.KeyInfo.KeyDescVer = KEY_DESC_AES;
+ }
+
+ /* Key Data Encapsulation format, use Ralink OUI to distinguish proprietary and standard. */
+ Key_Data[0] = 0xDD;
+ Key_Data[1] = 0x00; /* Length (This field will be filled later) */
+ Key_Data[2] = 0x00; /* OUI */
+ Key_Data[3] = 0x0C; /* OUI */
+ Key_Data[4] = 0x43; /* OUI */
+ Key_Data[5] = 0x02; /* Data Type (STAKey Key Data Encryption) */
+
+ /* STAKey Data Encapsulation format */
+ Key_Data[6] = 0x00; /*Reserved */
+ Key_Data[7] = 0x00; /*Reserved */
+
+ /* STAKey MAC address */
+ NdisMoveMemory(&Key_Data[8], pEntry->Addr, MAC_ADDR_LEN); /* initiator MAC address */
+
+ /* STAKey (Handle the difference between TKIP and AES-CCMP) */
+ if (pDaEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ Key_Data[1] = 0x1E; /* 4+2+6+16(OUI+Reserved+STAKey_MAC_Addr+STAKey) */
+ NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_AES_TK);
+ }
+ else
+ {
+ Key_Data[1] = 0x2E; /* 4+2+6+32(OUI+Reserved+STAKey_MAC_Addr+STAKey) */
+ NdisMoveMemory(&Key_Data[14], pEntry->PairwiseKey.Key, LEN_TK);
+ NdisMoveMemory(&Key_Data[14+LEN_TK], pEntry->PairwiseKey.TxMic, LEN_TKIP_MIC);
+ NdisMoveMemory(&Key_Data[14+LEN_TK+LEN_TKIP_MIC], pEntry->PairwiseKey.RxMic, LEN_TKIP_MIC);
+ }
+
+ key_length = Key_Data[1];
+ pOutPacket->Body_Len[1] = key_length + 0x5f;
+
+ /* This is proprietary DLS protocol, it will be adhered when spec. is finished. */
+ NdisZeroMemory(temp, 64);
+ NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
+ WpaDerivePTK(pAd, temp, temp, pAd->ApCfg.MBSSID[pEntry->apidx].Bssid, temp, DA, pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("PTK-0-%x %x %x %x %x %x %x %x \n",
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[0],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[1],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[2],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[3],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[4],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[5],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[6],
+ pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK[7]));
+
+ NdisMoveMemory(pOutPacket->KeyDesc.KeyData, Key_Data, key_length);
+ NdisZeroMemory(mic, sizeof(mic));
+
+ *(USHORT *)(&pOutPacket->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pOutPacket->KeyDesc.KeyInfo));
+
+ MakeOutgoingFrame(pOutBuffer, &FrameLen,
+ pOutPacket->Body_Len[1] + 4, pOutPacket,
+ END_OF_ARGS);
+
+ /* Calculate MIC */
+ if (pDaEntry->WepStatus == Ndis802_11Encryption3Enabled)
+ {
+ RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, digest, SHA1_DIGEST_SIZE);
+ NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
+ }
+ else
+ {
+ RT_HMAC_MD5(pAd->ApCfg.MBSSID[pEntry->apidx].DlsPTK, LEN_PTK_KCK, pOutBuffer, FrameLen, mic, MD5_DIGEST_SIZE);
+ NdisMoveMemory(pOutPacket->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC);
+ }
+
+ RTMPToWirelessSta(pAd, pDaEntry, Header802_3, LENGTH_802_3, (PUCHAR)pOutPacket, pOutPacket->Body_Len[1] + 4, FALSE);
+
+ MlmeFreeMemory(pAd, (PUCHAR)pOutBuffer);
+ os_free_mem(NULL, mpool);
+ }while(FALSE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleSTAKey: FrameLen=%ld\n", FrameLen));
+}
+#endif /* QOS_DLS_SUPPORT */
+
+#ifdef HOSTAPD_SUPPORT
+/*for sending an event to notify hostapd about michael failure. */
+VOID ieee80211_notify_michael_failure(
+ IN PRTMP_ADAPTER pAd,
+ IN PHEADER_802_11 pHeader,
+ IN UINT keyix,
+ IN INT report)
+{
+ static const char *tag = "MLME-MICHAELMICFAILURE.indication";
+/* struct net_device *dev = pAd->net_dev; */
+/* union iwreq_data wrqu; */
+ char buf[128]; /* XXX */
+
+
+ /* TODO: needed parameters: count, keyid, key type, src address, TSC */
+ if(report)/*station reports a mic error to this ap. */
+ {
+ snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
+ keyix, "uni",
+ ether_sprintf(pHeader->Addr2));
+ }
+ else/*ap itself receives a mic error. */
+ {
+ snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag,
+ keyix, IEEE80211_IS_MULTICAST(pHeader->Addr1) ? "broad" : "uni",
+ ether_sprintf(pHeader->Addr2));
+ }
+ RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, -1, NULL, NULL, 0);
+/* NdisZeroMemory(&wrqu, sizeof(wrqu)); */
+/* wrqu.data.length = strlen(buf); */
+/* wireless_send_event(dev, RT_WLAN_EVENT_CUSTOM, &wrqu, buf); */
+}
+
+
+const CHAR* ether_sprintf(const UINT8 *mac)
+{
+ static char etherbuf[18];
+ snprintf(etherbuf,sizeof(etherbuf),"%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
+ return etherbuf;
+}
+#endif /* HOSTAPD_SUPPORT */
+
+
+#ifdef APCLI_SUPPORT
+#ifdef APCLI_WPA_SUPPLICANT_SUPPORT
+VOID ApcliWpaSendEapolStart(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pBssid,
+ IN PMAC_TABLE_ENTRY pMacEntry,
+ IN PAPCLI_STRUCT pApCliEntry)
+{
+ IEEE8021X_FRAME Packet;
+ UCHAR Header802_3[14];
+
+ DBGPRINT(RT_DEBUG_TRACE, ("-----> ApCliWpaSendEapolStart\n"));
+
+ NdisZeroMemory(Header802_3,sizeof(UCHAR)*14);
+
+ MAKE_802_3_HEADER(Header802_3, pBssid, &pApCliEntry->CurrentAddress[0], EAPOL);
+
+ // Zero message 2 body
+ NdisZeroMemory(&Packet, sizeof(Packet));
+ Packet.Version = EAPOL_VER;
+ Packet.Type = EAPOLStart;
+ Packet.Length = cpu2be16(0);
+
+ // Copy frame to Tx ring
+ RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry,
+ Header802_3, LENGTH_802_3, (PUCHAR)&Packet, 4, TRUE);
+
+ DBGPRINT(RT_DEBUG_TRACE, ("<----- WpaSendEapolStart\n"));
+}
+
+#define LENGTH_EAP_H 4
+// If the received frame is EAP-Packet ,find out its EAP-Code (Request(0x01), Response(0x02), Success(0x03), Failure(0x04)).
+INT ApcliWpaCheckEapCode(
+ IN PRTMP_ADAPTER pAd,
+ IN PUCHAR pFrame,
+ IN USHORT FrameLen,
+ IN USHORT OffSet)
+{
+
+ PUCHAR pData;
+ INT result = 0;
+
+ if( FrameLen < OffSet + LENGTH_EAPOL_H + LENGTH_EAP_H )
+ return result;
+
+ pData = pFrame + OffSet; // skip offset bytes
+
+ if(*(pData+1) == EAPPacket) // 802.1x header - Packet Type
+ {
+ result = *(pData+4); // EAP header - Code
+ }
+
+ return result;
+}
+#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */
+#endif/*APCLI_SUPPORT*/