assoc.c
来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 796 行 · 第 1/3 页
C
796 行
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2005, 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:
assoc.c
Abstract:
Handle association related requests either from WSTA or from local MLME
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-04-2003 created for 11g soft-AP
Rory Chen 02-04-2005 Support RT61
*/
#include "rt_config.h"
/*
==========================================================================
Description:
association state machine init, including state transition and timer init
Parameters:
S - pointer to the association state machine
Note:
The state machine looks like the following
ASSOC_IDLE
MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action
MT2_PEER_DISASSOC_REQ peer_disassoc_action
MT2_PEER_ASSOC_REQ drop
MT2_PEER_REASSOC_REQ drop
MT2_CLS3ERR cls3err_action
==========================================================================
*/
VOID AssocStateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *S,
OUT STATE_MACHINE_FUNC Trans[])
{
StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_ASSOC_STATE, MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, ASSOC_IDLE, ASSOC_MACHINE_BASE);
StateMachineSetAction(S, ASSOC_IDLE, MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)MlmeDisassocReqAction);
StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)PeerDisassocReqAction);
StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_ASSOC_REQ, (STATE_MACHINE_FUNC)PeerAssocReqAction);
StateMachineSetAction(S, ASSOC_IDLE, MT2_PEER_REASSOC_REQ, (STATE_MACHINE_FUNC)PeerReassocReqAction);
// StateMachineSetAction(S, ASSOC_IDLE, MT2_CLS3ERR, (STATE_MACHINE_FUNC)Cls3errAction);
}
/*
==========================================================================
Description:
peer assoc req handling procedure
Parameters:
Adapter - Adapter pointer
Elem - MLME Queue Element
Pre:
the station has been authenticated and the following information is stored
Post :
-# An association response frame is generated and sent to the air
==========================================================================
*/
VOID PeerAssocReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR Addr1[MAC_ADDR_LEN], Addr2[MAC_ADDR_LEN];
HEADER_802_11 AssocRspHdr;
UCHAR RateIe = IE_SUPP_RATES;
USHORT ListenInterval;
USHORT CapabilityInfo;
USHORT StatusCode = 0;
USHORT Aid = 1;
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
CHAR Ssid[32];
UCHAR SsidLen;
UCHAR SupportedRatesLen;
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR MaxSupportedRate = 0;
INT i;
UCHAR RSNIE_Len;
UCHAR RSN_IE[MAX_LEN_OF_RSNIE];
MAC_TABLE_ENTRY *pEntry;
BOOLEAN bWmmCapable;
ULONG RalinkIe;
BOOLEAN bRejectSTA = FALSE;
PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg;
// frame sanity check
if (! PeerAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, Addr2, &CapabilityInfo, &ListenInterval, &SsidLen, &Ssid[0], &SupportedRatesLen, &SupportedRates[0],RSN_IE, &RSNIE_Len, &bWmmCapable, &RalinkIe))
return;
pEntry = MacTableLookup(pAd, Addr2);
if (!pEntry)
return;
// clear the previous Pairwise key table
if(pEntry->Aid != 0)
{
NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY));
AsicRemovePairwiseKeyEntry(pAd, (UCHAR)pEntry->Aid);
//notify 802.1x-deamon to discard the sta
RTMPHandleNotify8021xDiscardSta(pAd, pEntry);
}
// for hidden SSID sake, SSID in AssociateRequest should be fully verified
if ((SsidLen != pAd->PortCfg.MBSSID[pEntry->ApIdx].SsidLen) || (NdisEqualMemory(Ssid, pAd->PortCfg.MBSSID[pEntry->ApIdx].Ssid, SsidLen)==0))
return;
// ignore request from unwanted STA
if (! ApCheckAccessControlList(pAd, Addr2, pEntry->ApIdx))
return;
DBGPRINT(RT_DEBUG_TRACE, "ASSOC - receive ASSOC request from %02x:%02x:%02x:%02x:%02x:%02x\n",
Addr2[0],Addr2[1],Addr2[2],Addr2[3],Addr2[4],Addr2[5]);
// sta supported rates must support all basic rates
for (i=0; i<pAd->PortCfg.SupportedRatesLen; i++) {
int j;
// the basic rate ap supported
if (pAd->PortCfg.SupportedRates[i] & 0x80) {
bRejectSTA = TRUE;
for (j=0; j<SupportedRatesLen; j++) {
if ((SupportedRates[j] & 0x7f) == (pAd->PortCfg.SupportedRates[i] & 0x7f)) {
bRejectSTA = FALSE;
break;
}
}
if (bRejectSTA == TRUE)
break;
}
}
// supported rates array may not be sorted. sort it and find the maximum rate
for (i=0; i<SupportedRatesLen; i++)
{
if (MaxSupportedRate < (SupportedRates[i] & 0x7f))
MaxSupportedRate = SupportedRates[i] & 0x7f;
}
if (bRejectSTA)
StatusCode = MLME_ASSOC_REJ_DATA_RATE;
else
// qualify this STA's auth_asoc status in the MAC table, decide StatusCode
StatusCode = BuildAssociation(pAd, Addr2, CapabilityInfo, MaxSupportedRate, RSN_IE, &RSNIE_Len, bWmmCapable, RalinkIe, &Aid);
// send Association Response
pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG);
if(pOutBuffer == NULL)
return;
DBGPRINT(RT_DEBUG_TRACE, "ASSOC - Send ASSOC response (Status=%d) from IF(ra%d)...\n\n", StatusCode, pEntry->ApIdx);
Aid |= 0xc000; // 2 most significant bits should be ON
MgtMacHeaderInit(pAd, &AssocRspHdr, SUBTYPE_ASSOC_RSP, 0, Addr2, pAd->PortCfg.MBSSID[pEntry->ApIdx].Bssid);
if ((pAd->PortCfg.PhyMode == PHY_11BG_MIXED) || (pAd->PortCfg.PhyMode == PHY_11G))
{
UCHAR SupportedRatesLen = 4;
UCHAR ExtendedRatesIe = IE_EXT_SUPP_RATES;
UCHAR ExtendedRatesLen = pAd->PortCfg.SupportedRatesLen - SupportedRatesLen;
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &AssocRspHdr,
2, &pAd->PortCfg.MBSSID[pEntry->ApIdx].CapabilityInfo ,//use AP's cability
2, &StatusCode,
2, &Aid,
1, &RateIe,
1, &SupportedRatesLen,
SupportedRatesLen, pAd->PortCfg.SupportedRates,
1, &ExtendedRatesIe,
1, &ExtendedRatesLen,
ExtendedRatesLen, &pAd->PortCfg.SupportedRates[SupportedRatesLen],
END_OF_ARGS);
}
else // include A band
{
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &AssocRspHdr,
2, &pAd->PortCfg.MBSSID[pEntry->ApIdx].CapabilityInfo ,//use AP's cability
2, &StatusCode,
2, &Aid,
1, &RateIe,
1, &pAd->PortCfg.SupportedRatesLen,
pAd->PortCfg.SupportedRatesLen, pAd->PortCfg.SupportedRates,
END_OF_ARGS);
}
#ifdef WMM_SUPPORT
// add WMM IE here
if (pAd->PortCfg.MBSSID[pEntry->ApIdx].bWmmCapable && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE))
{
ULONG TmpLen;
UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0};
WmeParmIe[8] = pAd->PortCfg.BssEdcaParm.EdcaUpdateCount & 0x0f;
WmeParmIe[8] |= (pAd->PortCfg.bAPSDCapable) ? 0x80 : 0x00;
for (i=QID_AC_BE; i<=QID_AC_VO; i++)
{
WmeParmIe[10+ (i*4)] = (i << 5) + // b5-6 is ACI
((UCHAR)pAd->PortCfg.BssEdcaParm.bACM[i] << 4) + // b4 is ACM
(pAd->PortCfg.BssEdcaParm.Aifsn[i] & 0x0f); // b0-3 is AIFSN
WmeParmIe[11+ (i*4)] = (pAd->PortCfg.BssEdcaParm.Cwmax[i] << 4) + // b5-8 is CWMAX
(pAd->PortCfg.BssEdcaParm.Cwmin[i] & 0x0f); // b0-3 is CWMIN
WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->PortCfg.BssEdcaParm.Txop[i] & 0xff); // low byte of TXOP
WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->PortCfg.BssEdcaParm.Txop[i] >> 8); // high byte of TXOP
}
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
26, WmeParmIe,
END_OF_ARGS);
FrameLen += TmpLen;
}
#endif /* WMM_SUPPORT */
#ifdef AGGREGATION_SUPPORT
// add Ralink-specific IE here - Byte0.b0=1 for aggregation
if (pAd->PortCfg.bAggregationCapable)
{
ULONG TmpLen;
UCHAR RalinkSpecificIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00};
MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen,
9, RalinkSpecificIe,
END_OF_ARGS);
FrameLen += TmpLen;
}
#endif
MiniportMMRequest(pAd, pOutBuffer, FrameLen);
kfree(pOutBuffer);
// enqueue a EAPOL_START message to trigger WPA state machine doing the authentication
if (StatusCode == MLME_SUCCESS)
{
#ifdef RTL865X_FAST_PATH
rtl865x_extDev_addHost(pEntry->Addr, CONFIG_8139CP_VID, pAd->PortCfg.MBSSID[pEntry->ApIdx].mylinkid);
#endif
pAd->RTSignal.Sig = SIG_ASSOCIATION;
pAd->RTSignal.Sequence = Fr->Hdr.Sequence;
NdisMoveMemory(pAd->RTSignal.MacAddr, pEntry->Addr, MAC_ADDR_LEN);
SendSingalToDaemon(pAd, SIGUSR2);
if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
{
// Enqueue a EAPOL-start message with the pEntry
MlmeEnqueue(pAd, WPA_STATE_MACHINE, MACHINE_TYPE_EAPOLStart, 6, &Addr2);
}
else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (RSNIE_Len == 38))
{// Key cache
// WZC didn't support PMK cache in assoc phase.
#if 0
INT CacheIdx;
if (((CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->ApIdx, pEntry->Addr)) != -1) && (RTMPEqualMemory((RSN_IE + 22), &pAd->PortCfg.MBSSID[pEntry->ApIdx].PMKIDCache.BSSIDInfo[CacheIdx].PMKID, LEN_PMKID)))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?