MT7601u/src/sta/p2pcli.c
Murat Demirtas 612db32659 FIXED
2016-10-30 14:40:00 +00:00

2213 lines
65 KiB
C

/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ap_apcli.c
Abstract:
Support AP-Client function.
Note:
1. Call RT28xx_ApCli_Init() in init function and
call RT28xx_ApCli_Remove() in close function
2. MAC of ApCli-interface is initialized in RT28xx_ApCli_Init()
3. ApCli index (0) of different rx packet is got in
APHandleRxDoneInterrupt() by using FromWhichBSSID = pEntry->apidx;
Or FromWhichBSSID = BSS0;
4. ApCli index (0) of different tx packet is assigned in
MBSS_VirtualIF_PacketSend() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID()
5. ApCli index (0) of different interface is got in APHardTransmit() by using
RTMP_GET_PACKET_IF()
6. ApCli index (0) of IOCTL command is put in pAd->OS_Cookie->ioctl_if
8. The number of ApCli only can be 1
9. apcli convert engine subroutines, we should just take care data packet.
Revision History:
Who When What
-------------- ---------- ----------------------------------------------
Shiang, Fonchi 02-13-2007 created
*/
#ifdef P2P_SUPPORT
#include "rt_config.h"
/* --------------------------------- Private -------------------------------- */
INT ApCliIfLookUp(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pAddr)
{
SHORT i;
SHORT ifIndex = -1;
do
{
for(i = 0; i < MAX_APCLI_NUM; i++)
{
if( MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].CurrentAddress, pAddr))
{
ifIndex = i;
DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCliIfIndex = %d\n", __FUNCTION__, ifIndex));
break;
}
}
} while (FALSE);
return ifIndex;
}
BOOLEAN isValidApCliIf(
SHORT ifIndex)
{
if((ifIndex >= 0) && (ifIndex < MAX_APCLI_NUM))
return TRUE;
else
return FALSE;
}
/*! \brief init the management mac frame header
* \param p_hdr mac header
* \param subtype subtype of the frame
* \param p_ds destination address, don't care if it is a broadcast address
* \return none
* \pre the station has the following information in the pAd->UserCfg
* - bssid
* - station address
* \post
* \note this function initializes the following field
*/
VOID ApCliMgtMacHeaderInit(
IN PRTMP_ADAPTER pAd,
IN OUT PHEADER_802_11 pHdr80211,
IN UCHAR SubType,
IN UCHAR ToDs,
IN PUCHAR pDA,
IN PUCHAR pBssid,
IN USHORT ifIndex)
{
NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
pHdr80211->FC.Type = BTYPE_MGMT;
pHdr80211->FC.SubType = SubType;
pHdr80211->FC.ToDs = ToDs;
COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].CurrentAddress);
COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
}
#ifdef DOT11_N_SUPPORT
/*
========================================================================
Routine Description:
Verify the support rate for HT phy type
Arguments:
pAd Pointer to our adapter
Return Value:
FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
IRQL = PASSIVE_LEVEL
========================================================================
*/
BOOLEAN ApCliCheckHt(
IN PRTMP_ADAPTER pAd,
IN USHORT IfIndex,
IN OUT HT_CAPABILITY_IE *pHtCapability,
IN OUT ADD_HT_INFO_IE *pAddHtInfo)
{
PAPCLI_STRUCT pApCliEntry = NULL;
if (IfIndex >= MAX_APCLI_NUM)
return FALSE;
pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex];
/* If use AMSDU, set flag. */
if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_AMSDU_INUSED);
/* Save Peer Capability */
if (pHtCapability->HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI20_CAPABLE);
if (pHtCapability->HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_SGI40_CAPABLE);
if (pHtCapability->HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (pHtCapability->HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
CLIENT_STATUS_SET_FLAG(pApCliEntry, fCLIENT_STATUS_RDG_CAPABLE);
pApCliEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
if ((pAd->OpMode == OPMODE_STA))
{
}
pAd->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[4] = 0x1;
//2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform<--
switch (pAd->CommonCfg.RxStream)
{
case 1:
pAd->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[1] = 0x00;
pAd->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00;
pAd->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00;
break;
case 2:
pAd->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[2] = 0x00;
pAd->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00;
break;
case 3:
pAd->ApCliMlmeAux.HtCapability.MCSSet[0] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[1] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[2] = 0xff;
pAd->ApCliMlmeAux.HtCapability.MCSSet[3] = 0x00;
break;
}
/* Record the RxMcs of AP */
NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16);
/*
if (pAd->Antenna.field.TxPath == 2) // 2: 2Tx 1: 1Tx
{
pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
}
else
{
pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
}
*/
/* 2008/12/17:KH modified to fix the low throughput of AP-Client on Big-Endian Platform--> */
/* choose smaller setting */
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
/* Send Assoc Req with my HT capability. */
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs;
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
pAd->ApCliMlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
pAd->ApCliMlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
pAd->ApCliMlmeAux.HtCapability.HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity;
pAd->ApCliMlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
if (pAd->CommonCfg.bRdg)
{
pAd->ApCliMlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
}
/*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */
return TRUE;
}
#endif /* DOT11_N_SUPPORT */
VOID ComposeP2PPsPoll(
IN PRTMP_ADAPTER pAd,
IN PAPCLI_STRUCT pApCliEntry)
{
NdisZeroMemory(&pApCliEntry->PsPollFrame, sizeof (PSPOLL_FRAME));
pApCliEntry->PsPollFrame.FC.Type = BTYPE_CNTL;
pApCliEntry->PsPollFrame.FC.SubType = SUBTYPE_PS_POLL;
pApCliEntry->PsPollFrame.Aid = pAd->ApCliMlmeAux.Aid | 0xC000;
COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Bssid, pAd->ApCliMlmeAux.Bssid);
COPY_MAC_ADDR(pApCliEntry->PsPollFrame.Ta, pApCliEntry->CurrentAddress);
}
VOID ComposeP2PNullFrame(
IN PRTMP_ADAPTER pAd,
IN PAPCLI_STRUCT pApCliEntry)
{
NdisZeroMemory(&pApCliEntry->NullFrame, sizeof (HEADER_802_11));
pApCliEntry->NullFrame.FC.Type = BTYPE_DATA;
pApCliEntry->NullFrame.FC.SubType = SUBTYPE_NULL_FUNC;
pApCliEntry->NullFrame.FC.ToDs = 1;
COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr1, pAd->ApCliMlmeAux.Bssid);
COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr2, pApCliEntry->CurrentAddress);
COPY_MAC_ADDR(pApCliEntry->NullFrame.Addr3, pAd->ApCliMlmeAux.Bssid);
}
/*
==========================================================================
Routine Description:
Connected to the BSSID
Arguments:
pAd - Pointer to our adapter
ApCliIdx - Which ApCli interface
Return Value:
FALSE: fail to alloc Mac entry.
Note:
==========================================================================
*/
BOOLEAN ApCliLinkUp(
IN PRTMP_ADAPTER pAd,
IN UCHAR ifIndex)
{
BOOLEAN result = FALSE;
PAPCLI_STRUCT pApCliEntry = NULL;
PMAC_TABLE_ENTRY pMacEntry = NULL;
do
{
if (ifIndex < MAX_APCLI_NUM)
{
DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK UP - IF(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s !!!\n",
ifIndex,
pAd->ApCfg.ApCliTab[ifIndex].AuthMode, GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].AuthMode),
pAd->ApCfg.ApCliTab[ifIndex].WepStatus, GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].WepStatus)));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(apcli%d)!!!\n", ifIndex));
result = FALSE;
break;
}
pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex];
/* Sanity check: This link had existed. */
if (pApCliEntry->Valid)
{
DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : This link had existed - IF(apcli%d)!!!\n", ifIndex));
result = FALSE;
break;
}
/* Insert the Remote AP to our MacTable. */
/*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->MlmeAux.Bssid)); */
pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pAd->ApCliMlmeAux.Bssid),
(ifIndex + MIN_NET_DEVICE_FOR_APCLI), OPMODE_AP, TRUE);
if (pMacEntry)
{
UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES];
PUCHAR pRates = Rates;
UCHAR RatesLen;
UCHAR MaxSupportedRate = 0;
UCHAR P2pIdx = P2P_NOT_FOUND;
DBGPRINT(RT_DEBUG_INFO, ("%s:: Insert MAC Table success. ifIndex = %d.\n", __FUNCTION__, ifIndex));
pMacEntry->Sst = SST_ASSOC;
DBGPRINT(RT_DEBUG_TRACE, ("\n++++++++ %s:: Delete BssSearch Table on Channel = %d. ++++++++\n", __FUNCTION__, pAd->CommonCfg.Channel));
DBGPRINT(RT_DEBUG_TRACE, (" BSSID = [%02x:%02x:%02x:%02x:%02x:%02x]. p2p_bssid = [%02x:%02x:%02x:%02x:%02x:%02x].\n", PRINT_MAC(pAd->ApCliMlmeAux.Bssid), PRINT_MAC(pAd->P2pCfg.Bssid)));
BssTableDeleteEntry(&pAd->ScanTab,
/*pAd->ApCliMlmeAux.Bssid*/pAd->P2pCfg.Bssid,
pAd->CommonCfg.Channel);
if (pApCliEntry->bP2pClient)
{
pMacEntry->bP2pClient = TRUE;
pMacEntry->P2pInfo.P2pClientState = P2PSTATE_CLIENT_ASSOC;
P2pIdx = P2pGroupTabSearch(pAd, pMacEntry->Addr);
if (P2pIdx != P2P_NOT_FOUND)
pMacEntry->P2pInfo.p2pIndex = P2pIdx;
}
else
pMacEntry->bP2pClient = FALSE;
NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime);
pApCliEntry->Valid = TRUE;
pApCliEntry->MacTabWCID = pMacEntry->Aid;
COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pAd->ApCliMlmeAux.Bssid);
pApCliEntry->SsidLen = pAd->ApCliMlmeAux.SsidLen;
NdisMoveMemory(pApCliEntry->Ssid, pAd->ApCliMlmeAux.Ssid, pApCliEntry->SsidLen);
ComposeP2PPsPoll(pAd, pApCliEntry);
ComposeP2PNullFrame(pAd, pApCliEntry);
if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA)
pMacEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED;
else
pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED;
/* Store appropriate RSN_IE for WPA SM negotiation later */
/* If WPAPSK/WPA2SPK mix mode, driver just stores either WPAPSK or WPA2PSK */
/* RSNIE. It depends on the AP-Client's authentication mode to store the corresponding RSNIE. */
if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pAd->ApCliMlmeAux.VarIELen != 0))
{
PUCHAR pVIE;
UCHAR len;
PEID_STRUCT pEid;
pVIE = pAd->ApCliMlmeAux.VarIEs;
len = pAd->ApCliMlmeAux.VarIELen;
while (len > 0)
{
pEid = (PEID_STRUCT) pVIE;
/* For WPA/WPAPSK */
if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
&& (pMacEntry->AuthMode == Ndis802_11AuthModeWPA || pMacEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
{
NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2));
pMacEntry->RSNIE_Len = (pEid->Len + 2);
DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA SM negotiation \n"));
}
/* For WPA2/WPA2PSK */
else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
&& (pMacEntry->AuthMode == Ndis802_11AuthModeWPA2 || pMacEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
{
NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2));
pMacEntry->RSNIE_Len = (pEid->Len + 2);
DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA2 SM negotiation \n"));
}
pVIE += (pEid->Len + 2);
len -= (pEid->Len + 2);
}
}
if (pMacEntry->RSNIE_Len == 0)
{
DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: root-AP has no RSN_IE \n"));
}
else
{
hex_dump("The RSN_IE of root-AP", pMacEntry->RSN_IE, pMacEntry->RSNIE_Len);
}
SupportRate(pAd->ApCliMlmeAux.SupRate, pAd->ApCliMlmeAux.SupRateLen, pAd->ApCliMlmeAux.ExtRate,
pAd->ApCliMlmeAux.ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate);
pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
pMacEntry->RateLen = RatesLen;
set_entry_phy_cfg(pAd, pMacEntry);
pMacEntry->CapabilityInfo = pAd->ApCliMlmeAux.CapabilityInfo;
/* If WEP is enabled, add paiewise and shared key */
if (pApCliEntry->WepStatus == Ndis802_11WEPEnabled)
{
PCIPHER_KEY pKey;
INT idx, BssIdx;
BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex;
for (idx=0; idx < SHARE_KEY_NUM; idx++)
{
pKey = &pApCliEntry->SharedKey[idx];
if (pKey->KeyLen > 0)
{
/* Set key material and cipherAlg to Asic */
RTMP_ASIC_SHARED_KEY_TABLE(pAd,
BssIdx,
idx,
pKey);
if (idx == pApCliEntry->DefaultKeyId)
{
INT cnt;
/* Generate 3-bytes IV randomly for software encryption using */
for(cnt = 0; cnt < LEN_WEP_TSC; cnt++)
pKey->TxTsc[cnt] = RandomByte(pAd);
RTMP_SET_WCID_SEC_INFO(pAd,
BssIdx,
idx,
pKey->CipherAlg,
pMacEntry->Aid,
SHAREDKEYTABLE);
}
}
}
}
#ifdef DOT11_N_SUPPORT
/* If this Entry supports 802.11n, upgrade to HT rate. */
if (pAd->ApCliMlmeAux.HtCapabilityLen != 0)
{
UCHAR j, bitmask; /* k,bitmask; */
CHAR i;
PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&pAd->ApCliMlmeAux.HtCapability;
if ((pAd->ApCliMlmeAux.HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
{
pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
}
else
{
pMacEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
pAd->MacTab.fAnyStationNonGF = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
}
if ((pHtCapability->HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
{
pMacEntry->MaxHTPhyMode.field.BW= BW_40;
pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(pHtCapability->HtCapInfo.ShortGIfor40));
}
else
{
pMacEntry->MaxHTPhyMode.field.BW = BW_20;
pMacEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(pHtCapability->HtCapInfo.ShortGIfor20));
pAd->MacTab.fAnyStation20Only = TRUE;
}
/* find max fixed rate */
pMacEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->ApCfg.ApCliTab[ifIndex].DesiredHtPhyInfo.MCSSet[0],
&pHtCapability->MCSSet[0]);
if (pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS != MCS_AUTO)
{
DBGPRINT(RT_DEBUG_TRACE, ("IF-apcli%d : Desired MCS = %d\n", ifIndex,
pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS));
set_ht_fixed_mcs(pAd, pMacEntry, pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.MCS, pAd->ApCfg.ApCliTab[ifIndex].HTPhyMode.field.MCS);
}
pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
pMacEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity;
pMacEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor;
pMacEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs;
pMacEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize;
pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word;
if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE))
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AMSDU_INUSED);
if (pHtCapability->HtCapInfo.ShortGIfor20)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_SGI20_CAPABLE);
if (pHtCapability->HtCapInfo.ShortGIfor40)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_SGI40_CAPABLE);
if (pHtCapability->HtCapInfo.TxSTBC)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
if (pHtCapability->HtCapInfo.RxSTBC)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
if (pHtCapability->ExtHtCapInfo.PlusHTC)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_HTC_CAPABLE);
if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_RDG_CAPABLE);
if (pHtCapability->ExtHtCapInfo.MCSFeedback == 0x03)
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
NdisMoveMemory(&pMacEntry->HTCapability, &pAd->ApCliMlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE));
NdisMoveMemory(pMacEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16);
}
else
{
pAd->MacTab.fAnyStationIsLegacy = TRUE;
DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n",
RateIdToMbps[pMacEntry->MaxSupportedRate]));
}
#endif /* DOT11_N_SUPPORT */
pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word;
pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate;
if (pAd->ApCfg.ApCliTab[ifIndex].bAutoTxRateSwitch == FALSE)
{
pMacEntry->bAutoTxRateSwitch = FALSE;
/* If the legacy mode is set, overwrite the transmit setting of this entry. */
RTMPUpdateLegacyTxSetting((UCHAR)pAd->ApCfg.ApCliTab[ifIndex].DesiredTransmitSetting.field.FixedTxMode, pMacEntry);
}
else
{
UCHAR TableSize = 0;
pMacEntry->bAutoTxRateSwitch = TRUE;
MlmeSelectTxRateTable(pAd, pMacEntry, &pMacEntry->pTable, &TableSize, &pMacEntry->CurrTxRateIndex);
}
/* It had been set in APStartUp. Don't set again. */
if (!INFRA_ON(pAd))
{
NdisMoveMemory(&(pAd->CommonCfg.APEdcaParm), &(pAd->ApCliMlmeAux.APEdcaParm), sizeof(EDCA_PARM));
AsicSetEdcaParm(pAd, &pAd->CommonCfg.APEdcaParm);
}
/* set this entry WMM capable or not */
if ((pAd->ApCliMlmeAux.APEdcaParm.bValid)
#ifdef DOT11_N_SUPPORT
|| IS_HT_STA(pMacEntry)
#endif /* DOT11_N_SUPPORT */
)
{
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
}
else
{
CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
}
if (pAd->CommonCfg.bAggregationCapable)
{
if ((pAd->CommonCfg.bPiggyBackCapable) && (pAd->ApCliMlmeAux.APRalinkIe & 0x00000003) == 3)
{
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_PIGGYBACK_INUSED);
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE);
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE);
RTMPSetPiggyBack(pAd, TRUE);
DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n"));
}
else if (pAd->ApCliMlmeAux.APRalinkIe & 0x00000001)
{
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE);
DBGPRINT(RT_DEBUG_TRACE, ("Ralink Aggregation\n"));
}
}
pApCliEntry->ApCliBeaconPeriod = pAd->ApCliMlmeAux.BeaconPeriod;
{
ULONG TmpLen;
UCHAR P2pIdx = P2P_NOT_FOUND;
UCHAR GroupCap = 0xff, DeviceCap = 0xff, DevAddr[6] = {0}, DeviceType[8], DeviceName[32], DeviceNameLen = 0;
PUCHAR pData;
USHORT Dpid, ConfigMethod;
pMacEntry->bP2pClient = TRUE;
pMacEntry->P2pInfo.P2pClientState = P2PSTATE_GO_OPERATING;
P2pIdx = P2pGroupTabSearch(pAd, pMacEntry->Addr);
if (P2pIdx == P2P_NOT_FOUND)
P2pIdx = P2pGroupTabInsert(pAd, DevAddr, P2PSTATE_DISCOVERY_GO, NULL, 0, 0, 0);
if (P2pIdx != P2P_NOT_FOUND)
pMacEntry->P2pInfo.p2pIndex = P2pIdx;
}
result = TRUE;
pAd->ApCfg.ApCliInfRunned++;
break;
}
result = FALSE;
} while(FALSE);
RTMPSetSupportMCS(pAd,
OPMODE_AP,
pMacEntry,
pAd->ApCliMlmeAux.SupRate,
pAd->ApCliMlmeAux.SupRateLen,
pAd->ApCliMlmeAux.ExtRate,
pAd->ApCliMlmeAux.ExtRateLen,
#ifdef DOT11_VHT_AC
pAd->ApCliMlmeAux.vht_cap_len,
&pAd->ApCliMlmeAux.vht_cap,
#endif /* DOT11_VHT_AC */
&pAd->ApCliMlmeAux.HtCapability,
pAd->ApCliMlmeAux.HtCapabilityLen);
#ifdef WSC_AP_SUPPORT
/* WSC initial connect to AP, jump to Wsc start action and set the correct parameters */
if ((result == TRUE) &&
(pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode == WSC_ENROLLEE) &&
(pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger == TRUE))
{
pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscState = WSC_STATE_LINK_UP;
pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscStatus = WSC_STATE_LINK_UP;
pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfStatus = WSC_SCSTATE_UNCONFIGURED;
NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.EntryAddr, MAC_ADDR_LEN);
NdisMoveMemory(pAd->ApCfg.ApCliTab[ifIndex].WscControl.EntryAddr, pAd->ApCliMlmeAux.Bssid, MAC_ADDR_LEN);
WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE);
}
else
{
WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[ifIndex].WscControl);
}
#endif /* WSC_AP_SUPPORT */
#ifdef CONFIG_MULTI_CHANNEL
if (pAd->Multi_Channel_Enable == TRUE)
{
UINT32 Data;
RTMP_IO_READ32(pAd, WMM_CTRL, &Data);
Data |= 0x80000000;/* bit 31 set to 1 */ /* WMM Channel switch to EDCA2 */
RTMP_IO_WRITE32(pAd, WMM_CTRL, Data);
RtmpPrepareHwNullFrame(pAd,
pMacEntry,
FALSE,
FALSE,
0,
OPMODE_AP,
PWR_SAVE,
TRUE,
1);
if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) &&
(pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger
))
{
printk ("p2p WSC trigger not set Multi-channel!!\n");
}
else if (INFRA_ON(pAd)
&& pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED
&& pMacEntry->WepStatus == Ndis802_11WEPDisabled)
{
printk("INFRA_ON(pAd) set HCCAToEDCATimer\n");
if (pAd->P2pCfg.bStartP2pConnect)
{
pAd->P2pCfg.bStartP2pConnect = FALSE;
}
RTMPSetTimer(&pAd->Mlme.MCCTimer, pAd->Mlme.HCCAToEDCATimerValue);
}
pAd->Mlme.P2pStayTick = 0;
pAd->StaCfg.bImprovedScan = FALSE;
}
#endif /* CONFIG_MULTI_CHANNEL */
return result;
}
/*
==========================================================================
Routine Description:
Disconnect current BSSID
Arguments:
pAd - Pointer to our adapter
ApCliIdx - Which ApCli interface
Return Value:
None
Note:
==========================================================================
*/
VOID ApCliLinkDown(
IN PRTMP_ADAPTER pAd,
IN UCHAR ifIndex)
{
PAPCLI_STRUCT pApCliEntry = NULL;
MAC_TABLE_ENTRY *pEntry;
UCHAR P2pIdx = P2P_NOT_FOUND;
UCHAR BBPValue = 0;
if (ifIndex < MAX_APCLI_NUM)
{
DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex));
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("!!! ERROR : APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex));
return;
}
#ifdef CONFIG_MULTI_CHANNEL
if (pAd->Multi_Channel_Enable == TRUE)
MultiChannelTimerStop(pAd);
#endif /* CONFIG_MULTI_CHANNEL */
pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex];
if (pApCliEntry->Valid == FALSE)
return;
/* Find the p2p Entry and change the p2p State. */
if (pApCliEntry->bP2pClient)
{
NdisZeroMemory(pAd->ApCfg.ApCliTab[0].CfgApCliBssid, MAC_ADDR_LEN);
pEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID];
P2pIdx = P2pGroupTabSearch(pAd, pEntry->Addr);
if ((P2P_CLI_ON(pAd)) && (IS_ENTRY_APCLI(pEntry)) &&
(pEntry->WpaState == AS_PTKINITDONE))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s:: Secured = %d. Addr = %02x:%02x:%02x:%02x:%02x:%02x.\n",
__FUNCTION__, pEntry->PortSecured, PRINT_MAC(pEntry->Addr)));
if (P2pIdx != P2P_NOT_FOUND)
pAd->P2pTable.Client[P2pIdx].P2pClientState = P2PSTATE_DISCOVERY;
if (pAd->P2pCfg.bP2pCliReConnect == FALSE)
P2pLinkDown(pAd, P2P_DISCONNECTED);
else
{
pAd->P2pCfg.bP2pCliReConnectTimerRunning = TRUE;
RTMPSetTimer(&pAd->P2pCfg.P2pCliReConnectTimer, P2P_CHECK_CLIENT_TIMER);
}
}
}
if ((INFRA_ON(pAd)) && (pAd->StaActive.SupportedHtPhy.ChannelWidth == BW_40))
{
}
else
{
rtmp_bbp_set_bw(pAd, BW_20);
}
pAd->ApCfg.ApCliInfRunned--;
MacTableDeleteEntry(pAd, pApCliEntry->MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID));
/* Clean Bss Search Table. */
#ifdef CONFIG_MULTI_CHANNEL
DBGPRINT(RT_DEBUG_TRACE, ("\n++++++++ %s:: Delete BssSearch Table on Channel = %d. ++++++++\n", __FUNCTION__, pAd->ApCliMlmeAux.Channel));
DBGPRINT(RT_DEBUG_TRACE, (" BSSID = [%02x:%02x:%02x:%02x:%02x:%02x]. p2p_bssid = [%02x:%02x:%02x:%02x:%02x:%02x].\n", PRINT_MAC(pAd->ApCliMlmeAux.Bssid), PRINT_MAC(pAd->P2pCfg.Bssid)));
BssTableDeleteEntry(&pAd->ScanTab,
/*pAd->ApCliMlmeAux.Bssid*/pAd->P2pCfg.Bssid,
pAd->ApCliMlmeAux.Channel);
#else
DBGPRINT(RT_DEBUG_TRACE, ("\n++++++++ %s:: Delete BssSearch Table on Channel = %d. ++++++++\n", __FUNCTION__, pAd->CommonCfg.Channel));
DBGPRINT(RT_DEBUG_TRACE, (" BSSID = [%02x:%02x:%02x:%02x:%02x:%02x]. p2p_bssid = [%02x:%02x:%02x:%02x:%02x:%02x].\n", PRINT_MAC(pAd->ApCliMlmeAux.Bssid), PRINT_MAC(pAd->P2pCfg.Bssid)));
BssTableDeleteEntry(&pAd->ScanTab,
/*pAd->ApCliMlmeAux.Bssid*/pAd->P2pCfg.Bssid,
pAd->CommonCfg.Channel);
#endif /*CONFIG_MULTI_CHANNEL*/
pApCliEntry->Valid = FALSE; /* This link doesn't associated with any remote-AP */
#ifdef CONFIG_MULTI_CHANNEL
if (pAd->Multi_Channel_Enable == TRUE)
{
UINT32 Data;
RTMP_IO_READ32(pAd, WMM_CTRL, &Data);
Data &= 0x7fffffff;/* bit 31 set to 0 */ /* WMM Channel switch to EDCA1 */
RTMP_IO_WRITE32(pAd, WMM_CTRL, Data);
if(!P2P_CLI_ON(pAd))
{
UINT32 Value=0;
MultiChannelSwitchToRa(pAd);
RTUSBReadMACRegister(pAd, PBF_CFG, &Value);
Value |= ((1 << 3) | (1 << 13));/* bit 3 and bit 13 set to 1 */
Value |= ((1 << 2) | (1 << 12));/* bit 2 and bit 12 set to 1 */
RTUSBWriteMACRegister(pAd, PBF_CFG, Value,FALSE);
pAd->MultiChannelFlowCtl=0;
RTMP_OS_NETDEV_WAKE_QUEUE(pAd->net_dev);
}
}
#endif /*CONFIG_MULTI_CHANNEL*/
}
/*
==========================================================================
Description:
APCLI Interface Up.
==========================================================================
*/
VOID ApCliIfUp(
IN PRTMP_ADAPTER pAd)
{
UCHAR ifIndex;
PAPCLI_STRUCT pApCliEntry;
/* Reset is in progress, stop immediately */
if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
return;
/* sanity check whether the interface is initialized. */
if (pAd->flg_apcli_init != TRUE)
return;
for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++)
{
pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex];
if (APCLI_IF_UP_CHECK(pAd, ifIndex)
&& (pApCliEntry->Enable == TRUE)
&& (pApCliEntry->Valid == FALSE))
{
DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startup.\n", __FUNCTION__, ifIndex));
COPY_MAC_ADDR(pApCliEntry->CfgApCliBssid, pAd->P2pCfg.Bssid);
DBGPRINT(RT_DEBUG_TRACE, ("SSID = [%s]. BSSID = [%02x:%02x:%02x:%02x:%02x:%02x].\n", pApCliEntry->CfgSsid, PRINT_MAC(pApCliEntry->CfgApCliBssid)));
if (pAd->ApCfg.ApCliTab[0].CtrlCurrState == APCLI_CTRL_DISCONNECTED)
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ, 0, NULL, ifIndex);
}
}
return;
}
/*
==========================================================================
Description:
APCLI Interface Down.
==========================================================================
*/
VOID ApCliIfDown(
IN PRTMP_ADAPTER pAd)
{
UCHAR ifIndex;
PAPCLI_STRUCT pApCliEntry;
for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++)
{
pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex];
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);
}
return;
}
/*
==========================================================================
Description:
APCLI Interface Monitor.
==========================================================================
*/
VOID ApCliIfMonitor(
IN PRTMP_ADAPTER pAd)
{
UCHAR index;
PAPCLI_STRUCT pApCliEntry;
/* Reset is in progress, stop immediately */
if ( RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))
return;
/* sanity check whether the interface is initialized. */
if (pAd->flg_apcli_init != TRUE)
return;
for(index = 0; index < MAX_APCLI_NUM; index++)
{
pApCliEntry = &pAd->ApCfg.ApCliTab[index];
if ((pApCliEntry->Valid == TRUE)
&& (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliRcvBeaconTime + (4 * OS_HZ)))))
{
DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: IF(apcli%d) - no Beancon is received from root-AP.\n", index));
DBGPRINT(RT_DEBUG_TRACE, ("ApCliIfMonitor: Reconnect the Root-Ap again.\n"));
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, index);
RTMP_MLME_HANDLER(pAd);
}
}
return;
}
/*! \brief To substitute the message type if the message is coming from external
* \param pFrame The frame received
* \param *Machine The state machine
* \param *MsgType the message type for the state machine
* \return TRUE if the substitution is successful, FALSE otherwise
* \pre
* \post
*/
BOOLEAN ApCliMsgTypeSubst(
IN PRTMP_ADAPTER pAd,
IN PFRAME_802_11 pFrame,
OUT INT *Machine,
OUT INT *MsgType)
{
USHORT Seq;
UCHAR EAPType;
BOOLEAN Return = FALSE;
#ifdef WSC_AP_SUPPORT
UCHAR EAPCode;
PMAC_TABLE_ENTRY pEntry;
#endif /* WSC_AP_SUPPORT */
/* only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid; otherwise, */
/* ignore this frame */
/* WPA EAPOL PACKET */
if (pFrame->Hdr.FC.Type == BTYPE_DATA)
{
#ifdef WSC_AP_SUPPORT
/* WSC EAPOL PACKET */
pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2);
if (pEntry && IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->apidx].WscControl.WscConfMode == WSC_ENROLLEE)
{
*Machine = WSC_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
EAPCode = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 4);
Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType);
}
if (!Return)
#endif /* WSC_AP_SUPPORT */
{
*Machine = WPA_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
Return = WpaMsgTypeSubst(EAPType, MsgType);
}
return Return;
}
else if (pFrame->Hdr.FC.Type == BTYPE_MGMT)
{
switch (pFrame->Hdr.FC.SubType)
{
case SUBTYPE_ASSOC_RSP:
*Machine = APCLI_ASSOC_STATE_MACHINE;
*MsgType = APCLI_MT2_PEER_ASSOC_RSP;
break;
case SUBTYPE_DISASSOC:
*Machine = APCLI_ASSOC_STATE_MACHINE;
*MsgType = APCLI_MT2_PEER_DISASSOC_REQ;
break;
case SUBTYPE_DEAUTH:
*Machine = APCLI_AUTH_STATE_MACHINE;
*MsgType = APCLI_MT2_PEER_DEAUTH;
break;
case SUBTYPE_AUTH:
/* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
if (Seq == 2 || Seq == 4)
{
*Machine = APCLI_AUTH_STATE_MACHINE;
*MsgType = APCLI_MT2_PEER_AUTH_EVEN;
}
else
{
return FALSE;
}
break;
case SUBTYPE_ACTION:
*Machine = ACTION_STATE_MACHINE;
/* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
{
*MsgType = MT2_ACT_INVALID;
}
else
{
*MsgType = (pFrame->Octet[0]&0x7F);
}
break;
default:
return FALSE;
}
return TRUE;
}
return FALSE;
}
BOOLEAN preCheckMsgTypeSubset(
IN PRTMP_ADAPTER pAd,
IN PFRAME_802_11 pFrame,
OUT INT *Machine,
OUT INT *MsgType)
{
if (pFrame->Hdr.FC.Type == BTYPE_MGMT)
{
switch (pFrame->Hdr.FC.SubType)
{
/* Beacon must be processed be AP Sync state machine. */
case SUBTYPE_BEACON:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_BEACON;
break;
/* Only Sta have chance to receive Probe-Rsp. */
case SUBTYPE_PROBE_RSP:
*Machine = APCLI_SYNC_STATE_MACHINE;
*MsgType = APCLI_MT2_PEER_PROBE_RSP;
break;
default:
return FALSE;
}
return TRUE;
}
return FALSE;
}
/*
==========================================================================
Description:
MLME message sanity check
Return:
TRUE if all parameters are OK, FALSE otherwise
IRQL = DISPATCH_LEVEL
==========================================================================
*/
BOOLEAN ApCliPeerAssocRspSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT PUCHAR pAddr2,
OUT USHORT *pCapabilityInfo,
OUT USHORT *pStatus,
OUT USHORT *pAid,
OUT ULONG *P2PSubelementLen,
OUT PUCHAR pP2pSubelement,
OUT UCHAR SupRate[],
OUT UCHAR *pSupRateLen,
OUT UCHAR ExtRate[],
OUT UCHAR *pExtRateLen,
OUT HT_CAPABILITY_IE *pHtCapability,
OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */
OUT UCHAR *pHtCapabilityLen,
OUT UCHAR *pAddHtInfoLen,
OUT UCHAR *pNewExtChannelOffset,
OUT PEDCA_PARM pEdcaParm,
OUT UCHAR *pCkipFlag)
{
CHAR IeType, *Ptr;
PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg;
PEID_STRUCT pEid;
ULONG Length = 0;
UCHAR P2POUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x9};
*pNewExtChannelOffset = 0xff;
*pHtCapabilityLen = 0;
*pAddHtInfoLen = 0;
COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2);
Ptr = (CHAR *) pFrame->Octet;
Length += LENGTH_802_11;
NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2);
Length += 2;
NdisMoveMemory(pStatus, &pFrame->Octet[2], 2);
Length += 2;
*pCkipFlag = 0;
*pExtRateLen = 0;
pEdcaParm->bValid = FALSE;
if (*pStatus != MLME_SUCCESS)
return TRUE;
NdisMoveMemory(pAid, &pFrame->Octet[4], 2);
Length += 2;
/* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */
*pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */
/* -- get supported rates from payload and advance the pointer */
IeType = pFrame->Octet[6];
*pSupRateLen = pFrame->Octet[7];
if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES))
{
DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SupportedRates IE\n", __FUNCTION__));
return FALSE;
}
else
NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen);
Length = Length + 2 + *pSupRateLen;
/* many AP implement proprietary IEs in non-standard order, we'd better */
/* tolerate mis-ordered IEs to get best compatibility */
pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)];
/* get variable fields from payload and advance the pointer */
while ((Length + 2 + pEid->Len) <= MsgLen)
{
switch (pEid->Eid)
{
case IE_EXT_SUPP_RATES:
if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES)
{
NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len);
*pExtRateLen = pEid->Len;
}
break;
#ifdef DOT11_N_SUPPORT
case IE_HT_CAP:
case IE_HT_CAP2:
if (pEid->Len >= SIZE_HT_CAP_IE) /* Note: allow extension.!! */
{
NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE);
*(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
*(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
*pHtCapabilityLen = SIZE_HT_CAP_IE;
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP. \n", __FUNCTION__));
}
break;
case IE_ADD_HT:
case IE_ADD_HT2:
if (pEid->Len >= sizeof(ADD_HT_INFO_IE))
{
/* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */
/* copy first sizeof(ADD_HT_INFO_IE) */
NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE));
*pAddHtInfoLen = SIZE_ADD_HT_INFO_IE;
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_ADD_HT. \n", __FUNCTION__));
}
break;
case IE_SECONDARY_CH_OFFSET:
if (pEid->Len == 1)
{
*pNewExtChannelOffset = pEid->Octet[0];
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__));
}
break;
#endif /* DOT11_N_SUPPORT */
/* CCX2, WMM use the same IE value */
/* case IE_CCX_V2: */
case IE_VENDOR_SPECIFIC:
/* handle WME PARAMTER ELEMENT */
if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24))
{
PUCHAR ptr;
int i;
/* parsing EDCA parameters */
pEdcaParm->bValid = TRUE;
pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */
pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */
pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */
/*pEdcaParm->bMoreDataAck = FALSE; *//* pEid->Octet[0] & 0x80; */
pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f;
pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0;
ptr = (PUCHAR) &pEid->Octet[8];
for (i=0; i<4; i++)
{
UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */
pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */
pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */
pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin */
pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax */
pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us */
ptr += 4; /* point to next AC */
}
}
if (NdisEqualMemory(pEid->Octet, P2POUIBYTE, sizeof(P2POUIBYTE)) && (pEid->Len >= 4))
{
if (*P2PSubelementLen == 0)
{
RTMPMoveMemory(pP2pSubelement, &pEid->Eid, (pEid->Len+2));
*P2PSubelementLen = (pEid->Len+2);
}
else if (*P2PSubelementLen > 0)
{
RTMPMoveMemory(pP2pSubelement + *P2PSubelementLen, &pEid->Eid, (pEid->Len+2));
*P2PSubelementLen += (pEid->Len+2);
}
DBGPRINT(RT_DEBUG_ERROR, (" ! ===>P2P - %s P2P IE Len becomes = %ld.\n", __FUNCTION__, *P2PSubelementLen));
}
break;
default:
DBGPRINT(RT_DEBUG_TRACE, ("%s():ignore unrecognized EID = %d\n", __FUNCTION__, pEid->Eid));
break;
}
Length = Length + 2 + pEid->Len;
pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
}
return TRUE;
}
MAC_TABLE_ENTRY *ApCliTableLookUpByWcid(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid,
IN PUCHAR pAddrs)
{
/*USHORT HashIdx; */
ULONG ApCliIndex;
PMAC_TABLE_ENTRY pCurEntry = NULL;
PMAC_TABLE_ENTRY pEntry = NULL;
if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE )
return NULL;
NdisAcquireSpinLock(&pAd->MacTabLock);
do
{
pCurEntry = &pAd->MacTab.Content[wcid];
ApCliIndex = 0xff;
if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry))
{
ApCliIndex = pCurEntry->MatchAPCLITabIdx;
}
if ((ApCliIndex == 0xff) || (ApCliIndex >= MAX_APCLI_NUM))
break;
if (pAd->ApCfg.ApCliTab[ApCliIndex].Valid != TRUE)
break;
if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddrs))
{
pEntry = pCurEntry;
break;
}
} while(FALSE);
NdisReleaseSpinLock(&pAd->MacTabLock);
return pEntry;
}
/*
==========================================================================
Description:
Check the WDS Entry is valid or not.
==========================================================================
*/
static inline BOOLEAN ValidApCliEntry(
IN PRTMP_ADAPTER pAd,
IN INT apCliIdx)
{
BOOLEAN result;
PMAC_TABLE_ENTRY pMacEntry;
APCLI_STRUCT *pApCliEntry;
do
{
if ((apCliIdx < 0) || (apCliIdx >= MAX_APCLI_NUM))
{
result = FALSE;
break;
}
pApCliEntry = (APCLI_STRUCT *)&pAd->ApCfg.ApCliTab[apCliIdx];
if (pApCliEntry->Valid != TRUE)
{
result = FALSE;
break;
}
if ((pApCliEntry->MacTabWCID <= 0)
|| (pApCliEntry->MacTabWCID >= MAX_LEN_OF_MAC_TABLE))
{
result = FALSE;
break;
}
pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID];
if (!IS_ENTRY_APCLI(pMacEntry))
{
result = FALSE;
break;
}
result = TRUE;
} while(FALSE);
return result;
}
BOOLEAN ApCliAllowToSendPacket(
IN RTMP_ADAPTER *pAd,
IN PNDIS_PACKET pPacket,
OUT UCHAR *pWcid)
{
UCHAR apCliIdx;
BOOLEAN allowed;
/*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket():Packet to ApCli interface!\n")); */
apCliIdx = RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI;
if (ValidApCliEntry(pAd, apCliIdx))
{
/*DBGPRINT(RT_DEBUG_TRACE, ("ApCliAllowToSendPacket(): Set the WCID as %d!\n", pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID)); */
*pWcid = pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID;
/*RTMP_SET_PACKET_WCID(pPacket, pAd->ApCfg.ApCliTab[apCliIdx].MacTabWCID); *//* to ApClient links. */
allowed = TRUE;
}
else
{
allowed = FALSE;
}
return allowed;
}
/*
========================================================================
Routine Description:
Validate the security configuration against the RSN information
element
Arguments:
pAdapter Pointer to our adapter
eid_ptr Pointer to VIE
Return Value:
TRUE for configuration match
FALSE for otherwise
Note:
========================================================================
*/
BOOLEAN ApCliValidateRSNIE(
IN PRTMP_ADAPTER pAd,
IN PEID_STRUCT pEid_ptr,
IN USHORT eid_len,
IN USHORT idx)
{
PUCHAR pVIE;
PUCHAR pTmp;
UCHAR len;
PEID_STRUCT pEid;
CIPHER_SUITE WPA; /* AP announced WPA cipher suite */
CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */
USHORT Count;
UCHAR Sanity;
PAPCLI_STRUCT pApCliEntry = NULL;
PRSN_IE_HEADER_STRUCT pRsnHeader;
NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
NDIS_802_11_AUTHENTICATION_MODE TmpAuthMode;
NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode;
NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux;
NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthMode;
NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthModeAux;
pVIE = (PUCHAR) pEid_ptr;
len = eid_len;
/* if (len >= MAX_LEN_OF_RSNIE || len <= MIN_LEN_OF_RSNIE) */
/* return FALSE; */
/* Init WPA setting */
WPA.PairCipher = Ndis802_11WEPDisabled;
WPA.PairCipherAux = Ndis802_11WEPDisabled;
WPA.GroupCipher = Ndis802_11WEPDisabled;
WPA.RsnCapability = 0;
WPA.bMixMode = FALSE;
WPA_AuthMode = Ndis802_11AuthModeOpen;
WPA_AuthModeAux = Ndis802_11AuthModeOpen;
/* Init WPA2 setting */
WPA2.PairCipher = Ndis802_11WEPDisabled;
WPA2.PairCipherAux = Ndis802_11WEPDisabled;
WPA2.GroupCipher = Ndis802_11WEPDisabled;
WPA2.RsnCapability = 0;
WPA2.bMixMode = FALSE;
WPA2_AuthMode = Ndis802_11AuthModeOpen;
WPA2_AuthModeAux = Ndis802_11AuthModeOpen;
Sanity = 0;
/* 1. Parse Cipher this received RSNIE */
while (len > 0)
{
pTmp = pVIE;
pEid = (PEID_STRUCT) pTmp;
switch(pEid->Eid)
{
case IE_WPA:
if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
{
/* if unsupported vendor specific IE */
break;
}
/* Skip OUI ,version and multicast suite OUI */
pTmp += 11;
/* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
/* Value Meaning */
/* 0 None */
/* 1 WEP-40 */
/* 2 Tkip */
/* 3 WRAP */
/* 4 AES */
/* 5 WEP-104 */
/* Parse group cipher */
switch (*pTmp)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
WPA.GroupCipher = Ndis802_11Encryption1Enabled;
break;
case 2:
WPA.GroupCipher = Ndis802_11Encryption2Enabled;
break;
case 4:
WPA.GroupCipher = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
/* number of unicast suite */
pTmp += 1;
/* Store unicast cipher count */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
/* pointer to unicast cipher */
pTmp += sizeof(USHORT);
/* Parsing all unicast cipher suite */
while (Count > 0)
{
/* Skip cipher suite OUI */
pTmp += 3;
TmpCipher = Ndis802_11WEPDisabled;
switch (*pTmp)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
TmpCipher = Ndis802_11Encryption1Enabled;
break;
case 2:
TmpCipher = Ndis802_11Encryption2Enabled;
break;
case 4:
TmpCipher = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
if (TmpCipher > WPA.PairCipher)
{
/* Move the lower cipher suite to PairCipherAux */
WPA.PairCipherAux = WPA.PairCipher;
WPA.PairCipher = TmpCipher;
}
else
{
WPA.PairCipherAux = TmpCipher;
}
pTmp++;
Count--;
}
/* Get AKM suite counts */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
pTmp += sizeof(USHORT);
/* Parse AKM ciphers */
/* Parsing all AKM cipher suite */
while (Count > 0)
{
/* Skip cipher suite OUI */
pTmp += 3;
TmpAuthMode = Ndis802_11AuthModeOpen;
switch (*pTmp)
{
case 1:
/* WPA-enterprise */
TmpAuthMode = Ndis802_11AuthModeWPA;
break;
case 2:
/* WPA-personal */
TmpAuthMode = Ndis802_11AuthModeWPAPSK;
break;
default:
break;
}
if (TmpAuthMode > WPA_AuthMode)
{
/* Move the lower AKM suite to WPA_AuthModeAux */
WPA_AuthModeAux = WPA_AuthMode;
WPA_AuthMode = TmpAuthMode;
}
else
{
WPA_AuthModeAux = TmpAuthMode;
}
pTmp++;
Count--;
}
/* ToDo - Support WPA-None ? */
/* Check the Pair & Group, if different, turn on mixed mode flag */
if (WPA.GroupCipher != WPA.PairCipher)
WPA.bMixMode = TRUE;
DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA1 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n",
((WPA.bMixMode) ? "Mix" : GetEncryptType(WPA.PairCipher)),
GetEncryptType(WPA.GroupCipher),
GetAuthMode(WPA_AuthMode)));
Sanity |= 0x1;
break;
case IE_RSN:
pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
/* 0. Version must be 1 */
/* The pRsnHeader->Version exists in native little-endian order, so we may need swap it for RT_BIG_ENDIAN systems. */
if (le2cpu16(pRsnHeader->Version) != 1)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - RSN Version isn't 1(%d) \n", pRsnHeader->Version));
break;
}
pTmp += sizeof(RSN_IE_HEADER_STRUCT);
/* 1. Check cipher OUI */
if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
{
/* if unsupported vendor specific IE */
break;
}
/* Skip cipher suite OUI */
pTmp += 3;
/* Parse group cipher */
switch (*pTmp)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
break;
case 2:
WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
break;
case 4:
WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
/* number of unicast suite */
pTmp += 1;
/* Get pairwise cipher counts */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
pTmp += sizeof(USHORT);
/* 3. Get pairwise cipher */
/* Parsing all unicast cipher suite */
while (Count > 0)
{
/* Skip OUI*/
pTmp += 3;
TmpCipher = Ndis802_11WEPDisabled;
switch (*pTmp)
{
case 1:
case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
TmpCipher = Ndis802_11Encryption1Enabled;
break;
case 2:
TmpCipher = Ndis802_11Encryption2Enabled;
break;
case 4:
TmpCipher = Ndis802_11Encryption3Enabled;
break;
default:
break;
}
if (TmpCipher > WPA2.PairCipher)
{
/* Move the lower cipher suite to PairCipherAux */
WPA2.PairCipherAux = WPA2.PairCipher;
WPA2.PairCipher = TmpCipher;
}
else
{
WPA2.PairCipherAux = TmpCipher;
}
pTmp ++;
Count--;
}
/* Get AKM suite counts */
NdisMoveMemory(&Count, pTmp, sizeof(USHORT));
Count = cpu2le16(Count);
pTmp += sizeof(USHORT);
/* Parse AKM ciphers */
/* Parsing all AKM cipher suite */
while (Count > 0)
{
/* Skip cipher suite OUI */
pTmp += 3;
TmpAuthMode = Ndis802_11AuthModeOpen;
switch (*pTmp)
{
case 1:
/* WPA2-enterprise */
TmpAuthMode = Ndis802_11AuthModeWPA2;
break;
case 2:
/* WPA2-personal */
TmpAuthMode = Ndis802_11AuthModeWPA2PSK;
break;
default:
break;
}
if (TmpAuthMode > WPA2_AuthMode)
{
/* Move the lower AKM suite to WPA2_AuthModeAux */
WPA2_AuthModeAux = WPA2_AuthMode;
WPA2_AuthMode = TmpAuthMode;
}
else
{
WPA2_AuthModeAux = TmpAuthMode;
}
pTmp++;
Count--;
}
/* Check the Pair & Group, if different, turn on mixed mode flag */
if (WPA2.GroupCipher != WPA2.PairCipher)
WPA2.bMixMode = TRUE;
DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA2 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n",
(WPA2.bMixMode ? "Mix" : GetEncryptType(WPA2.PairCipher)), GetEncryptType(WPA2.GroupCipher),
GetAuthMode(WPA2_AuthMode)));
Sanity |= 0x2;
break;
default:
DBGPRINT(RT_DEBUG_WARN, ("ApCliValidateRSNIE - Unknown pEid->Eid(%d) \n", pEid->Eid));
break;
}
/* skip this Eid */
pVIE += (pEid->Len + 2);
len -= (pEid->Len + 2);
}
/* 2. Validate this RSNIE with mine */
pApCliEntry = &pAd->ApCfg.ApCliTab[idx];
/* Peer AP doesn't include WPA/WPA2 capable */
if (Sanity == 0)
{
/* Check the authenticaton mode */
if (pApCliEntry->AuthMode >= Ndis802_11AuthModeWPA)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match \n", __FUNCTION__));
return FALSE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s - The pre-RSNA authentication mode is used. \n", __FUNCTION__));
return TRUE;
}
}
/* Recovery user-defined cipher suite */
pApCliEntry->PairCipher = pApCliEntry->WepStatus;
pApCliEntry->GroupCipher = pApCliEntry->WepStatus;
pApCliEntry->bMixCipher = FALSE;
Sanity = 0;
/* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */
/* WPAPSK */
if ((WPA_AuthMode == pApCliEntry->AuthMode) ||
((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == pApCliEntry->AuthMode)))
{
/* Check cipher suite, AP must have more secured cipher than station setting */
if (WPA.bMixMode == FALSE)
{
if (pApCliEntry->WepStatus != WPA.GroupCipher)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n"));
return FALSE;
}
}
/* check group cipher */
if (pApCliEntry->WepStatus < WPA.GroupCipher)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate group cipher error \n"));
return FALSE;
}
/* check pairwise cipher, skip if none matched */
/* If profile set to AES, let it pass without question. */
/* If profile set to TKIP, we must find one mateched */
if ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) &&
(pApCliEntry->WepStatus != WPA.PairCipher) &&
(pApCliEntry->WepStatus != WPA.PairCipherAux))
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n"));
return FALSE;
}
Sanity |= 0x1;
}
/* WPA2PSK */
else if ((WPA2_AuthMode == pApCliEntry->AuthMode) ||
((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == pApCliEntry->AuthMode)))
{
/* Check cipher suite, AP must have more secured cipher than station setting */
if (WPA2.bMixMode == FALSE)
{
if (pApCliEntry->WepStatus != WPA2.GroupCipher)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n"));
return FALSE;
}
}
/* check group cipher */
if (pApCliEntry->WepStatus < WPA2.GroupCipher)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate group cipher error \n"));
return FALSE;
}
/* check pairwise cipher, skip if none matched */
/* If profile set to AES, let it pass without question. */
/* If profile set to TKIP, we must find one mateched */
if ((pApCliEntry->WepStatus == Ndis802_11Encryption2Enabled) &&
(pApCliEntry->WepStatus != WPA2.PairCipher) &&
(pApCliEntry->WepStatus != WPA2.PairCipherAux))
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate pairwise cipher error \n"));
return FALSE;
}
Sanity |= 0x2;
}
if (Sanity == 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - Validate RSIE Failure \n"));
return FALSE;
}
/* Re-assign pairwise-cipher and group-cipher. Re-build RSNIE. */
if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPAPSK))
{
pApCliEntry->GroupCipher = WPA.GroupCipher;
if (pApCliEntry->WepStatus == WPA.PairCipher)
pApCliEntry->PairCipher = WPA.PairCipher;
else if (WPA.PairCipherAux != Ndis802_11WEPDisabled)
pApCliEntry->PairCipher = WPA.PairCipherAux;
else /* There is no PairCipher Aux, downgrade our capability to TKIP */
pApCliEntry->PairCipher = Ndis802_11Encryption2Enabled;
}
else if ((pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pApCliEntry->AuthMode == Ndis802_11AuthModeWPA2PSK))
{
pApCliEntry->GroupCipher = WPA2.GroupCipher;
if (pApCliEntry->WepStatus == WPA2.PairCipher)
pApCliEntry->PairCipher = WPA2.PairCipher;
else if (WPA2.PairCipherAux != Ndis802_11WEPDisabled)
pApCliEntry->PairCipher = WPA2.PairCipherAux;
else /* There is no PairCipher Aux, downgrade our capability to TKIP */
pApCliEntry->PairCipher = Ndis802_11Encryption2Enabled;
}
/* Set Mix cipher flag */
if (pApCliEntry->PairCipher != pApCliEntry->GroupCipher)
{
pApCliEntry->bMixCipher = TRUE;
/* re-build RSNIE */
/* RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); */
}
/* re-build RSNIE */
RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI));
return TRUE;
}
BOOLEAN ApCliHandleRxBroadcastFrame(
IN PRTMP_ADAPTER pAd,
IN RX_BLK *pRxBlk,
IN MAC_TABLE_ENTRY *pEntry,
IN UCHAR FromWhichBSSID)
{
RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo;
PHEADER_802_11 pHeader = pRxBlk->pHeader;
RXWI_STRUC *pRxWI = pRxBlk->pRxWI;
APCLI_STRUCT *pApCliEntry = NULL;
/* It is possible to receive the multicast packet when in AP Client mode */
/* Such as a broadcast from remote AP to AP-client, address1 is ffffff, address2 is remote AP's bssid, addr3 is sta4 mac address */
pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->MatchAPCLITabIdx];
/* Filter out Bcast frame which AP relayed for us */
/* Multicast packet send from AP1 , received by AP2 and send back to AP1, drop this frame */
if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->CurrentAddress))
return FALSE; /* give up this frame */
if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll)
return FALSE; /* give up this frame */
/* skip the 802.11 header */
pRxBlk->pData += LENGTH_802_11;
pRxBlk->DataSize -= LENGTH_802_11;
/* Use software to decrypt the encrypted frame. */
/* Because this received frame isn't my BSS frame, Asic passed to driver without decrypting it. */
/* If receiving an "encrypted" unicast packet(its WEP bit as 1) and doesn't match my BSSID, it */
/* pass to driver with "Decrypted" marked as 0 in RxD. */
if ((pRxInfo->MyBss == 0) && (pRxInfo->Decrypted == 0) && (pHeader->FC.Wep == 1))
{
if (RTMPSoftDecryptionAction(pAd,
(PUCHAR)pHeader, 0,
&pApCliEntry->SharedKey[pRxWI->RxWIKeyIndex],
pRxBlk->pData,
&(pRxBlk->DataSize)) == NDIS_STATUS_FAILURE)
{
return FALSE; /* give up this frame */
}
}
pRxInfo->MyBss = 1;
Indicate_Legacy_Packet(pAd, pRxBlk, FromWhichBSSID);
return TRUE;
}
VOID APCliInstallPairwiseKey(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry)
{
UCHAR IfIdx;
UINT8 BssIdx;
IfIdx = pEntry->MatchAPCLITabIdx;
BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + IfIdx;
WPAInstallPairwiseKey(pAd,
BssIdx,
pEntry,
FALSE);
}
BOOLEAN APCliInstallSharedKey(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pKey,
IN UCHAR KeyLen,
IN UCHAR DefaultKeyIdx,
IN MAC_TABLE_ENTRY *pEntry)
{
UCHAR IfIdx;
UCHAR GTK_len = 0;
if (!pEntry || !IS_ENTRY_APCLI(pEntry))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__));
return FALSE;
}
IfIdx = pEntry->MatchAPCLITabIdx;
if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled && KeyLen >= LEN_TKIP_GTK)
{
GTK_len = LEN_TKIP_GTK;
}
else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled &&
KeyLen >= LEN_AES_GTK)
{
GTK_len = LEN_AES_GTK;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n",
__FUNCTION__, pAd->ApCfg.ApCliTab[IfIdx].GroupCipher, KeyLen));
return FALSE;
}
/* Update GTK */
/* set key material, TxMic and RxMic for WPAPSK */
NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].GTK, pKey, GTK_len);
pAd->ApCfg.ApCliTab[IfIdx].DefaultKeyId = DefaultKeyIdx;
/* Update shared key table */
NdisZeroMemory(&pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY));
pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].KeyLen = GTK_len;
NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK);
if (GTK_len == LEN_TKIP_GTK)
{
NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC);
NdisMoveMemory(pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC);
}
/* Update Shared Key CipherAlg */
pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE;
if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption2Enabled)
pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP;
else if (pAd->ApCfg.ApCliTab[IfIdx].GroupCipher == Ndis802_11Encryption3Enabled)
pAd->ApCfg.ApCliTab[IfIdx].SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES;
return TRUE;
}
VOID APCli_Init(
IN PRTMP_ADAPTER pAd,
IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps)
{
#define APCLI_MAX_DEV_NUM 32
PNET_DEV new_dev_p;
/* VIRTUAL_ADAPTER *apcli_pAd; */
INT apcli_index;
/* RTMP_OS_NETDEV_OP_HOOK netDevOpHook; */
APCLI_STRUCT *pApCliEntry;
/* sanity check to avoid redundant virtual interfaces are created */
if (pAd->flg_apcli_init != FALSE)
return;
/* init */
for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++)
pAd->ApCfg.ApCliTab[apcli_index].dev = NULL;
/* create virtual network interface */
for(apcli_index = 0; apcli_index < MAX_APCLI_NUM; apcli_index++)
{
UINT32 MC_RowID = 0, IoctlIF = 0;
#ifdef MULTIPLE_CARD_SUPPORT
MC_RowID = pAd->MC_RowID;
#endif /* MULTIPLE_CARD_SUPPORT */
#ifdef HOSTAPD_SUPPORT
IoctlIF = pAd->IoctlIF;
#endif /* HOSTAPD_SUPPORT */
new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, apcli_index, sizeof(PRTMP_ADAPTER), INF_APCLI_DEV_NAME);
#ifdef HOSTAPD_SUPPORT
pAd->IoctlIF = IoctlIF;
#endif /* HOSTAPD_SUPPORT */
RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd);
pApCliEntry = &pAd->ApCfg.ApCliTab[apcli_index];
/* init MAC address of virtual network interface */
COPY_MAC_ADDR(pApCliEntry->CurrentAddress, pAd->CurrentAddress);
if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1)
{
if (pAd->ApCfg.BssidNum > 0 || MAX_MESH_NUM > 0)
{
/*
Refer to HW definition -
Bit1 of MAC address Byte0 is local administration bit
and should be set to 1 in extended multiple BSSIDs'
Bit3~ of MAC address Byte0 is extended multiple BSSID index.
*/
pApCliEntry->CurrentAddress[0] += 2;
pApCliEntry->CurrentAddress[0] += (((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1) << 2);
}
}
else
{
pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] =
(pApCliEntry->CurrentAddress[ETH_LENGTH_OF_ADDRESS - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF;
}
pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */
pNetDevOps->needProtcted = TRUE;
NdisMoveMemory(pNetDevOps->devAddr, &pApCliEntry->CurrentAddress[0], MAC_ADDR_LEN);
/* register this device to OS */
RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps);
/* backup our virtual network interface */
pApCliEntry->dev = new_dev_p;
#ifdef WSC_AP_SUPPORT
pApCliEntry->WscControl.pAd = pAd;
NdisZeroMemory(pApCliEntry->WscControl.EntryAddr, MAC_ADDR_LEN);
pApCliEntry->WscControl.WscConfigMethods= 0x018C;
/* WscGenerateUUID(pAd, &pApCliEntry->WscControl.Wsc_Uuid_E[0], &pApCliEntry->WscControl.Wsc_Uuid_Str[0], 0, FALSE); */
/* WscInit(pAd, TRUE, apcli_index); */
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WSC_INIT, 0, (VOID *)pApCliEntry, apcli_index);
#endif /* WSC_AP_SUPPORT */
}
pAd->flg_apcli_init = TRUE;
}
VOID ApCli_Remove(
IN PRTMP_ADAPTER pAd)
{
UINT index;
for(index = 0; index < MAX_APCLI_NUM; index++)
{
RtmpOSNetDevProtect(1);
if (pAd->ApCfg.ApCliTab[index].dev)
{
RtmpOSNetDevDetach(pAd->ApCfg.ApCliTab[index].dev);
RtmpOSNetDevProtect(0);
RtmpOSNetDevFree(pAd->ApCfg.ApCliTab[index].dev);
RtmpOSNetDevProtect(1);
/* Clear it as NULL to prevent latter access error. */
pAd->flg_apcli_init = FALSE;
pAd->ApCfg.ApCliTab[index].dev = NULL;
}
RtmpOSNetDevProtect(0);
}
}
BOOLEAN ApCli_Open(
IN PRTMP_ADAPTER pAd,
IN PNET_DEV dev_p)
{
UCHAR ifIndex;
for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++)
{
if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p)
{
RTMP_OS_NETDEV_START_QUEUE(dev_p);
ApCliIfUp(pAd);
return TRUE;
}
}
return FALSE;
}
BOOLEAN ApCli_Close(
IN PRTMP_ADAPTER pAd,
IN PNET_DEV dev_p)
{
UCHAR ifIndex;
for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++)
{
if (pAd->ApCfg.ApCliTab[ifIndex].dev == dev_p)
{
RTMP_OS_NETDEV_STOP_QUEUE(dev_p);
/* send disconnect-req to sta State Machine. */
if (pAd->ApCfg.ApCliTab[ifIndex].Enable)
{
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, ifIndex);
RTMP_MLME_HANDLER(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", __FUNCTION__, ifIndex));
}
return TRUE;
}
}
return FALSE;
}
int APC_PacketSend(
IN PNDIS_PACKET skb_p,
IN PNET_DEV dev_p,
IN RTMP_NET_PACKET_TRANSMIT Func)
{
RTMP_ADAPTER *pAd;
PAPCLI_STRUCT pApCli;
INT apcliIndex;
pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p);
ASSERT(pAd);
#ifdef RALINK_ATE
if (ATE_ON(pAd))
{
RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE);
return 0;
}
#endif /* RALINK_ATE */
if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) ||
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)))
{
/* wlan is scanning/disabled/reset */
RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE);
return 0;
}
pApCli = (PAPCLI_STRUCT)&pAd->ApCfg.ApCliTab;
for(apcliIndex = 0; apcliIndex < MAX_APCLI_NUM; apcliIndex++)
{
if (pApCli[apcliIndex].Valid != TRUE)
continue;
/* find the device in our ApCli list */
if (pApCli[apcliIndex].dev == dev_p)
{
/* ya! find it */
pAd->RalinkCounters.PendingNdisPacketCount ++;
RTMP_SET_PACKET_SOURCE(skb_p, PKTSRC_NDIS);
RTMP_SET_PACKET_MOREDATA(skb_p, FALSE);
RTMP_SET_PACKET_NET_DEVICE_APCLI(skb_p, apcliIndex);
SET_OS_PKT_NETDEV(skb_p, pAd->net_dev);
/* transmit the packet */
return Func(skb_p);
}
}
RELEASE_NDIS_PACKET(pAd, skb_p, NDIS_STATUS_FAILURE);
return 0;
}
#endif /* P2P_SUPPORT */