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 + -
显示快捷键?