blob: 06a4c0fdf6af5e287f2f29a11c77047b56b026c5 [file] [log] [blame]
/*
* Copyright (c) 2012-2013, 2017-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file was originally distributed by Qualcomm Atheros, Inc.
* under proprietary terms before Copyright ownership was assigned
* to the Linux Foundation.
*/
/*
* This file limProcessAssocReqFrame.cc contains the code
* for processing Re/Association Request Frame.
* Author: Chandra Modumudi
* Date: 03/18/02
* History:-
* Date Modified by Modification Information
* --------------------------------------------------------------------
* 05/26/10 js WPA handling in (Re)Assoc frames
*
*/
#include "palTypes.h"
#include "aniGlobal.h"
#include "wniCfg.h"
#include "sirApi.h"
#include "cfgApi.h"
#include "schApi.h"
#include "pmmApi.h"
#include "utilsApi.h"
#include "limTypes.h"
#include "limUtils.h"
#include "limAssocUtils.h"
#include "limSecurityUtils.h"
#include "limSerDesUtils.h"
#include "limStaHashApi.h"
#include "limAdmitControl.h"
#include "palApi.h"
#include "limSessionUtils.h"
#include "vos_types.h"
/**
* limConvertSupportedChannels
*
*FUNCTION:
* This function is called by limProcessAssocReqFrame() to
* parse the channel support IE in the Assoc/Reassoc Request
* frame, and send relevant information in the SME_ASSOC_IND
*
*NOTE:
*
* @param pMac - A pointer to Global MAC structure
* @param pMlmAssocInd - A pointer to SME ASSOC/REASSOC IND
* @param assocReq - A pointer to ASSOC/REASSOC Request frame
*
* @return None
*/
static void
limConvertSupportedChannels(tpAniSirGlobal pMac,
tpLimMlmAssocInd pMlmAssocInd,
tSirAssocReq *assocReq)
{
tANI_U16 i, j, index=0;
tANI_U8 firstChannelNumber;
tANI_U8 numberOfChannel;
tANI_U8 nextChannelNumber;
if(assocReq->supportedChannels.length >= SIR_MAX_SUPPORTED_CHANNEL_LIST)
{
limLog(pMac, LOG1, FL("Number of supported channels:%d is more than "
"MAX"), assocReq->supportedChannels.length);
pMlmAssocInd->supportedChannels.numChnl = 0;
return;
}
for(i=0; i < (assocReq->supportedChannels.length); i++)
{
// Get First Channel Number
firstChannelNumber = assocReq->supportedChannels.supportedChannels[i];
pMlmAssocInd->supportedChannels.channelList[index] = firstChannelNumber;
i++;
index++;
if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST)
{
pMlmAssocInd->supportedChannels.numChnl = 0;
return;
}
// Get Number of Channels in a Subband
numberOfChannel = assocReq->supportedChannels.supportedChannels[i];
PELOG2(limLog(pMac, LOG2, FL("Rcv AssocReq: chnl=%d, numOfChnl=%d "),
firstChannelNumber, numberOfChannel);)
if (numberOfChannel > 1)
{
nextChannelNumber = firstChannelNumber;
if(SIR_BAND_5_GHZ == limGetRFBand(firstChannelNumber))
{
for (j=1; j < numberOfChannel; j++)
{
nextChannelNumber += SIR_11A_FREQUENCY_OFFSET;
pMlmAssocInd->supportedChannels.channelList[index] = nextChannelNumber;
index++;
if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST)
{
pMlmAssocInd->supportedChannels.numChnl = 0;
return;
}
}
}
else if(SIR_BAND_2_4_GHZ == limGetRFBand(firstChannelNumber))
{
for (j=1; j < numberOfChannel; j++)
{
nextChannelNumber += SIR_11B_FREQUENCY_OFFSET;
pMlmAssocInd->supportedChannels.channelList[index] = nextChannelNumber;
index++;
if (index >= SIR_MAX_SUPPORTED_CHANNEL_LIST)
{
pMlmAssocInd->supportedChannels.numChnl = 0;
return;
}
}
}
}
}
pMlmAssocInd->supportedChannels.numChnl = (tANI_U8) index;
PELOG2(limLog(pMac, LOG2,
FL("Send AssocInd to WSM: spectrum ON, minPwr %d, maxPwr %d, "
"numChnl %d"),
pMlmAssocInd->powerCap.minTxPower,
pMlmAssocInd->powerCap.maxTxPower,
pMlmAssocInd->supportedChannels.numChnl);)
}
/**---------------------------------------------------------------
\fn limProcessAssocReqFrame
\brief This function is called by limProcessMessageQueue()
\ upon Re/Association Request frame reception in
\ BTAMP AP or Soft AP role.
\
\param pMac
\param *pRxPacketInfo - A pointer to Buffer descriptor + associated PDUs
\param subType - Indicates whether it is Association Request(=0)
\ or Reassociation Request(=1) frame
\return None
------------------------------------------------------------------*/
void
limProcessAssocReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,
tANI_U8 subType, tpPESession psessionEntry)
{
tANI_U8 updateContext;
tANI_U8 *pBody;
tANI_U16 peerIdx, temp;
tANI_U32 val;
tANI_U16 prevAuthSeqno = 0xFFFF;
tANI_S32 framelen;
tSirRetStatus status;
tpSirMacMgmtHdr pHdr;
struct tLimPreAuthNode *pStaPreAuthContext;
tAniAuthType authType;
tSirMacCapabilityInfo localCapabilities;
tpDphHashNode pStaDs = NULL;
tpSirAssocReq pAssocReq;
tLimMlmStates mlmPrevState;
tDot11fIERSN Dot11fIERSN;
tDot11fIEWPA Dot11fIEWPA;
tANI_U32 phyMode;
tHalBitVal qosMode;
tHalBitVal wsmMode, wmeMode;
tANI_U8 *wpsIe = NULL;
tSirMacRateSet basicRates;
tANI_U8 i = 0, j = 0;
tANI_BOOLEAN pmfConnection = eANI_BOOLEAN_FALSE;
#ifdef WLAN_FEATURE_11W
tPmfSaQueryTimerId timerId;
tANI_U32 retryInterval;
#endif
limGetPhyMode(pMac, &phyMode, psessionEntry);
limGetQosMode(psessionEntry, &qosMode);
pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo);
framelen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
limLog(pMac, LOG1, FL("Received %s Req Frame on sessionid: %d systemrole %d"
" limMlmState %d from: "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
psessionEntry->peSessionId, psessionEntry->limSystemRole,
psessionEntry->limMlmState, MAC_ADDR_ARRAY(pHdr->sa));
if (psessionEntry->limSystemRole == eLIM_STA_ROLE || psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE )
{
limLog(pMac, LOGE, FL("received unexpected ASSOC REQ on sessionid: %d "
"sys subType=%d for role=%d from: "MAC_ADDRESS_STR),
psessionEntry->peSessionId,
subType, psessionEntry->limSystemRole, MAC_ADDR_ARRAY(pHdr->sa));
sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3,
WDA_GET_RX_MPDU_DATA(pRxPacketInfo), framelen);
return;
}
/*
* If a STA is already present in DPH and it
* is initiating a Assoc re-transmit, do not
* process it. This can happen when first Assoc Req frame
* is received but ACK lost at STA side. The ACK for this
* dropped Assoc Req frame should be sent by HW. Host simply
* does not process it once the entry for the STA is already
* present in DPH.
*/
pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &peerIdx,
&psessionEntry->dph.dphHashTable);
if (NULL != pStaDs)
{
if (pStaDs->PrevAssocSeqno == ((pHdr->seqControl.seqNumHi << 4) |
(pHdr->seqControl.seqNumLo)))
{
/* Ignore the Retry */
limLog(pMac, LOGE,
FL("STA is initiating Assoc Req after ACK lost. "
"So, do not Process sessionid: %d sys subType=%d "
"for role=%d from: "MAC_ADDRESS_STR),
psessionEntry->peSessionId, subType,
psessionEntry->limSystemRole,
MAC_ADDR_ARRAY(pHdr->sa));
return;
}
else
{
#ifdef WLAN_FEATURE_11W
/* Do not send Assoc rsp for duplicate assoc req in case of PMF
* enabled STA, as driver needs to start SA Querry in this case
*/
if (!pStaDs->rmfEnabled)
#endif
{
/* STA might have missed the assoc response,
* so it is sending assoc request frame again.
*/
limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS,
pStaDs->assocId, pStaDs->staAddr,
pStaDs->mlmStaContext.subType, pStaDs,
psessionEntry, NULL);
limLog(pMac, LOGE,
FL("DUT already received an assoc request frame "
"and STA is sending another assoc req.So, do not "
"Process sessionid: %d sys subType=%d for role=%d "
"from: "MAC_ADDRESS_STR),
psessionEntry->peSessionId, subType,
psessionEntry->limSystemRole,
MAC_ADDR_ARRAY(pHdr->sa));
return;
}
}
}
// Get pointer to Re/Association Request frame body
pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo);
if (limIsGroupAddr(pHdr->sa))
{
// Received Re/Assoc Req frame from a BC/MC address
// Log error and ignore it
limLog(pMac, LOGE, FL("Received %s Req on sessionid: %d frame from a "
"BC/MC address"MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
psessionEntry->peSessionId,
MAC_ADDR_ARRAY(pHdr->sa));
return;
}
sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, (tANI_U8 *) pBody, framelen);
if (vos_mem_compare((tANI_U8* ) pHdr->sa, (tANI_U8 *) pHdr->da,
(tANI_U8) (sizeof(tSirMacAddr))))
{
limLog(pMac, LOGE, FL("Rejected Assoc Req frame Since same mac as"
" SAP/GO"));
limSendAssocRspMgmtFrame(pMac,
eSIR_MAC_UNSPEC_FAILURE_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
return ;
}
// If TKIP counter measures active send Assoc Rsp frame to station with eSIR_MAC_MIC_FAILURE_REASON
if ((psessionEntry->bTkipCntrMeasActive) && (psessionEntry->limSystemRole == eLIM_AP_ROLE))
{
limLog(pMac, LOGE, FL("TKIP counter measure is active"));
limSendAssocRspMgmtFrame(pMac,
eSIR_MAC_MIC_FAILURE_REASON,
1,
pHdr->sa,
subType, 0, psessionEntry, NULL);
return;
}
// Allocate memory for the Assoc Request frame
pAssocReq = vos_mem_malloc(sizeof(*pAssocReq));
if (NULL == pAssocReq)
{
limLog(pMac, LOGP, FL("Allocate Memory failed in AssocReq"));
return;
}
vos_mem_set((void *)pAssocReq , sizeof(*pAssocReq), 0);
// Parse Assoc Request frame
if (subType == LIM_ASSOC)
status = sirConvertAssocReqFrame2Struct(pMac, pBody, framelen, pAssocReq);
else
status = sirConvertReassocReqFrame2Struct(pMac, pBody, framelen, pAssocReq);
if (status != eSIR_SUCCESS)
{
limLog(pMac, LOGW,
FL("Parse error AssocRequest, length=%d from "MAC_ADDRESS_STR),
framelen, MAC_ADDR_ARRAY(pHdr->sa));
limSendAssocRspMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_STATUS, 1,
pHdr->sa, subType, 0, psessionEntry, NULL);
goto error;
}
pAssocReq->assocReqFrame = vos_mem_malloc(framelen);
if ( NULL == pAssocReq->assocReqFrame )
{
limLog(pMac, LOGE, FL("Unable to allocate memory for the assoc req, "
"length=%d from "),framelen);
goto error;
}
vos_mem_copy((tANI_U8 *) pAssocReq->assocReqFrame,
(tANI_U8 *) pBody, framelen);
pAssocReq->assocReqFrameLength = framelen;
if (cfgGetCapabilityInfo(pMac, &temp,psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("could not retrieve Capabilities"));
goto error;
}
limCopyU16((tANI_U8 *) &localCapabilities, temp);
if (limCompareCapabilities(pMac,
pAssocReq,
&localCapabilities,psessionEntry) == false)
{
limLog(pMac, LOGE, FL("local caps mismatch received caps"));
limLog(pMac, LOGE, FL("Received %s Req with unsupported "
"capabilities from"MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
/**
* Capabilities of requesting STA does not match with
* local capabilities. Respond with 'unsupported capabilities'
* status code.
*/
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry ,NULL);
goto error;
}
updateContext = false;
if (limCmpSSid(pMac, &pAssocReq->ssId, psessionEntry) == false)
{
limLog(pMac, LOGE, FL("Received %s Req with unmatched ssid ( Received"
" SSID: %.*s current SSID: %.*s ) from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", pAssocReq->ssId.length,
pAssocReq->ssId.ssId, psessionEntry->ssId.length,
psessionEntry->ssId.ssId, MAC_ADDR_ARRAY(pHdr->sa));
/**
* Received Re/Association Request with either
* Broadcast SSID OR with SSID that does not
* match with local one.
* Respond with unspecified status code.
*/
limSendAssocRspMgmtFrame(pMac,
eSIR_MAC_UNSPEC_FAILURE_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
/***************************************************************
** Verify if the requested rates are available in supported rate
** set or Extended rate set. Some APs are adding basic rates in
** Extended rateset IE
***************************************************************/
basicRates.numRates = 0;
for(i = 0; i < pAssocReq->supportedRates.numRates && (i < SIR_MAC_RATESET_EID_MAX); i++)
{
basicRates.rate[i] = pAssocReq->supportedRates.rate[i];
basicRates.numRates++;
}
for(j = 0; (j < pAssocReq->extendedRates.numRates) && (i < SIR_MAC_RATESET_EID_MAX); i++,j++)
{
basicRates.rate[i] = pAssocReq->extendedRates.rate[j];
basicRates.numRates++;
}
if (limCheckRxBasicRates(pMac, basicRates, psessionEntry) == false)
{
limLog(pMac, LOGE, FL("Received %s Req with unsupported "
"rates from"MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
/**
* Requesting STA does not support ALL BSS basic
* rates. Respond with 'basic rates not supported'
* status code.
*/
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
if((psessionEntry->limSystemRole == eLIM_AP_ROLE ) &&
(psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11G_ONLY) &&
((!pAssocReq->extendedRatesPresent ) || (pAssocReq->HTCaps.present)))
{
limLog(pMac, LOGE, FL("SOFTAP was in 11G only mode, rejecting legacy "
"STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));
limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
1, pHdr->sa, subType, 0, psessionEntry, NULL);
goto error;
}//end if phyMode == 11G_only
if((psessionEntry->limSystemRole == eLIM_AP_ROLE) &&
(psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11N_ONLY) &&
(!pAssocReq->HTCaps.present))
{
limLog(pMac, LOGE, FL("SOFTAP was in 11N only mode, rejecting legacy "
"STA : "MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));
limSendAssocRspMgmtFrame( pMac, eSIR_MAC_CAPABILITIES_NOT_SUPPORTED_STATUS,
1, pHdr->sa, subType, 0, psessionEntry, NULL);
goto error;
}//end if PhyMode == 11N_only
/* Spectrum Management (11h) specific checks */
if (localCapabilities.spectrumMgt)
{
tSirRetStatus status = eSIR_SUCCESS;
/* If station is 11h capable, then it SHOULD send all mandatory
* IEs in assoc request frame. Let us verify that
*/
if (pAssocReq->capabilityInfo.spectrumMgt)
{
if (!((pAssocReq->powerCapabilityPresent) && (pAssocReq->supportedChannelsPresent)))
{
/* One or more required information elements are missing, log the peers error */
if (!pAssocReq->powerCapabilityPresent)
{
limLog(pMac, LOG1, FL("LIM Info: Missing Power capability "
"IE in %s Req from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
}
if (!pAssocReq->supportedChannelsPresent)
{
limLog(pMac, LOGW, FL("LIM Info: Missing Supported channel "
"IE in %s Req from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
}
}
else
{
/* Assoc request has mandatory fields */
status = limIsDot11hPowerCapabilitiesInRange(pMac, pAssocReq, psessionEntry);
if (eSIR_SUCCESS != status)
{
limLog(pMac, LOGW, FL("LIM Info: MinTxPower(STA) > "
"MaxTxPower(AP) in %s Req from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
}
status = limIsDot11hSupportedChannelsValid(pMac, pAssocReq);
if (eSIR_SUCCESS != status)
{
limLog(pMac, LOGW, FL("LIM Info: wrong supported "
"channels (STA) in %s Req from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
}
/* IEs are valid, use them if needed */
}
} //if(assoc.capabilityInfo.spectrumMgt)
else
{
/* As per the capabiities, the spectrum management is not enabled on the station
* The AP may allow the associations to happen even if spectrum management is not
* allowed, if the transmit power of station is below the regulatory maximum
*/
/* TODO: presently, this is not handled. In the current implemetation, the AP would
* allow the station to associate even if it doesn't support spectrum management.
*/
}
}// end of spectrum management related processing
if ( (pAssocReq->HTCaps.present) && (limCheckMCSSet(pMac, pAssocReq->HTCaps.supportedMCSSet) == false))
{
limLog(pMac, LOGE, FL("received %s req with unsupported"
"MCS Rate Set from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
MAC_ADDR_ARRAY(pHdr->sa));
/**
* Requesting STA does not support ALL BSS MCS basic Rate set rates.
* Spec does not define any status code for this scenario.
*/
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_OUTSIDE_SCOPE_OF_SPEC_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
//if (pMac->dph.gDphPhyMode == WNI_CFG_PHY_MODE_11G)
if (phyMode == WNI_CFG_PHY_MODE_11G)
{
if (wlan_cfgGetInt(pMac, WNI_CFG_11G_ONLY_POLICY, &val) != eSIR_SUCCESS)
{
limLog(pMac, LOGP, FL("could not retrieve 11g-only flag"));
goto error;
}
if (!pAssocReq->extendedRatesPresent && val)
{
limLog(pMac, LOGE, FL("Rejecting Re/Assoc req from 11b STA: "
MAC_ADDRESS_STR),MAC_ADDR_ARRAY(pHdr->sa));
/**
* Received Re/Association Request from
* 11b STA when 11g only policy option
* is set.
* Reject with unspecified status code.
*/
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_BASIC_RATES_NOT_SUPPORTED_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
#ifdef WLAN_DEBUG
pMac->lim.gLim11bStaAssocRejectCount++;
#endif
goto error;
}
}
#ifdef WMM_APSD
// Save the QOS info element in assoc request..
limGetWmeMode(pMac, &wmeMode);
if (wmeMode == eHAL_SET)
{
tpQosInfoSta qInfo;
qInfo = (tpQosInfoSta) (pAssocReq->qosCapability.qosInfo);
if ((pMac->lim.gWmmApsd.apsdEnable == 0) && (qInfo->ac_be || qInfo->ac_bk || qInfo->ac_vo || qInfo->ac_vi))
{
limLog(pMac, LOGW,
FL("Rejecting Re/Assoc req from STA: "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
limLog(pMac, LOGE, FL("APSD not enabled, qosInfo - 0x%x"), *qInfo);
/**
* Received Re/Association Request from
* 11b STA when 11g only policy option
* is set.
* Reject with unspecified status code.
*/
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_WME_REFUSED_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
}
#endif
// Check for 802.11n HT caps compatibility; are HT Capabilities
// turned on in lim?
if ( psessionEntry->htCapability )
{
// There are; are they turned on in the STA?
if ( pAssocReq->HTCaps.present )
{
// The station *does* support 802.11n HT capability...
limLog( pMac, LOG1, FL( "AdvCodingCap:%d ChaWidthSet:%d "
"PowerSave:%d greenField:%d "
"shortGI20:%d shortGI40:%d"
"txSTBC:%d rxSTBC:%d delayBA:%d"
"maxAMSDUsize:%d DSSS/CCK:%d "
"PSMP:%d stbcCntl:%d lsigTXProt:%d"),
pAssocReq->HTCaps.advCodingCap,
pAssocReq->HTCaps.supportedChannelWidthSet,
pAssocReq->HTCaps.mimoPowerSave,
pAssocReq->HTCaps.greenField,
pAssocReq->HTCaps.shortGI20MHz,
pAssocReq->HTCaps.shortGI40MHz,
pAssocReq->HTCaps.txSTBC,
pAssocReq->HTCaps.rxSTBC,
pAssocReq->HTCaps.delayedBA,
pAssocReq->HTCaps.maximalAMSDUsize,
pAssocReq->HTCaps.dsssCckMode40MHz,
pAssocReq->HTCaps.psmp,
pAssocReq->HTCaps.stbcControlFrame,
pAssocReq->HTCaps.lsigTXOPProtection );
// Make sure the STA's caps are compatible with our own:
//11.15.2 Support of DSSS/CCK in 40 MHz
//the AP shall refuse association requests from an HT STA that has the DSSS/CCK
//Mode in 40 MHz subfield set to 1;
//FIXME_BTAMP_AP : Need to be enabled
/*
if ( !pMac->lim.gHTDsssCckRate40MHzSupport && pAssocReq->HTCaps.dsssCckMode40MHz )
{
statusCode = eSIR_MAC_DSSS_CCK_RATE_NOT_SUPPORT_STATUS;
limLog( pMac, LOGW, FL( "AP DSSS/CCK is disabled; "
"STA rejected." ) );
// Reject association
limSendAssocRspMgmtFrame( pMac, statusCode, 1, pHdr->sa, subType, 0,psessionEntry);
goto error;
}
*/
}
} // End if on HT caps turned on in lim.
/* Clear the buffers so that frame parser knows that there isn't a previously decoded IE in these buffers */
vos_mem_set((tANI_U8*)&Dot11fIERSN, sizeof( Dot11fIERSN ), 0);
vos_mem_set((tANI_U8*)&Dot11fIEWPA, sizeof( Dot11fIEWPA ), 0);
/* if additional IE is present, check if it has WscIE */
if( pAssocReq->addIEPresent && pAssocReq->addIE.length )
wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length);
/* when wpsIe is present, RSN/WPA IE is ignored */
if( wpsIe == NULL )
{
/** check whether as RSN IE is present */
if(psessionEntry->limSystemRole == eLIM_AP_ROLE
&& psessionEntry->pLimStartBssReq->privacy
&& psessionEntry->pLimStartBssReq->rsnIE.length)
{
limLog(pMac, LOG1,
FL("RSN enabled auth, Re/Assoc req from STA: "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
if(pAssocReq->rsnPresent)
{
if(pAssocReq->rsn.length)
{
// Unpack the RSN IE
if (dot11fUnpackIeRSN(pMac,
&pAssocReq->rsn.info[0],
pAssocReq->rsn.length,
&Dot11fIERSN) != DOT11F_PARSE_SUCCESS)
{
limLog(pMac, LOGE,
FL("Invalid RSNIE received"));
limSendAssocRspMgmtFrame(pMac,
eSIR_MAC_INVALID_RSN_IE_CAPABILITIES_STATUS,
1, pHdr->sa, subType, 0,psessionEntry, NULL);
goto error;
}
/* Check RSN version is supported or not */
if(SIR_MAC_OUI_VERSION_1 == Dot11fIERSN.version)
{
/* check the groupwise and pairwise cipher suites */
if(eSIR_SUCCESS != (status = limCheckRxRSNIeMatch(pMac, Dot11fIERSN, psessionEntry,
pAssocReq->HTCaps.present, &pmfConnection)))
{
limLog(pMac, LOGE, FL("RSN Mismatch. Rejecting Re/Assoc req from "
"STA: "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
/* some IE is not properly sent */
/* received Association req frame with RSN IE but length is 0 */
limSendAssocRspMgmtFrame(
pMac,
status,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
}
else
{
limLog(pMac, LOGE, FL("RSN Version mismatch. "
"Rejecting Re/Assoc req from "
"STA: "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
/* received Association req frame with RSN IE version wrong */
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_UNSUPPORTED_RSN_IE_VERSION_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
}
else
{
limLog(pMac, LOGW, FL("RSN length not correct. "
"Rejecting Re/Assoc req from STA:"
MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
/* received Association req frame with RSN IE but length is 0 */
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
} /* end - if(pAssocReq->rsnPresent) */
if((!pAssocReq->rsnPresent) && pAssocReq->wpaPresent)
{
// Unpack the WPA IE
if(pAssocReq->wpa.length)
{
if (dot11fUnpackIeWPA(pMac,
&pAssocReq->wpa.info[4], //OUI is not taken care
(pAssocReq->wpa.length - 4),
&Dot11fIEWPA) != DOT11F_PARSE_SUCCESS)
{
limLog(pMac, LOGE, FL("Invalid WPA IE"));
limSendAssocRspMgmtFrame(pMac,
eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
1, pHdr->sa, subType, 0,psessionEntry, NULL);
goto error;
}
/* check the groupwise and pairwise cipher suites */
if(eSIR_SUCCESS != (status = limCheckRxWPAIeMatch(pMac, Dot11fIEWPA, psessionEntry, pAssocReq->HTCaps.present)))
{
limLog(pMac, LOGW, FL("WPA IE mismatch. "
"Rejecting Re/Assoc req from "
"STA: "MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
/* received Association req frame with WPA IE but mismatch */
limSendAssocRspMgmtFrame(
pMac,
status,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}
}
else
{
limLog(pMac, LOGW, FL("WPA len incorrect. "
"Rejecting Re/Assoc req from STA: "
MAC_ADDRESS_STR),
MAC_ADDR_ARRAY(pHdr->sa));
/* received Association req frame with invalid WPA IE */
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_INVALID_INFORMATION_ELEMENT_STATUS,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
goto error;
}/* end - if(pAssocReq->wpa.length) */
} /* end - if(pAssocReq->wpaPresent) */
} /* end of if(psessionEntry->pLimStartBssReq->privacy
&& psessionEntry->pLimStartBssReq->rsnIE->length) */
} /* end of if( ! pAssocReq->wscInfo.present ) */
/**
* Extract 'associated' context for STA, if any.
* This is maintained by DPH and created by LIM.
*/
pStaDs = dphLookupHashEntry(pMac, pHdr->sa, &peerIdx, &psessionEntry->dph.dphHashTable);
/// Extract pre-auth context for the STA, if any.
pStaPreAuthContext = limSearchPreAuthList(pMac, pHdr->sa);
if (pStaDs == NULL)
{
/// Requesting STA is not currently associated
if (peGetCurrentSTAsCount(pMac) == pMac->lim.maxStation)
{
/**
* Maximum number of STAs that AP can handle reached.
* Send Association response to peer MAC entity
*/
limLog(pMac, LOGE, FL("Max Sta count reached : %d"),
pMac->lim.maxStation);
limRejectAssociation(pMac, pHdr->sa,
subType, false,
(tAniAuthType) 0, 0,
false,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
goto error;
}
/// Check if STA is pre-authenticated.
if ((pStaPreAuthContext == NULL) ||
(pStaPreAuthContext &&
(pStaPreAuthContext->mlmState !=
eLIM_MLM_AUTHENTICATED_STATE)))
{
/**
* STA is not pre-authenticated yet requesting
* Re/Association before Authentication.
* OR STA is in the process of getting authenticated
* and sent Re/Association request.
* Send Deauthentication frame with 'prior
* authentication required' reason code.
*/
limSendDeauthMgmtFrame(
pMac,
eSIR_MAC_STA_NOT_PRE_AUTHENTICATED_REASON, //=9
pHdr->sa, psessionEntry, FALSE);
limLog(pMac, LOGE, FL("received %s req on sessionid: %d from STA "
"that does not have pre-auth context"MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc",
psessionEntry->peSessionId,
MAC_ADDR_ARRAY(pHdr->sa));
goto error;
}
/// Delete 'pre-auth' context of STA
authType = pStaPreAuthContext->authType;
/// Store the previous auth frame's seq no
prevAuthSeqno = pStaPreAuthContext->seqNo;
limDeletePreAuthNode(pMac, pHdr->sa);
// All is well. Assign AID (after else part)
} // if (pStaDs == NULL)
else
{
// STA context does exist for this STA
if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
{
/**
* Requesting STA is in some 'transient' state?
* Ignore the Re/Assoc Req frame by incrementing
* debug counter & logging error.
*/
if (subType == LIM_ASSOC)
{
#ifdef WLAN_DEBUG
pMac->lim.gLimNumAssocReqDropInvldState++;
#endif
limLog(pMac, LOGE, FL("received Assoc req in state "
"%d from "), pStaDs->mlmStaContext.mlmState);
}
else
{
#ifdef WLAN_DEBUG
pMac->lim.gLimNumReassocReqDropInvldState++;
#endif
limLog(pMac, LOGE, FL("received ReAssoc req in state %d"
" from "), pStaDs->mlmStaContext.mlmState);
}
limPrintMacAddr(pMac, pHdr->sa, LOG1);
limPrintMlmState(pMac, LOG1, (tLimMlmStates) pStaDs->mlmStaContext.mlmState);
goto error;
} // if (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)
/* STA sent association Request frame while already in
* 'associated' state */
#ifdef WLAN_FEATURE_11W
limLog(pMac, LOG1, FL("Re/Assoc request from station that is already associated"));
limLog(pMac, LOG1, FL("PMF enabled %d, SA Query state %d"), pStaDs->rmfEnabled,
pStaDs->pmfSaQueryState);
if (pStaDs->rmfEnabled)
{
switch (pStaDs->pmfSaQueryState)
{
// start SA Query procedure, respond to Association Request
// with try again later
case DPH_SA_QUERY_NOT_IN_PROGRESS:
/*
* We should reset the retry counter before we start
* the SA query procedure, otherwise in next set of SA query
* procedure we will end up using the stale value.
*/
pStaDs->pmfSaQueryRetryCount = 0;
limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
pHdr->sa, subType, pStaDs,
psessionEntry, NULL);
limSendSaQueryRequestFrame(
pMac, (tANI_U8 *)&(pStaDs->pmfSaQueryCurrentTransId),
pHdr->sa, psessionEntry);
pStaDs->pmfSaQueryStartTransId = pStaDs->pmfSaQueryCurrentTransId;
pStaDs->pmfSaQueryCurrentTransId++;
// start timer for SA Query retry
if (tx_timer_activate(&pStaDs->pmfSaQueryTimer) != TX_SUCCESS)
{
limLog(pMac, LOGE, FL("PMF SA Query timer activation failed!"));
goto error;
}
pStaDs->pmfSaQueryState = DPH_SA_QUERY_IN_PROGRESS;
goto error;
// SA Query procedure still going, respond to Association
// Request with try again later
case DPH_SA_QUERY_IN_PROGRESS:
limSendAssocRspMgmtFrame(pMac, eSIR_MAC_TRY_AGAIN_LATER, 1,
pHdr->sa, subType, 0, psessionEntry,
NULL);
goto error;
// SA Query procedure timed out, accept Association Request
// normally
case DPH_SA_QUERY_TIMED_OUT:
pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
break;
}
}
#endif
/* no change in the capability so drop the frame */
if ((VOS_TRUE == vos_mem_compare(&pStaDs->mlmStaContext.capabilityInfo,
&pAssocReq->capabilityInfo,
sizeof(tSirMacCapabilityInfo)))&&
(subType == LIM_ASSOC))
{
limLog(pMac, LOGE, FL(" Received Assoc req in state %d STAid=%d"),
pStaDs->mlmStaContext.mlmState,peerIdx);
goto error;
}
else
{
/**
* STA sent Re/association Request frame while already in
* 'associated' state. Update STA capabilities and
* send Association response frame with same AID
*/
limLog(pMac, LOG1, FL("Received Assoc req from STA already connected"
" UpdateConext"));
pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
if (pStaPreAuthContext &&
(pStaPreAuthContext->mlmState ==
eLIM_MLM_AUTHENTICATED_STATE))
{
/// STA has triggered pre-auth again
authType = pStaPreAuthContext->authType;
limDeletePreAuthNode(pMac, pHdr->sa);
}
else
authType = pStaDs->mlmStaContext.authType;
updateContext = true;
if (dphInitStaState(pMac, pHdr->sa, peerIdx, true, &psessionEntry->dph.dphHashTable)
== NULL)
{
limLog(pMac, LOGE, FL("could not Init STAid=%d"), peerIdx);
goto error;
}
}
goto sendIndToSme;
} // end if (lookup for STA in perStaDs fails)
// check if sta is allowed per QoS AC rules
//if (pMac->dph.gDphQosEnabled || pMac->dph.gDphWmeEnabled)
limGetWmeMode(psessionEntry, &wmeMode);
if ((qosMode == eHAL_SET) || (wmeMode == eHAL_SET))
{
// for a qsta, check if the requested Traffic spec
// is admissible
// for a non-qsta check if the sta can be admitted
if (pAssocReq->addtsPresent)
{
tANI_U8 tspecIdx = 0; //index in the sch tspec table.
if (limAdmitControlAddTS(pMac, pHdr->sa, &(pAssocReq->addtsReq),
&(pAssocReq->qosCapability), 0, false, NULL, &tspecIdx, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL("AdmitControl: TSPEC rejected"));
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
#ifdef WLAN_DEBUG
pMac->lim.gLimNumAssocReqDropACRejectTS++;
#endif
goto error;
}
}
else if (limAdmitControlAddSta(pMac, pHdr->sa, false)
!= eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL("AdmitControl: Sta rejected"));
limSendAssocRspMgmtFrame(
pMac,
eSIR_MAC_QAP_NO_BANDWIDTH_REASON,
1,
pHdr->sa,
subType, 0,psessionEntry, NULL);
#ifdef WLAN_DEBUG
pMac->lim.gLimNumAssocReqDropACRejectSta++;
#endif
goto error;
}
// else all ok
limLog(pMac, LOG1, FL("AdmitControl: Sta OK!"));
}
/**
* STA is Associated !
*/
limLog(pMac, LOGE, FL("Received %s Req successful from "MAC_ADDRESS_STR),
(LIM_ASSOC == subType) ? "Assoc" : "ReAssoc", MAC_ADDR_ARRAY(pHdr->sa));
/**
* AID for this association will be same as the peer Index used in DPH table.
* Assign unused/least recently used peer Index from perStaDs.
* NOTE: limAssignPeerIdx() assigns AID values ranging
* between 1 - cfg_item(WNI_CFG_ASSOC_STA_LIMIT)
*/
peerIdx = limAssignPeerIdx(pMac, psessionEntry);
if (!peerIdx)
{
// Could not assign AID
// Reject association
limLog(pMac, LOGE, FL("PeerIdx not avaialble. Reject associaton"));
limRejectAssociation(pMac, pHdr->sa,
subType, true, authType,
peerIdx, false,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
goto error;
}
/**
* Add an entry to hash table maintained by DPH module
*/
pStaDs = dphAddHashEntry(pMac, pHdr->sa, peerIdx, &psessionEntry->dph.dphHashTable);
if (pStaDs == NULL)
{
// Could not add hash table entry at DPH
limLog(pMac, LOGE,
FL("could not add hash entry at DPH for aid=%d, MacAddr:"
MAC_ADDRESS_STR),
peerIdx,MAC_ADDR_ARRAY(pHdr->sa));
// Release AID
limReleasePeerIdx(pMac, peerIdx, psessionEntry);
limRejectAssociation(pMac, pHdr->sa,
subType, true, authType, peerIdx, false,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
goto error;
}
/// Store the previous auth frame's seq no
if (prevAuthSeqno != 0xFFFF)
{
pStaDs->PrevAuthSeqno = prevAuthSeqno;
}
/// Store the current assoc seq no
pStaDs->PrevAssocSeqno = ((pHdr->seqControl.seqNumHi << 4) |
(pHdr->seqControl.seqNumLo));
limLog(pMac, LOG1, FL("Prev auth seq no %d Prev Assoc seq no. %d"),
pStaDs->PrevAuthSeqno, pStaDs->PrevAssocSeqno);
sendIndToSme:
psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
pStaDs->mlmStaContext.htCapability = pAssocReq->HTCaps.present;
#ifdef WLAN_FEATURE_11AC
pStaDs->mlmStaContext.vhtCapability = pAssocReq->VHTCaps.present;
#endif
pStaDs->qos.addtsPresent = (pAssocReq->addtsPresent==0) ? false : true;
pStaDs->qos.addts = pAssocReq->addtsReq;
pStaDs->qos.capability = pAssocReq->qosCapability;
pStaDs->versionPresent = 0;
/* short slot and short preamble should be updated before doing limaddsta */
pStaDs->shortPreambleEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortPreamble;
pStaDs->shortSlotTimeEnabled = (tANI_U8)pAssocReq->capabilityInfo.shortSlotTime;
if (pAssocReq->propIEinfo.versionPresent) //update STA version info
{
pStaDs->versionPresent = 1;
pStaDs->version = pAssocReq->propIEinfo.version;
}
pStaDs->propCapability = 0;
if (pAssocReq->propIEinfo.capabilityPresent)
{
if (sirGetCfgPropCaps(pMac, &pStaDs->propCapability))
pStaDs->propCapability &= pAssocReq->propIEinfo.capability;
}
pStaDs->valid = 0;
pStaDs->mlmStaContext.authType = authType;
pStaDs->staType = STA_ENTRY_PEER;
//TODO: If listen interval is more than certain limit, reject the association.
//Need to check customer requirements and then implement.
pStaDs->mlmStaContext.listenInterval = pAssocReq->listenInterval;
pStaDs->mlmStaContext.capabilityInfo = pAssocReq->capabilityInfo;
/* The following count will be used to knock-off the station if it doesn't
* come back to receive the buffered data. The AP will wait for numTimSent number
* of beacons after sending TIM information for the station, before assuming that
* the station is no more associated and disassociates it
*/
/** timWaitCount is used by PMM for monitoring the STA's in PS for LINK*/
pStaDs->timWaitCount = (tANI_U8)GET_TIM_WAIT_COUNT(pAssocReq->listenInterval);
/** Initialise the Current successful MPDU's tranfered to this STA count as 0 */
pStaDs->curTxMpduCnt = 0;
if(IS_DOT11_MODE_HT(psessionEntry->dot11mode) &&
(pAssocReq->HTCaps.present))
{
pStaDs->htGreenfield = (tANI_U8)pAssocReq->HTCaps.greenField;
pStaDs->htAMpduDensity = pAssocReq->HTCaps.mpduDensity;
pStaDs->htDsssCckRate40MHzSupport = (tANI_U8)pAssocReq->HTCaps.dsssCckMode40MHz;
pStaDs->htLsigTXOPProtection = (tANI_U8)pAssocReq->HTCaps.lsigTXOPProtection;
pStaDs->htMaxAmsduLength = (tANI_U8)pAssocReq->HTCaps.maximalAMSDUsize;
pStaDs->htMaxRxAMpduFactor = pAssocReq->HTCaps.maxRxAMPDUFactor;
pStaDs->htMIMOPSState = pAssocReq->HTCaps.mimoPowerSave;
/* pAssocReq will be copied to psessionEntry->parsedAssocReq later */
/* check whether AP is enabled with shortGI */
if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val) !=
eSIR_SUCCESS) {
limLog(pMac, LOGE,
FL("could not retrieve shortGI 20Mhz CFG"));
goto error;
}
if (val) {
pStaDs->htShortGI20Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI20MHz;
} else {
/* Unset htShortGI20Mhz in ht_caps*/
pAssocReq->HTCaps.shortGI20MHz = 0;
pStaDs->htShortGI20Mhz = 0;
}
if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val) !=
eSIR_SUCCESS) {
limLog(pMac, LOGE,
FL("could not retrieve shortGI 40Mhz CFG"));
goto error;
}
if (val) {
pStaDs->htShortGI40Mhz = (tANI_U8)pAssocReq->HTCaps.shortGI40MHz;
} else {
/* Unset htShortGI40Mhz in ht_caps */
pAssocReq->HTCaps.shortGI40MHz = 0;
pStaDs->htShortGI40Mhz = 0;
}
pStaDs->htSupportedChannelWidthSet = (tANI_U8)pAssocReq->HTCaps.supportedChannelWidthSet;
/* peer just follows AP; so when we are softAP/GO, we just store our session entry's secondary channel offset here in peer INFRA STA
* However, if peer's 40MHz channel width support is disabled then secondary channel will be zero
*/
pStaDs->htSecondaryChannelOffset = (pStaDs->htSupportedChannelWidthSet)?psessionEntry->htSecondaryChannelOffset:0;
#ifdef WLAN_FEATURE_11AC
if(pAssocReq->operMode.present)
{
pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pAssocReq->operMode.chanWidth == eHT_CHANNEL_WIDTH_80MHZ) ? WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ : WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ);
pStaDs->htSupportedChannelWidthSet = (tANI_U8)(pAssocReq->operMode.chanWidth ? eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ);
}
else if (pAssocReq->VHTCaps.present)
{
// Check if STA has enabled it's channel bonding mode.
// If channel bonding mode is enabled, we decide based on SAP's current configuration.
// else, we set it to VHT20.
pStaDs->vhtSupportedChannelWidthSet = (tANI_U8)((pStaDs->htSupportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) ?
WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ :
psessionEntry->vhtTxChannelWidthSet );
}
// Lesser among the AP and STA bandwidth of operation.
pStaDs->htSupportedChannelWidthSet =
(pStaDs->htSupportedChannelWidthSet < psessionEntry->htSupportedChannelWidthSet) ?
pStaDs->htSupportedChannelWidthSet : psessionEntry->htSupportedChannelWidthSet ;
#endif
pStaDs->baPolicyFlag = 0xFF;
pStaDs->htLdpcCapable = (tANI_U8)pAssocReq->HTCaps.advCodingCap;
}
if(pAssocReq->VHTCaps.present)
{
pStaDs->vhtLdpcCapable = (tANI_U8)pAssocReq->VHTCaps.ldpcCodingCap;
}
#ifdef WLAN_FEATURE_11AC
if (limPopulateMatchingRateSet(pMac,
pStaDs,
&(pAssocReq->supportedRates),
&(pAssocReq->extendedRates),
pAssocReq->HTCaps.supportedMCSSet,
&(pAssocReq->propIEinfo.propRates),
psessionEntry , &pAssocReq->VHTCaps)
!= eSIR_SUCCESS)
#else
if (limPopulateMatchingRateSet(pMac,
pStaDs,
&(pAssocReq->supportedRates),
&(pAssocReq->extendedRates),
pAssocReq->HTCaps.supportedMCSSet,
&(pAssocReq->propIEinfo.propRates), psessionEntry) != eSIR_SUCCESS)
#endif
{
// Could not update hash table entry at DPH with rateset
limLog(pMac, LOGE,
FL("could not update hash entry at DPH for aid=%d, MacAddr: "
MAC_ADDRESS_STR),
peerIdx, MAC_ADDR_ARRAY(pHdr->sa));
// Release AID
limReleasePeerIdx(pMac, peerIdx, psessionEntry);
limRejectAssociation(pMac, pHdr->sa,
subType, true, authType, peerIdx, true,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
goto error;
}
vos_mem_copy((tANI_U8 *) &pStaDs->mlmStaContext.propRateSet,
(tANI_U8 *) &(pAssocReq->propIEinfo.propRates),
pAssocReq->propIEinfo.propRates.numPropRates + 1);
/// Add STA context at MAC HW (BMU, RHP & TFP)
pStaDs->qosMode = eANI_BOOLEAN_FALSE;
pStaDs->lleEnabled = eANI_BOOLEAN_FALSE;
if (pAssocReq->capabilityInfo.qos && (qosMode == eHAL_SET))
{
pStaDs->lleEnabled = eANI_BOOLEAN_TRUE;
pStaDs->qosMode = eANI_BOOLEAN_TRUE;
}
pStaDs->wmeEnabled = eANI_BOOLEAN_FALSE;
pStaDs->wsmEnabled = eANI_BOOLEAN_FALSE;
limGetWmeMode(psessionEntry, &wmeMode);
//if ((! pStaDs->lleEnabled) && assoc.wmeInfoPresent && pMac->dph.gDphWmeEnabled)
if ((! pStaDs->lleEnabled) && pAssocReq->wmeInfoPresent && (wmeMode == eHAL_SET))
{
pStaDs->wmeEnabled = eANI_BOOLEAN_TRUE;
pStaDs->qosMode = eANI_BOOLEAN_TRUE;
limGetWsmMode(psessionEntry, &wsmMode);
/* WMM_APSD - WMM_SA related processing should be separate; WMM_SA and WMM_APSD
can coexist */
if( pAssocReq->WMMInfoStation.present)
{
/* check whether AP supports or not */
if ((psessionEntry->limSystemRole == eLIM_AP_ROLE)
&& (psessionEntry->apUapsdEnable == 0) && (pAssocReq->WMMInfoStation.acbe_uapsd
|| pAssocReq->WMMInfoStation.acbk_uapsd
|| pAssocReq->WMMInfoStation.acvo_uapsd
|| pAssocReq->WMMInfoStation.acvi_uapsd))
{
/**
* Received Re/Association Request from
* STA when UPASD is not supported.
*/
limLog( pMac, LOGE, FL( "AP do not support UAPSD so reply "
"to STA accordingly" ));
/* update UAPSD and send it to LIM to add STA */
pStaDs->qos.capability.qosInfo.acbe_uapsd = 0;
pStaDs->qos.capability.qosInfo.acbk_uapsd = 0;
pStaDs->qos.capability.qosInfo.acvo_uapsd = 0;
pStaDs->qos.capability.qosInfo.acvi_uapsd = 0;
pStaDs->qos.capability.qosInfo.maxSpLen = 0;
}
else
{
/* update UAPSD and send it to LIM to add STA */
pStaDs->qos.capability.qosInfo.acbe_uapsd = pAssocReq->WMMInfoStation.acbe_uapsd;
pStaDs->qos.capability.qosInfo.acbk_uapsd = pAssocReq->WMMInfoStation.acbk_uapsd;
pStaDs->qos.capability.qosInfo.acvo_uapsd = pAssocReq->WMMInfoStation.acvo_uapsd;
pStaDs->qos.capability.qosInfo.acvi_uapsd = pAssocReq->WMMInfoStation.acvi_uapsd;
pStaDs->qos.capability.qosInfo.maxSpLen = pAssocReq->WMMInfoStation.max_sp_length;
}
}
//if (assoc.wsmCapablePresent && pMac->dph.gDphWsmEnabled)
if (pAssocReq->wsmCapablePresent && (wsmMode == eHAL_SET))
pStaDs->wsmEnabled = eANI_BOOLEAN_TRUE;
}
// Re/Assoc Response frame to requesting STA
pStaDs->mlmStaContext.subType = subType;
if (pAssocReq->propIEinfo.aniIndicator)
pStaDs->aniPeer = 1;
#ifdef WLAN_FEATURE_11W
pStaDs->rmfEnabled = (pmfConnection) ? 1 : 0;
pStaDs->pmfSaQueryState = DPH_SA_QUERY_NOT_IN_PROGRESS;
timerId.fields.sessionId = psessionEntry->peSessionId;
timerId.fields.peerIdx = peerIdx;
if (wlan_cfgGetInt(pMac, WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL,
&retryInterval) != eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL("Could not retrieve PMF SA Query retry interval value"));
limRejectAssociation(pMac, pHdr->sa,
subType, true, authType,
peerIdx, false,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
goto error;
}
if (WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STAMIN > retryInterval)
{
retryInterval = WNI_CFG_PMF_SA_QUERY_RETRY_INTERVAL_STADEF;
}
if (tx_timer_create(&pStaDs->pmfSaQueryTimer, "PMF SA Query timer",
limPmfSaQueryTimerHandler, timerId.value,
SYS_MS_TO_TICKS((retryInterval * 1024) / 1000),
0, TX_NO_ACTIVATE) != TX_SUCCESS)
{
limLog(pMac, LOGE, FL("could not create PMF SA Query timer"));
limRejectAssociation(pMac, pHdr->sa,
subType, true, authType,
peerIdx, false,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
goto error;
}
#endif
// BTAMP: Storing the parsed assoc request in the psessionEntry array
psessionEntry->parsedAssocReq[pStaDs->assocId] = pAssocReq;
/* BTAMP: If STA context already exist (ie. updateContext = 1)
* for this STA, then we should delete the old one, and add
* the new STA. This is taken care of in the limDelSta() routine.
*
* Prior to BTAMP, we were setting this flag so that when
* PE receives SME_ASSOC_CNF, and if this flag is set, then
* PE shall delete the old station and then add. But now in
* BTAMP, we're directly adding station before waiting for
* SME_ASSOC_CNF, so we can do this now.
*/
if (!updateContext)
{
pStaDs->mlmStaContext.updateContext = 0;
// BTAMP: Add STA context at HW - issue WDA_ADD_STA_REQ to HAL
if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL("could not Add STA with assocId=%d"),
pStaDs->assocId);
limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType,
true, pStaDs->mlmStaContext.authType, pStaDs->assocId, true,
(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
goto error;
}
}
else
{
pStaDs->mlmStaContext.updateContext = 1;
mlmPrevState = pStaDs->mlmStaContext.mlmState;
/* As per the HAL/FW needs the reassoc req need not be calling limDelSta */
if(subType != LIM_REASSOC)
{
//we need to set the mlmState here in order differentiate in limDelSta.
pStaDs->mlmStaContext.mlmState = eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE;
if(limDelSta(pMac, pStaDs, true, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL("could not DEL STA with assocId=%d staId %d"),
pStaDs->assocId, pStaDs->staIndex);
limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_UNSPEC_FAILURE_STATUS, psessionEntry);
//Restoring the state back.
pStaDs->mlmStaContext.mlmState = mlmPrevState;
pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
goto error;
}
}
else
{
/* mlmState is changed in limAddSta context */
/* use the same AID, already allocated */
if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS)
{
limLog(pMac, LOGE, FL( "Could not AddSta with assocId= %d staId %d"),
pStaDs->assocId, pStaDs->staIndex);
limRejectAssociation( pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType,
pStaDs->assocId, true,(tSirResultCodes) eSIR_MAC_WME_REFUSED_STATUS, psessionEntry);
//Restoring the state back.
pStaDs->mlmStaContext.mlmState = mlmPrevState;
pAssocReq = psessionEntry->parsedAssocReq[pStaDs->assocId];
goto error;
}
}
}
return;
error:
if (pAssocReq != NULL)
{
if ( pAssocReq->assocReqFrame )
{
vos_mem_free(pAssocReq->assocReqFrame);
pAssocReq->assocReqFrame = NULL;
}
vos_mem_free(pAssocReq);
}
/* If it is not duplicate Assoc request then only make to Null */
if ((pStaDs != NULL) &&
(pStaDs->mlmStaContext.mlmState != eLIM_MLM_WT_ADD_STA_RSP_STATE))
psessionEntry->parsedAssocReq[pStaDs->assocId] = NULL;
return;
} /*** end limProcessAssocReqFrame() ***/
/**---------------------------------------------------------------
\fn limSendMlmAssocInd
\brief This function sends either LIM_MLM_ASSOC_IND
\ or LIM_MLM_REASSOC_IND to SME.
\
\param pMac
\param *pStaDs - Station DPH hash entry
\param psessionEntry - PE session entry
\return None
* ?????? How do I get
* - subtype =====> psessionEntry->parsedAssocReq.reassocRequest
* - aid =====> pStaDs->assocId
* - pHdr->sa =====> pStaDs->staAddr
* - authType
* - pHdr->seqControl =====> no longer needed
* - pStaDs
------------------------------------------------------------------*/
void limSendMlmAssocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psessionEntry)
{
tpLimMlmAssocInd pMlmAssocInd = NULL;
tpLimMlmReassocInd pMlmReassocInd;
tpSirAssocReq pAssocReq;
tANI_U16 temp;
tANI_U32 phyMode;
tANI_U8 subType;
tANI_U8 *wpsIe = NULL;
tANI_U32 tmp;
// tANI_U16 statusCode;
tANI_U16 i, j=0;
// Get a copy of the already parsed Assoc Request
pAssocReq = (tpSirAssocReq) psessionEntry->parsedAssocReq[pStaDs->assocId];
// Get the phyMode
limGetPhyMode(pMac, &phyMode, psessionEntry);
// Extract pre-auth context for the peer BTAMP-STA, if any.
// Determiine if its Assoc or ReAssoc Request
if (pAssocReq->reassocRequest == 1)
subType = LIM_REASSOC;
else
subType = LIM_ASSOC;
limLog(pMac, LOG1, FL("Sessionid %d ssid %s subtype %d Associd %d staAddr "
MAC_ADDRESS_STR), psessionEntry->peSessionId, pAssocReq->ssId.ssId,
subType,pStaDs->assocId,MAC_ADDR_ARRAY(pStaDs->staAddr));
if (subType == LIM_ASSOC || subType == LIM_REASSOC)
{
temp = sizeof(tLimMlmAssocInd);
pMlmAssocInd = vos_mem_malloc(temp);
if (NULL == pMlmAssocInd)
{
limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry);
limLog(pMac, LOGP, FL("AllocateMemory failed for pMlmAssocInd"));
return;
}
vos_mem_set(pMlmAssocInd, temp ,0);
vos_mem_copy((tANI_U8 *)pMlmAssocInd->peerMacAddr,
(tANI_U8 *)pStaDs->staAddr, sizeof(tSirMacAddr));
pMlmAssocInd->aid = pStaDs->assocId;
vos_mem_copy((tANI_U8 *)&pMlmAssocInd->ssId,
(tANI_U8 *)&(pAssocReq->ssId), pAssocReq->ssId.length + 1);
pMlmAssocInd->sessionId = psessionEntry->peSessionId;
pMlmAssocInd->authType = pStaDs->mlmStaContext.authType;
pMlmAssocInd->capabilityInfo = pAssocReq->capabilityInfo;
// Fill in RSN IE information
pMlmAssocInd->rsnIE.length = 0;
// if WPS IE is present, ignore RSN IE
if (pAssocReq->addIEPresent && pAssocReq->addIE.length ) {
wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length);
}
if (pAssocReq->rsnPresent && (NULL == wpsIe))
{
limLog(pMac, LOG2, FL("Assoc Req RSN IE len = %d"),
pAssocReq->rsn.length);
pMlmAssocInd->rsnIE.length = 2 + pAssocReq->rsn.length;
pMlmAssocInd->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID;
pMlmAssocInd->rsnIE.rsnIEdata[1] = pAssocReq->rsn.length;
vos_mem_copy(&pMlmAssocInd->rsnIE.rsnIEdata[2],
pAssocReq->rsn.info,
pAssocReq->rsn.length);
}
// Fill in 802.11h related info
if (pAssocReq->powerCapabilityPresent && pAssocReq->supportedChannelsPresent)
{
pMlmAssocInd->spectrumMgtIndicator = eSIR_TRUE;
pMlmAssocInd->powerCap.minTxPower = pAssocReq->powerCapability.minTxPower;
pMlmAssocInd->powerCap.maxTxPower = pAssocReq->powerCapability.maxTxPower;
limConvertSupportedChannels(pMac, pMlmAssocInd, pAssocReq);
}
else
pMlmAssocInd->spectrumMgtIndicator = eSIR_FALSE;
/* This check is to avoid extra Sec IEs present incase of WPS */
if (pAssocReq->wpaPresent && (NULL == wpsIe))
{
if((pMlmAssocInd->rsnIE.length + pAssocReq->wpa.length) >= SIR_MAC_MAX_IE_LENGTH)
{
PELOGE(limLog(pMac, LOGE, FL("rsnIEdata index out of bounds %d"),
pMlmAssocInd->rsnIE.length);)
vos_mem_free(pMlmAssocInd);
return;
}
pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length] = SIR_MAC_WPA_EID;
pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length + 1] = pAssocReq->wpa.length;
vos_mem_copy(&pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length + 2],
pAssocReq->wpa.info,
pAssocReq->wpa.length);
pMlmAssocInd->rsnIE.length += 2 + pAssocReq->wpa.length;
}
pMlmAssocInd->addIE.length = 0;
if (pAssocReq->addIEPresent)
{
vos_mem_copy(&pMlmAssocInd->addIE.addIEdata,
pAssocReq->addIE.addIEdata,
pAssocReq->addIE.length);
pMlmAssocInd->addIE.length = pAssocReq->addIE.length;
}
if(pAssocReq->wmeInfoPresent)
{
if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WME_ENABLED, &tmp) != eSIR_SUCCESS)
limLog(pMac, LOGP, FL("wlan_cfgGetInt failed for id %d"),
WNI_CFG_WME_ENABLED );
/* check whether AP is enabled with WMM */
if(tmp)
{
pMlmAssocInd->WmmStaInfoPresent = 1;
}
else
{
pMlmAssocInd->WmmStaInfoPresent= 0;
}
/* Note: we are not rejecting association here because IOT will fail */
}
#ifdef WLAN_FEATURE_AP_HT40_24G
if(pAssocReq->HTCaps.present)
{
limLog(pMac, LOGW, FL("HT40MHzInto: %d"),
pAssocReq->HTCaps.stbcControlFrame);
pMlmAssocInd->HT40MHzIntoPresent =
pAssocReq->HTCaps.stbcControlFrame;
}
#endif
// Required for indicating the frames to upper layer
pMlmAssocInd->assocReqLength = pAssocReq->assocReqFrameLength;
pMlmAssocInd->assocReqPtr = pAssocReq->assocReqFrame;
pMlmAssocInd->beaconPtr = psessionEntry->beacon;
pMlmAssocInd->beaconLength = psessionEntry->bcnLen;
pMlmAssocInd->chan_info.chan_id = psessionEntry->currentOperChannel;
if (psessionEntry->limRFBand == SIR_BAND_2_4_GHZ) {
if (psessionEntry->vhtCapability && pAssocReq->VHTCaps.present) {
pMlmAssocInd->chan_info.info = MODE_11AC_VHT20_2G;
pMlmAssocInd->VHTCaps = pAssocReq->VHTCaps;
} else if (psessionEntry->htCapability &&
pAssocReq->HTCaps.present) {
pMlmAssocInd->chan_info.info = MODE_11NG_HT20;
pMlmAssocInd->HTCaps = pAssocReq->HTCaps;
} else if (pStaDs->supportedRates.llaRates[0]) {
pMlmAssocInd->chan_info.info = MODE_11G;
} else {
pMlmAssocInd->chan_info.info = MODE_11B;
}
} else {
if (psessionEntry->vhtCapability && pAssocReq->VHTCaps.present) {
if ((psessionEntry->vhtTxChannelWidthSet ==
eHT_CHANNEL_WIDTH_80MHZ) &&
pAssocReq->HTCaps.supportedChannelWidthSet) {
pMlmAssocInd->chan_info.info = MODE_11AC_VHT80;
} else if ((psessionEntry->vhtTxChannelWidthSet ==
eHT_CHANNEL_WIDTH_40MHZ) &&
pAssocReq->HTCaps.supportedChannelWidthSet) {
pMlmAssocInd->chan_info.info = MODE_11AC_VHT40;
} else
pMlmAssocInd->chan_info.info = MODE_11AC_VHT20;
pMlmAssocInd->VHTCaps = pAssocReq->VHTCaps;
} else if (psessionEntry->htCapability &&
pAssocReq->HTCaps.present) {
if ((psessionEntry->vhtTxChannelWidthSet ==
eHT_CHANNEL_WIDTH_40MHZ) &&
pAssocReq->HTCaps.supportedChannelWidthSet) {
pMlmAssocInd->chan_info.info = MODE_11NA_HT40;
} else
pMlmAssocInd->chan_info.info = MODE_11NA_HT20;
pMlmAssocInd->HTCaps = pAssocReq->HTCaps;
} else
pMlmAssocInd->chan_info.info = MODE_11A;
}
pMlmAssocInd->ch_width = eHT_CHANNEL_WIDTH_20MHZ;
if (pStaDs->mlmStaContext.htCapability)
pMlmAssocInd->ch_width = pStaDs->htSupportedChannelWidthSet ?
eHT_CHANNEL_WIDTH_40MHZ : eHT_CHANNEL_WIDTH_20MHZ;
pMlmAssocInd->rate_flags =
limGetMaxRateFlags(pStaDs, psessionEntry);
limPostSmeMessage(pMac, LIM_MLM_ASSOC_IND, (tANI_U32 *) pMlmAssocInd);
vos_mem_free(pMlmAssocInd);
}
else
{
// If its of Reassociation Request, then post LIM_MLM_REASSOC_IND
temp = sizeof(tLimMlmReassocInd);
pMlmReassocInd = vos_mem_malloc(temp);
if (NULL == pMlmReassocInd)
{
limLog(pMac, LOGP, FL("call to AllocateMemory failed for "
"pMlmReassocInd"));
limReleasePeerIdx(pMac, pStaDs->assocId, psessionEntry);
return;
}
vos_mem_set(pMlmReassocInd, temp, 0);
vos_mem_copy((tANI_U8 *) pMlmReassocInd->peerMacAddr,
(tANI_U8 *)pStaDs->staAddr, sizeof(tSirMacAddr));
vos_mem_copy((tANI_U8 *) pMlmReassocInd->currentApAddr,
(tANI_U8 *)&(pAssocReq->currentApAddr), sizeof(tSirMacAddr));
pMlmReassocInd->aid = pStaDs->assocId;
pMlmReassocInd->authType = pStaDs->mlmStaContext.authType;
vos_mem_copy((tANI_U8 *)&pMlmReassocInd->ssId,
(tANI_U8 *)&(pAssocReq->ssId), pAssocReq->ssId.length + 1);
if (pAssocReq->propIEinfo.aniIndicator)
pStaDs->aniPeer = 1;
pMlmReassocInd->capabilityInfo = pAssocReq->capabilityInfo;
pMlmReassocInd->rsnIE.length = 0;
if (pAssocReq->addIEPresent && pAssocReq->addIE.length )
wpsIe = limGetWscIEPtr(pMac, pAssocReq->addIE.addIEdata, pAssocReq->addIE.length);
if (pAssocReq->rsnPresent && (NULL == wpsIe))
{
limLog(pMac, LOG2, FL("Assoc Req: RSN IE length = %d"),
pAssocReq->rsn.length);
pMlmReassocInd->rsnIE.length = 2 + pAssocReq->rsn.length;
pMlmReassocInd->rsnIE.rsnIEdata[0] = SIR_MAC_RSN_EID;
pMlmReassocInd->rsnIE.rsnIEdata[1] = pAssocReq->rsn.length;
vos_mem_copy(&pMlmReassocInd->rsnIE.rsnIEdata[2],
pAssocReq->rsn.info, pAssocReq->rsn.length);
}
// 802.11h support
if (pAssocReq->powerCapabilityPresent && pAssocReq->supportedChannelsPresent)
{
pMlmReassocInd->spectrumMgtIndicator = eSIR_TRUE;
pMlmReassocInd->powerCap.minTxPower = pAssocReq->powerCapability.minTxPower;
pMlmReassocInd->powerCap.maxTxPower = pAssocReq->powerCapability.maxTxPower;
pMlmReassocInd->supportedChannels.numChnl = (tANI_U8)(pAssocReq->supportedChannels.length / 2);
limLog(pMac, LOG1,
FL("Sending Reassoc Ind: spectrum ON, minPwr %d, "
"maxPwr %d, numChnl %d"),
pMlmReassocInd->powerCap.minTxPower,
pMlmReassocInd->powerCap.maxTxPower,
pMlmReassocInd->supportedChannels.numChnl);
for(i=0; i < pMlmReassocInd->supportedChannels.numChnl; i++)
{
pMlmReassocInd->supportedChannels.channelList[i] = pAssocReq->supportedChannels.supportedChannels[j];
limLog(pMac, LOG1, FL("Sending ReassocInd: chn[%d] = %d "),
i, pMlmReassocInd->supportedChannels.channelList[i]);
j+=2;
}
}
else
pMlmReassocInd->spectrumMgtIndicator = eSIR_FALSE;
/* This check is to avoid extra Sec IEs present incase of WPS */
if (pAssocReq->wpaPresent && (NULL == wpsIe))
{
limLog(pMac, LOG2, FL("Received WPA IE length in Assoc Req is %d"),
pAssocReq->wpa.length);
pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length] = SIR_MAC_WPA_EID;
pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length + 1] = pAssocReq->wpa.length;
vos_mem_copy(&pMlmReassocInd->rsnIE.rsnIEdata[pMlmReassocInd->rsnIE.length + 2],
pAssocReq->wpa.info,
pAssocReq->wpa.length);
pMlmReassocInd->rsnIE.length += 2 + pAssocReq->wpa.length;
}
pMlmReassocInd->addIE.length = 0;
if (pAssocReq->addIEPresent)
{
vos_mem_copy(&pMlmReassocInd->addIE.addIEdata,
pAssocReq->addIE.addIEdata,
pAssocReq->addIE.length);
pMlmReassocInd->addIE.length = pAssocReq->addIE.length;
}
if(pAssocReq->wmeInfoPresent)
{
if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WME_ENABLED, &tmp) != eSIR_SUCCESS)
limLog(pMac, LOGP, FL("wlan_cfgGetInt failed for id %d"),
WNI_CFG_WME_ENABLED );
/* check whether AP is enabled with WMM */
if(tmp)
{
pMlmReassocInd->WmmStaInfoPresent = 1;
}
else
{
pMlmReassocInd->WmmStaInfoPresent = 0;
}
/* Note: we are not rejecting Re-association here because IOT will fail */
}
#ifdef WLAN_FEATURE_AP_HT40_24G
if(pAssocReq->HTCaps.present)
{
limLog(pMac, LOGW, FL("RASSOC HT40MHzInto: %d"),
pAssocReq->HTCaps.stbcControlFrame);
pMlmReassocInd->HT40MHzIntoPresent =
pAssocReq->HTCaps.stbcControlFrame;
}
#endif
// Required for indicating the frames to upper layer
pMlmReassocInd->assocReqLength = pAssocReq->assocReqFrameLength;
pMlmReassocInd->assocReqPtr = pAssocReq->assocReqFrame;
pMlmReassocInd->beaconPtr = psessionEntry->beacon;
pMlmReassocInd->beaconLength = psessionEntry->bcnLen;
limPostSmeMessage(pMac, LIM_MLM_REASSOC_IND, (tANI_U32 *) pMlmReassocInd);
vos_mem_free(pMlmReassocInd);
}
return;
} /*** end limSendMlmAssocInd() ***/