mirror of
https://github.com/YikeStone/MT7601u.git
synced 2025-08-02 19:04:09 +05:30
2213 lines
65 KiB
C
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 */
|
|
|