bdc0a1739f
Removed the CFLAG RT2860 from Makefile and dependency on it in the driver code. Signed-off-by: Mark Einon <mark.einon@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2198 lines
73 KiB
C
2198 lines
73 KiB
C
/*
|
|
*************************************************************************
|
|
* Ralink Tech Inc.
|
|
* 5F., No.36, Taiyuan St., Jhubei City,
|
|
* Hsinchu County 302,
|
|
* Taiwan, R.O.C.
|
|
*
|
|
* (c) Copyright 2002-2007, Ralink Technology, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
* *
|
|
*************************************************************************
|
|
|
|
Module Name:
|
|
dls.c
|
|
|
|
Abstract:
|
|
Handle WMM-DLS state machine
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
Rory Chen 02-14-2006
|
|
Arvin Tai 06-03-2008 Modified for RT28xx
|
|
*/
|
|
|
|
#include "../rt_config.h"
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
dls state machine init, including state transition and timer init
|
|
Parameters:
|
|
Sm - pointer to the dls state machine
|
|
Note:
|
|
The state machine looks like this
|
|
|
|
DLS_IDLE
|
|
MT2_MLME_DLS_REQUEST MlmeDlsReqAction
|
|
MT2_PEER_DLS_REQUEST PeerDlsReqAction
|
|
MT2_PEER_DLS_RESPONSE PeerDlsRspAction
|
|
MT2_MLME_DLS_TEARDOWN MlmeTearDownAction
|
|
MT2_PEER_DLS_TEARDOWN PeerTearDownAction
|
|
|
|
IRQL = PASSIVE_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
void DlsStateMachineInit(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN STATE_MACHINE *Sm,
|
|
OUT STATE_MACHINE_FUNC Trans[])
|
|
{
|
|
UCHAR i;
|
|
|
|
StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG, (STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
|
|
|
|
// the first column
|
|
StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_REQ, (STATE_MACHINE_FUNC)MlmeDlsReqAction);
|
|
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_REQ, (STATE_MACHINE_FUNC)PeerDlsReqAction);
|
|
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_RSP, (STATE_MACHINE_FUNC)PeerDlsRspAction);
|
|
StateMachineSetAction(Sm, DLS_IDLE, MT2_MLME_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)MlmeDlsTearDownAction);
|
|
StateMachineSetAction(Sm, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN, (STATE_MACHINE_FUNC)PeerDlsTearDownAction);
|
|
|
|
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].pAd = pAd;
|
|
RTMPInitTimer(pAd, &pAd->StaCfg.DLSEntry[i].Timer, GET_TIMER_FUNCTION(DlsTimeoutAction), pAd, FALSE);
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID MlmeDlsReqAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen = 0;
|
|
HEADER_802_11 DlsReqHdr;
|
|
PRT_802_11_DLS pDLS = NULL;
|
|
UCHAR Category = CATEGORY_DLS;
|
|
UCHAR Action = ACTION_DLS_REQUEST;
|
|
ULONG tmp;
|
|
USHORT reason;
|
|
ULONG Timeout;
|
|
BOOLEAN TimerCancelled;
|
|
|
|
if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &reason))
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsReqAction() \n"));
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsReqAction() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
ActHeaderInit(pAd, &DlsReqHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
|
|
// Build basic frame first
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(HEADER_802_11), &DlsReqHdr,
|
|
1, &Category,
|
|
1, &Action,
|
|
6, &pDLS->MacAddr,
|
|
6, pAd->CurrentAddress,
|
|
2, &pAd->StaActive.CapabilityInfo,
|
|
2, &pDLS->TimeOut,
|
|
1, &SupRateIe,
|
|
1, &pAd->MlmeAux.SupRateLen,
|
|
pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
|
|
END_OF_ARGS);
|
|
|
|
if (pAd->MlmeAux.ExtRateLen != 0)
|
|
{
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &ExtRateIe,
|
|
1, &pAd->MlmeAux.ExtRateLen,
|
|
pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
|
|
END_OF_ARGS);
|
|
FrameLen += tmp;
|
|
}
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
|
|
{
|
|
UCHAR HtLen;
|
|
|
|
#ifdef RT_BIG_ENDIAN
|
|
HT_CAPABILITY_IE HtCapabilityTmp;
|
|
#endif
|
|
|
|
// add HT Capability IE
|
|
HtLen = sizeof(HT_CAPABILITY_IE);
|
|
#ifndef RT_BIG_ENDIAN
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &HtCapIe,
|
|
1, &HtLen,
|
|
HtLen, &pAd->CommonCfg.HtCapability,
|
|
END_OF_ARGS);
|
|
#else
|
|
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
|
|
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
|
|
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
|
|
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &HtCapIe,
|
|
1, &HtLen,
|
|
HtLen, &HtCapabilityTmp,
|
|
END_OF_ARGS);
|
|
#endif
|
|
FrameLen = FrameLen + tmp;
|
|
}
|
|
#endif // DOT11_N_SUPPORT //
|
|
|
|
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
|
|
Timeout = DLS_TIMEOUT;
|
|
RTMPSetTimer(&pDLS->Timer, Timeout);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID PeerDlsReqAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen = 0;
|
|
USHORT StatusCode = MLME_SUCCESS;
|
|
HEADER_802_11 DlsRspHdr;
|
|
UCHAR Category = CATEGORY_DLS;
|
|
UCHAR Action = ACTION_DLS_RESPONSE;
|
|
ULONG tmp;
|
|
USHORT CapabilityInfo;
|
|
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
|
|
USHORT DLSTimeOut;
|
|
SHORT i;
|
|
ULONG Timeout;
|
|
BOOLEAN TimerCancelled;
|
|
PRT_802_11_DLS pDLS = NULL;
|
|
UCHAR MaxSupportedRateIn500Kbps = 0;
|
|
UCHAR SupportedRatesLen;
|
|
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
|
|
UCHAR HtCapabilityLen;
|
|
HT_CAPABILITY_IE HtCapability;
|
|
|
|
if (!PeerDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &DLSTimeOut,
|
|
&SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
|
|
return;
|
|
|
|
// supported rates array may not be sorted. sort it and find the maximum rate
|
|
for (i = 0; i < SupportedRatesLen; i++)
|
|
{
|
|
if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
|
|
MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
if (!INFRA_ON(pAd))
|
|
{
|
|
StatusCode = MLME_REQUEST_DECLINED;
|
|
}
|
|
else if (!pAd->CommonCfg.bWmmCapable)
|
|
{
|
|
StatusCode = MLME_DEST_STA_IS_NOT_A_QSTA;
|
|
}
|
|
else if (!pAd->CommonCfg.bDLSCapable)
|
|
{
|
|
StatusCode = MLME_REQUEST_DECLINED;
|
|
}
|
|
else
|
|
{
|
|
// find table to update parameters
|
|
for (i = (MAX_NUM_OF_DLS_ENTRY-1); i >= 0; i--)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
|
|
else
|
|
{
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
}
|
|
|
|
pAd->StaCfg.DLSEntry[i].Sequence = 0;
|
|
pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
|
|
if (HtCapabilityLen != 0)
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
|
|
else
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
|
|
pDLS = &pAd->StaCfg.DLSEntry[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// can not find in table, create a new one
|
|
if (i < 0)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() can not find same entry \n"));
|
|
for (i=(MAX_NUM_OF_DLS_ENTRY - 1); i >= MAX_NUM_OF_INIT_DLS_ENTRY; i--)
|
|
{
|
|
if (!pAd->StaCfg.DLSEntry[i].Valid)
|
|
{
|
|
MAC_TABLE_ENTRY *pEntry;
|
|
UCHAR MaxSupportedRate = RATE_11;
|
|
|
|
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
|
|
}
|
|
else
|
|
{
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
}
|
|
|
|
pAd->StaCfg.DLSEntry[i].Sequence = 0;
|
|
pAd->StaCfg.DLSEntry[i].Valid = TRUE;
|
|
pAd->StaCfg.DLSEntry[i].TimeOut = DLSTimeOut;
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer = DLSTimeOut;
|
|
NdisMoveMemory(pAd->StaCfg.DLSEntry[i].MacAddr, SA, MAC_ADDR_LEN);
|
|
if (HtCapabilityLen != 0)
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
|
|
else
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
|
|
pDLS = &pAd->StaCfg.DLSEntry[i];
|
|
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
|
|
|
|
switch (MaxSupportedRateIn500Kbps)
|
|
{
|
|
case 108: MaxSupportedRate = RATE_54; break;
|
|
case 96: MaxSupportedRate = RATE_48; break;
|
|
case 72: MaxSupportedRate = RATE_36; break;
|
|
case 48: MaxSupportedRate = RATE_24; break;
|
|
case 36: MaxSupportedRate = RATE_18; break;
|
|
case 24: MaxSupportedRate = RATE_12; break;
|
|
case 18: MaxSupportedRate = RATE_9; break;
|
|
case 12: MaxSupportedRate = RATE_6; break;
|
|
case 22: MaxSupportedRate = RATE_11; break;
|
|
case 11: MaxSupportedRate = RATE_5_5; break;
|
|
case 4: MaxSupportedRate = RATE_2; break;
|
|
case 2: MaxSupportedRate = RATE_1; break;
|
|
default: MaxSupportedRate = RATE_11; break;
|
|
}
|
|
|
|
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
|
|
|
|
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->HTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MinHTPhyMode.field.BW = BW_20;
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
pEntry->HTCapability.MCSSet[0] = 0;
|
|
pEntry->HTCapability.MCSSet[1] = 0;
|
|
|
|
// If this Entry supports 802.11n, upgrade to HT rate.
|
|
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
|
|
{
|
|
UCHAR j, bitmask; //k,bitmask;
|
|
CHAR ii;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsReqAction() Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
|
|
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pAd->MacTab.fAnyStationNonGF = TRUE;
|
|
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
|
|
}
|
|
|
|
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW= BW_40;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
|
|
pAd->MacTab.fAnyStation20Only = TRUE;
|
|
}
|
|
|
|
// find max fixed rate
|
|
for (ii=15; ii>=0; ii--)
|
|
{
|
|
j = ii/8;
|
|
bitmask = (1<<(ii-(j*8)));
|
|
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MCS = ii;
|
|
break;
|
|
}
|
|
if (ii==0)
|
|
break;
|
|
}
|
|
|
|
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
|
|
{
|
|
|
|
printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
|
|
pAd->StaCfg.DesiredTransmitSetting.field.MCS);
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
|
|
{
|
|
// Fix MCS as HT Duplicated Mode
|
|
pEntry->MaxHTPhyMode.field.BW = 1;
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pEntry->MaxHTPhyMode.field.STBC = 0;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = 0;
|
|
pEntry->MaxHTPhyMode.field.MCS = 32;
|
|
}
|
|
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
|
|
{
|
|
// STA supports fixed MCS
|
|
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
}
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
|
|
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
|
|
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
|
|
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
|
|
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
|
|
if (HtCapability.HtCapInfo.ShortGIfor20)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
|
|
if (HtCapability.HtCapInfo.ShortGIfor40)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
|
|
if (HtCapability.HtCapInfo.TxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
|
|
if (HtCapability.HtCapInfo.RxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.PlusHTC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
|
|
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
|
|
|
|
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
|
|
}
|
|
#endif // DOT11_N_SUPPORT //
|
|
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
|
|
|
|
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
|
|
{
|
|
PUCHAR pTable;
|
|
UCHAR TableSize = 0;
|
|
|
|
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
|
|
pEntry->bAutoTxRateSwitch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
|
|
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
pEntry->bAutoTxRateSwitch = FALSE;
|
|
|
|
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
|
|
}
|
|
pEntry->RateLen = SupportedRatesLen;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
StatusCode = MLME_SUCCESS;
|
|
|
|
// can not find in table, create a new one
|
|
if (i < 0)
|
|
{
|
|
StatusCode = MLME_QOS_UNSPECIFY;
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsReqAction() DLSEntry table full(only can support %d DLS session) \n", MAX_NUM_OF_DLS_ENTRY - MAX_NUM_OF_INIT_DLS_ENTRY));
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsReqAction() use entry(%d) %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
i, SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
}
|
|
}
|
|
|
|
ActHeaderInit(pAd, &DlsRspHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
|
|
// Build basic frame first
|
|
if (StatusCode == MLME_SUCCESS)
|
|
{
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(HEADER_802_11), &DlsRspHdr,
|
|
1, &Category,
|
|
1, &Action,
|
|
2, &StatusCode,
|
|
6, SA,
|
|
6, pAd->CurrentAddress,
|
|
2, &pAd->StaActive.CapabilityInfo,
|
|
1, &SupRateIe,
|
|
1, &pAd->MlmeAux.SupRateLen,
|
|
pAd->MlmeAux.SupRateLen, pAd->MlmeAux.SupRate,
|
|
END_OF_ARGS);
|
|
|
|
if (pAd->MlmeAux.ExtRateLen != 0)
|
|
{
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &ExtRateIe,
|
|
1, &pAd->MlmeAux.ExtRateLen,
|
|
pAd->MlmeAux.ExtRateLen, pAd->MlmeAux.ExtRate,
|
|
END_OF_ARGS);
|
|
FrameLen += tmp;
|
|
}
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
|
|
{
|
|
UCHAR HtLen;
|
|
|
|
#ifdef RT_BIG_ENDIAN
|
|
HT_CAPABILITY_IE HtCapabilityTmp;
|
|
#endif
|
|
|
|
// add HT Capability IE
|
|
HtLen = sizeof(HT_CAPABILITY_IE);
|
|
#ifndef RT_BIG_ENDIAN
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &HtCapIe,
|
|
1, &HtLen,
|
|
HtLen, &pAd->CommonCfg.HtCapability,
|
|
END_OF_ARGS);
|
|
#else
|
|
NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen);
|
|
*(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo));
|
|
*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo));
|
|
|
|
MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp,
|
|
1, &HtCapIe,
|
|
1, &HtLen,
|
|
HtLen, &HtCapabilityTmp,
|
|
END_OF_ARGS);
|
|
#endif
|
|
FrameLen = FrameLen + tmp;
|
|
}
|
|
#endif // DOT11_N_SUPPORT //
|
|
|
|
if (pDLS && (pDLS->Status != DLS_FINISH))
|
|
{
|
|
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
|
|
Timeout = DLS_TIMEOUT;
|
|
RTMPSetTimer(&pDLS->Timer, Timeout);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(HEADER_802_11), &DlsRspHdr,
|
|
1, &Category,
|
|
1, &Action,
|
|
2, &StatusCode,
|
|
6, SA,
|
|
6, pAd->CurrentAddress,
|
|
END_OF_ARGS);
|
|
}
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID PeerDlsRspAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
USHORT CapabilityInfo;
|
|
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
|
|
USHORT StatusCode;
|
|
SHORT i;
|
|
BOOLEAN TimerCancelled;
|
|
UCHAR MaxSupportedRateIn500Kbps = 0;
|
|
UCHAR SupportedRatesLen;
|
|
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
|
|
UCHAR HtCapabilityLen;
|
|
HT_CAPABILITY_IE HtCapability;
|
|
|
|
if (!pAd->CommonCfg.bDLSCapable)
|
|
return;
|
|
|
|
if (!INFRA_ON(pAd))
|
|
return;
|
|
|
|
if (!PeerDlsRspSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &CapabilityInfo, &StatusCode,
|
|
&SupportedRatesLen, &SupportedRates[0], &HtCapabilityLen, &HtCapability))
|
|
return;
|
|
|
|
// supported rates array may not be sorted. sort it and find the maximum rate
|
|
for (i=0; i<SupportedRatesLen; i++)
|
|
{
|
|
if (MaxSupportedRateIn500Kbps < (SupportedRates[i] & 0x7f))
|
|
MaxSupportedRateIn500Kbps = SupportedRates[i] & 0x7f;
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d, CapabilityInfo=0x%x\n",
|
|
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode, CapabilityInfo));
|
|
|
|
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
if (StatusCode == MLME_SUCCESS)
|
|
{
|
|
MAC_TABLE_ENTRY *pEntry;
|
|
UCHAR MaxSupportedRate = RATE_11;
|
|
|
|
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
|
|
|
|
switch (MaxSupportedRateIn500Kbps)
|
|
{
|
|
case 108: MaxSupportedRate = RATE_54; break;
|
|
case 96: MaxSupportedRate = RATE_48; break;
|
|
case 72: MaxSupportedRate = RATE_36; break;
|
|
case 48: MaxSupportedRate = RATE_24; break;
|
|
case 36: MaxSupportedRate = RATE_18; break;
|
|
case 24: MaxSupportedRate = RATE_12; break;
|
|
case 18: MaxSupportedRate = RATE_9; break;
|
|
case 12: MaxSupportedRate = RATE_6; break;
|
|
case 22: MaxSupportedRate = RATE_11; break;
|
|
case 11: MaxSupportedRate = RATE_5_5; break;
|
|
case 4: MaxSupportedRate = RATE_2; break;
|
|
case 2: MaxSupportedRate = RATE_1; break;
|
|
default: MaxSupportedRate = RATE_11; break;
|
|
}
|
|
|
|
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
|
|
|
|
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->HTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MinHTPhyMode.field.BW = BW_20;
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
pEntry->HTCapability.MCSSet[0] = 0;
|
|
pEntry->HTCapability.MCSSet[1] = 0;
|
|
|
|
// If this Entry supports 802.11n, upgrade to HT rate.
|
|
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
|
|
{
|
|
UCHAR j, bitmask; //k,bitmask;
|
|
CHAR ii;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
|
|
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pAd->MacTab.fAnyStationNonGF = TRUE;
|
|
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
|
|
}
|
|
|
|
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW= BW_40;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
|
|
pAd->MacTab.fAnyStation20Only = TRUE;
|
|
}
|
|
|
|
// find max fixed rate
|
|
for (ii=15; ii>=0; ii--)
|
|
{
|
|
j = ii/8;
|
|
bitmask = (1<<(ii-(j*8)));
|
|
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MCS = ii;
|
|
break;
|
|
}
|
|
if (ii==0)
|
|
break;
|
|
}
|
|
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
|
|
{
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
|
|
{
|
|
// Fix MCS as HT Duplicated Mode
|
|
pEntry->MaxHTPhyMode.field.BW = 1;
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pEntry->MaxHTPhyMode.field.STBC = 0;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = 0;
|
|
pEntry->MaxHTPhyMode.field.MCS = 32;
|
|
}
|
|
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
|
|
{
|
|
// STA supports fixed MCS
|
|
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
}
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
|
|
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
|
|
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
|
|
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
|
|
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
|
|
if (HtCapability.HtCapInfo.ShortGIfor20)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
|
|
if (HtCapability.HtCapInfo.ShortGIfor40)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
|
|
if (HtCapability.HtCapInfo.TxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
|
|
if (HtCapability.HtCapInfo.RxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.PlusHTC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
|
|
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
|
|
|
|
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
|
|
}
|
|
#endif // DOT11_N_SUPPORT //
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
|
|
|
|
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
|
|
{
|
|
PUCHAR pTable;
|
|
UCHAR TableSize = 0;
|
|
|
|
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
|
|
pEntry->bAutoTxRateSwitch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
|
|
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
pEntry->bAutoTxRateSwitch = FALSE;
|
|
|
|
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
|
|
}
|
|
pEntry->RateLen = SupportedRatesLen;
|
|
|
|
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
|
|
{
|
|
// If support WPA or WPA2, start STAKey hand shake,
|
|
// If failed hand shake, just tear down peer DLS
|
|
if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
|
|
{
|
|
MLME_DLS_REQ_STRUCT MlmeDlsReq;
|
|
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
|
|
|
|
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
|
|
}
|
|
else
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
}
|
|
|
|
//initialize seq no for DLS frames.
|
|
pAd->StaCfg.DLSEntry[i].Sequence = 0;
|
|
if (HtCapabilityLen != 0)
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
|
|
else
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// DLS setup procedure failed.
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i >= MAX_NUM_OF_INIT_DLS_ENTRY)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() update timeout value \n"));
|
|
for (i=(MAX_NUM_OF_DLS_ENTRY-1); i>=MAX_NUM_OF_INIT_DLS_ENTRY; i--)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
if (StatusCode == MLME_SUCCESS)
|
|
{
|
|
MAC_TABLE_ENTRY *pEntry;
|
|
UCHAR MaxSupportedRate = RATE_11;
|
|
|
|
pEntry = MacTableInsertDlsEntry(pAd, SA, i);
|
|
|
|
switch (MaxSupportedRateIn500Kbps)
|
|
{
|
|
case 108: MaxSupportedRate = RATE_54; break;
|
|
case 96: MaxSupportedRate = RATE_48; break;
|
|
case 72: MaxSupportedRate = RATE_36; break;
|
|
case 48: MaxSupportedRate = RATE_24; break;
|
|
case 36: MaxSupportedRate = RATE_18; break;
|
|
case 24: MaxSupportedRate = RATE_12; break;
|
|
case 18: MaxSupportedRate = RATE_9; break;
|
|
case 12: MaxSupportedRate = RATE_6; break;
|
|
case 22: MaxSupportedRate = RATE_11; break;
|
|
case 11: MaxSupportedRate = RATE_5_5; break;
|
|
case 4: MaxSupportedRate = RATE_2; break;
|
|
case 2: MaxSupportedRate = RATE_1; break;
|
|
default: MaxSupportedRate = RATE_11; break;
|
|
}
|
|
|
|
pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate);
|
|
|
|
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MaxHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->MinHTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
pEntry->HTPhyMode.field.MODE = MODE_CCK;
|
|
pEntry->HTPhyMode.field.MCS = pEntry->MaxSupportedRate;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MaxHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->MinHTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->MinHTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
pEntry->HTPhyMode.field.MODE = MODE_OFDM;
|
|
pEntry->HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pEntry->MaxSupportedRate];
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MinHTPhyMode.field.BW = BW_20;
|
|
|
|
#ifdef DOT11_N_SUPPORT
|
|
pEntry->HTCapability.MCSSet[0] = 0;
|
|
pEntry->HTCapability.MCSSet[1] = 0;
|
|
|
|
// If this Entry supports 802.11n, upgrade to HT rate.
|
|
if ((HtCapabilityLen != 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
|
|
{
|
|
UCHAR j, bitmask; //k,bitmask;
|
|
CHAR ii;
|
|
|
|
DBGPRINT(RT_DEBUG_OFF, ("DLS - PeerDlsRspAction Receive Peer HT Capable STA from %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
|
|
if ((HtCapability.HtCapInfo.GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTGREENFIELD;
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pAd->MacTab.fAnyStationNonGF = TRUE;
|
|
pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1;
|
|
}
|
|
|
|
if ((HtCapability.HtCapInfo.ChannelWidth) && (pAd->CommonCfg.DesiredHtPhy.ChannelWidth))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW= BW_40;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor40)&(HtCapability.HtCapInfo.ShortGIfor40));
|
|
}
|
|
else
|
|
{
|
|
pEntry->MaxHTPhyMode.field.BW = BW_20;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = ((pAd->CommonCfg.DesiredHtPhy.ShortGIfor20)&(HtCapability.HtCapInfo.ShortGIfor20));
|
|
pAd->MacTab.fAnyStation20Only = TRUE;
|
|
}
|
|
|
|
// find max fixed rate
|
|
for (ii=15; ii>=0; ii--)
|
|
{
|
|
j = ii/8;
|
|
bitmask = (1<<(ii-(j*8)));
|
|
if ( (pAd->StaCfg.DesiredHtPhyInfo.MCSSet[j]&bitmask) && (HtCapability.MCSSet[j]&bitmask))
|
|
{
|
|
pEntry->MaxHTPhyMode.field.MCS = ii;
|
|
break;
|
|
}
|
|
if (ii==0)
|
|
break;
|
|
}
|
|
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS != MCS_AUTO)
|
|
{
|
|
printk("@@@ pAd->CommonCfg.RegTransmitSetting.field.MCS = %d\n",
|
|
pAd->StaCfg.DesiredTransmitSetting.field.MCS);
|
|
if (pAd->StaCfg.DesiredTransmitSetting.field.MCS == 32)
|
|
{
|
|
// Fix MCS as HT Duplicated Mode
|
|
pEntry->MaxHTPhyMode.field.BW = 1;
|
|
pEntry->MaxHTPhyMode.field.MODE = MODE_HTMIX;
|
|
pEntry->MaxHTPhyMode.field.STBC = 0;
|
|
pEntry->MaxHTPhyMode.field.ShortGI = 0;
|
|
pEntry->MaxHTPhyMode.field.MCS = 32;
|
|
}
|
|
else if (pEntry->MaxHTPhyMode.field.MCS > pAd->StaCfg.HTPhyMode.field.MCS)
|
|
{
|
|
// STA supports fixed MCS
|
|
pEntry->MaxHTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
}
|
|
}
|
|
|
|
pEntry->MaxHTPhyMode.field.STBC = (HtCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC));
|
|
pEntry->MpduDensity = HtCapability.HtCapParm.MpduDensity;
|
|
pEntry->MaxRAmpduFactor = HtCapability.HtCapParm.MaxRAmpduFactor;
|
|
pEntry->MmpsMode = (UCHAR)HtCapability.HtCapInfo.MimoPs;
|
|
pEntry->AMsduSize = (UCHAR)HtCapability.HtCapInfo.AMsduSize;
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
|
|
if (HtCapability.HtCapInfo.ShortGIfor20)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE);
|
|
if (HtCapability.HtCapInfo.ShortGIfor40)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE);
|
|
if (HtCapability.HtCapInfo.TxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_TxSTBC_CAPABLE);
|
|
if (HtCapability.HtCapInfo.RxSTBC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RxSTBC_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.PlusHTC)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HTC_CAPABLE);
|
|
if (pAd->CommonCfg.bRdg && HtCapability.ExtHtCapInfo.RDGSupport)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE);
|
|
if (HtCapability.ExtHtCapInfo.MCSFeedback == 0x03)
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_MCSFEEDBACK_CAPABLE);
|
|
|
|
NdisMoveMemory(&pEntry->HTCapability, &HtCapability, sizeof(HT_CAPABILITY_IE));
|
|
}
|
|
#endif // DOT11_N_SUPPORT //
|
|
|
|
pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word;
|
|
pEntry->CurrTxRate = pEntry->MaxSupportedRate;
|
|
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE);
|
|
|
|
if (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
|
|
{
|
|
PUCHAR pTable;
|
|
UCHAR TableSize = 0;
|
|
|
|
MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &pEntry->CurrTxRateIndex);
|
|
pEntry->bAutoTxRateSwitch = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
|
|
pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
|
|
pEntry->bAutoTxRateSwitch = FALSE;
|
|
|
|
RTMPUpdateLegacyTxSetting((UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode, pEntry);
|
|
}
|
|
pEntry->RateLen = SupportedRatesLen;
|
|
|
|
if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
|
|
{
|
|
// If support WPA or WPA2, start STAKey hand shake,
|
|
// If failed hand shake, just tear down peer DLS
|
|
if (RTMPSendSTAKeyRequest(pAd, pAd->StaCfg.DLSEntry[i].MacAddr) != NDIS_STATUS_SUCCESS)
|
|
{
|
|
MLME_DLS_REQ_STRUCT MlmeDlsReq;
|
|
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
|
|
|
|
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed when call RTMPSendSTAKeyRequest \n"));
|
|
}
|
|
else
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_WAIT_KEY;
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - waiting for STAKey handshake procedure\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x Succeed with WEP or no security\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
|
|
}
|
|
pAd->StaCfg.DLSEntry[i].Sequence = 0;
|
|
if (HtCapabilityLen != 0)
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = TRUE;
|
|
else
|
|
pAd->StaCfg.DLSEntry[i].bHTCap = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// DLS setup procedure failed.
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - PeerDlsRspAction failed with StatusCode=%d \n", StatusCode));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID MlmeDlsTearDownAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen = 0;
|
|
UCHAR Category = CATEGORY_DLS;
|
|
UCHAR Action = ACTION_DLS_TEARDOWN;
|
|
USHORT ReasonCode = REASON_QOS_UNSPECIFY;
|
|
HEADER_802_11 DlsTearDownHdr;
|
|
PRT_802_11_DLS pDLS;
|
|
BOOLEAN TimerCancelled;
|
|
UCHAR i;
|
|
|
|
if(!MlmeDlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pDLS, &ReasonCode))
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - MlmeDlsTearDownAction() with ReasonCode=%d \n", ReasonCode));
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,("DLS - MlmeDlsTearDownAction() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
|
|
// Build basic frame first
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(HEADER_802_11), &DlsTearDownHdr,
|
|
1, &Category,
|
|
1, &Action,
|
|
6, &pDLS->MacAddr,
|
|
6, pAd->CurrentAddress,
|
|
2, &ReasonCode,
|
|
END_OF_ARGS);
|
|
|
|
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
RTMPCancelTimer(&pDLS->Timer, &TimerCancelled);
|
|
|
|
// Remove key in local dls table entry
|
|
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
|
|
// clear peer dls table entry
|
|
for (i = MAX_NUM_OF_INIT_DLS_ENTRY; i < MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if (MAC_ADDR_EQUAL(pDLS->MacAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID PeerDlsTearDownAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN MLME_QUEUE_ELEM *Elem)
|
|
{
|
|
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
|
|
USHORT ReasonCode;
|
|
UINT i;
|
|
BOOLEAN TimerCancelled;
|
|
|
|
if (!pAd->CommonCfg.bDLSCapable)
|
|
return;
|
|
|
|
if (!INFRA_ON(pAd))
|
|
return;
|
|
|
|
if (!PeerDlsTearDownSanity(pAd, Elem->Msg, Elem->MsgLen, DA, SA, &ReasonCode))
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n", SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
|
|
|
|
// clear local dls table entry
|
|
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
//AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
|
|
//AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
|
|
// clear peer dls table entry
|
|
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(SA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
//AsicDelWcidTab(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
|
|
//AsicRemovePairwiseKeyEntry(pAd, BSS0, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID);
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPCheckDLSTimeOut(
|
|
IN PRTMP_ADAPTER pAd)
|
|
{
|
|
ULONG i;
|
|
MLME_DLS_REQ_STRUCT MlmeDlsReq;
|
|
USHORT reason = REASON_QOS_UNSPECIFY;
|
|
|
|
if (! pAd->CommonCfg.bDLSCapable)
|
|
return;
|
|
|
|
if (! INFRA_ON(pAd))
|
|
return;
|
|
|
|
// If timeout value is equaled to zero, it means always not be timeout.
|
|
|
|
// update local dls table entry
|
|
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
&& (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer --;
|
|
|
|
if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
|
|
{
|
|
reason = REASON_QOS_REQUEST_TIMEOUT;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
}
|
|
}
|
|
}
|
|
|
|
// update peer dls table entry
|
|
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
&& (pAd->StaCfg.DLSEntry[i].TimeOut != 0))
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer --;
|
|
|
|
if (pAd->StaCfg.DLSEntry[i].CountDownTimer == 0)
|
|
{
|
|
reason = REASON_QOS_REQUEST_TIMEOUT;
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
BOOLEAN RTMPRcvFrameDLSCheck(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PHEADER_802_11 pHeader,
|
|
IN ULONG Len,
|
|
IN PRT28XX_RXD_STRUC pRxD)
|
|
{
|
|
ULONG i;
|
|
BOOLEAN bFindEntry = FALSE;
|
|
BOOLEAN bSTAKeyFrame = FALSE;
|
|
PEAPOL_PACKET pEap;
|
|
PUCHAR pProto, pAddr = NULL;
|
|
PUCHAR pSTAKey = NULL;
|
|
UCHAR ZeroReplay[LEN_KEY_DESC_REPLAY];
|
|
UCHAR Mic[16], OldMic[16];
|
|
UCHAR digest[80];
|
|
UCHAR DlsPTK[80];
|
|
UCHAR temp[64];
|
|
BOOLEAN TimerCancelled;
|
|
CIPHER_KEY PairwiseKey;
|
|
|
|
|
|
if (! pAd->CommonCfg.bDLSCapable)
|
|
return bSTAKeyFrame;
|
|
|
|
if (! INFRA_ON(pAd))
|
|
return bSTAKeyFrame;
|
|
|
|
if (! (pHeader->FC.SubType & 0x08))
|
|
return bSTAKeyFrame;
|
|
|
|
if (Len < LENGTH_802_11 + 6 + 2 + 2)
|
|
return bSTAKeyFrame;
|
|
|
|
pProto = (PUCHAR)pHeader + LENGTH_802_11 + 2 + 6; // QOS Control field , 0xAA 0xAA 0xAA 0x00 0x00 0x00
|
|
pAddr = pHeader->Addr2;
|
|
|
|
// L2PAD bit on will pad 2 bytes at LLC
|
|
if (pRxD->L2PAD)
|
|
{
|
|
pProto += 2;
|
|
}
|
|
|
|
if (RTMPEqualMemory(EAPOL, pProto, 2) && (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA))
|
|
{
|
|
pEap = (PEAPOL_PACKET) (pProto + 2);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff Len=%ld, DataLen=%d, KeyMic=%d, Install=%d, KeyAck=%d, Secure=%d, EKD_DL=%d, Error=%d, Request=%d\n", Len,
|
|
(LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16),
|
|
pEap->KeyDesc.KeyInfo.KeyMic,
|
|
pEap->KeyDesc.KeyInfo.Install,
|
|
pEap->KeyDesc.KeyInfo.KeyAck,
|
|
pEap->KeyDesc.KeyInfo.Secure,
|
|
pEap->KeyDesc.KeyInfo.EKD_DL,
|
|
pEap->KeyDesc.KeyInfo.Error,
|
|
pEap->KeyDesc.KeyInfo.Request));
|
|
|
|
if ((Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE + 16)) && pEap->KeyDesc.KeyInfo.KeyMic
|
|
&& pEap->KeyDesc.KeyInfo.Install && pEap->KeyDesc.KeyInfo.KeyAck && pEap->KeyDesc.KeyInfo.Secure
|
|
&& pEap->KeyDesc.KeyInfo.EKD_DL && !pEap->KeyDesc.KeyInfo.Error && !pEap->KeyDesc.KeyInfo.Request)
|
|
{
|
|
// First validate replay counter, only accept message with larger replay counter
|
|
// Let equal pass, some AP start with all zero replay counter
|
|
NdisZeroMemory(ZeroReplay, LEN_KEY_DESC_REPLAY);
|
|
if ((RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, pAd->StaCfg.ReplayCounter, LEN_KEY_DESC_REPLAY) != 1) &&
|
|
(RTMPCompareMemory(pEap->KeyDesc.ReplayCounter, ZeroReplay, LEN_KEY_DESC_REPLAY) != 0))
|
|
return bSTAKeyFrame;
|
|
|
|
//RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter (%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
|
|
pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
|
|
pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
|
|
pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
|
|
|
|
// put these code segment to get the replay counter
|
|
if (pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED)
|
|
return bSTAKeyFrame;
|
|
|
|
// Check MIC value
|
|
// Save the MIC and replace with zero
|
|
// use proprietary PTK
|
|
NdisZeroMemory(temp, 64);
|
|
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
|
|
WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
|
|
|
|
NdisMoveMemory(OldMic, pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
|
|
NdisZeroMemory(pEap->KeyDesc.KeyMic, LEN_KEY_DESC_MIC);
|
|
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
|
|
{
|
|
// AES
|
|
HMAC_SHA1((PUCHAR) pEap, pEap->Body_Len[1] + 4, DlsPTK, LEN_EAP_MICK, digest);
|
|
NdisMoveMemory(Mic, digest, LEN_KEY_DESC_MIC);
|
|
}
|
|
else
|
|
{
|
|
hmac_md5(DlsPTK, LEN_EAP_MICK, (PUCHAR) pEap, pEap->Body_Len[1] + 4, Mic);
|
|
}
|
|
|
|
if (!NdisEqualMemory(OldMic, Mic, LEN_KEY_DESC_MIC))
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("MIC Different in Msg1 of STAKey handshake! \n"));
|
|
return bSTAKeyFrame;
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_TRACE, ("MIC VALID in Msg1 of STAKey handshake! \n"));
|
|
#if 1
|
|
if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0C)
|
|
&& (pEap->KeyDesc.KeyData[4] == 0x43) && (pEap->KeyDesc.KeyData[5] == 0x02))
|
|
{
|
|
pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
|
|
pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%ld, KeyDataLen=%d\n",
|
|
pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
|
|
|
|
bSTAKeyFrame = TRUE;
|
|
}
|
|
#else
|
|
if ((pEap->KeyDesc.KeyData[0] == 0xDD) && (pEap->KeyDesc.KeyData[2] == 0x00) && (pEap->KeyDesc.KeyData[3] == 0x0F)
|
|
&& (pEap->KeyDesc.KeyData[4] == 0xAC) && (pEap->KeyDesc.KeyData[5] == 0x02))
|
|
{
|
|
pAddr = pEap->KeyDesc.KeyData + 8; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2)
|
|
pSTAKey = pEap->KeyDesc.KeyData + 14; // Tpe(1), Len(1), OUI(3), DataType(1), Reserved(2), STAKey_Mac_Addr(6)
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 from %02x:%02x:%02x:%02x:%02x:%02x Len=%d, KeyDataLen=%d\n",
|
|
pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5], Len, pEap->KeyDesc.KeyData[1]));
|
|
|
|
bSTAKeyFrame = TRUE;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
else if (Len >= (LENGTH_802_11 + 6 + 2 + 2 + sizeof(EAPOL_PACKET) - MAX_LEN_OF_RSNIE))
|
|
{
|
|
#if 0
|
|
RTMPMoveMemory(pAd->StaCfg.ReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
|
|
#endif
|
|
RTMPMoveMemory(pAd->StaCfg.DlsReplayCounter, pEap->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Sniff replay counter 2(%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x) Len=%ld, KeyDataLen=%d\n",
|
|
pAd->StaCfg.ReplayCounter[0], pAd->StaCfg.ReplayCounter[1], pAd->StaCfg.ReplayCounter[2],
|
|
pAd->StaCfg.ReplayCounter[3], pAd->StaCfg.ReplayCounter[4], pAd->StaCfg.ReplayCounter[5],
|
|
pAd->StaCfg.ReplayCounter[6], pAd->StaCfg.ReplayCounter[7], Len, pEap->KeyDesc.KeyData[1]));
|
|
|
|
}
|
|
}
|
|
|
|
// If timeout value is equaled to zero, it means always not be timeout.
|
|
// update local dls table entry
|
|
for (i= 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
if (bSTAKeyFrame)
|
|
{
|
|
PMAC_TABLE_ENTRY pEntry;
|
|
|
|
// STAKey frame, add pairwise key table
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
|
|
PairwiseKey.KeyLen = LEN_TKIP_EK;
|
|
NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
|
|
NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
|
|
NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
|
|
|
|
PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
|
|
|
|
pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
|
|
//AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
|
|
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
|
|
// Add Pair-wise key to Asic
|
|
AsicAddPairwiseKeyEntry(pAd,
|
|
pAd->StaCfg.DLSEntry[i].MacAddr,
|
|
(UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
|
|
&PairwiseKey);
|
|
|
|
RTMPAddWcidAttributeEntry(pAd,
|
|
BSS0,
|
|
0,
|
|
PairwiseKey.CipherAlg,
|
|
pEntry);
|
|
|
|
NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Peer STA MAC Address STAKey) \n"));
|
|
|
|
RTMPSendSTAKeyHandShake(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Initiator side)\n"));
|
|
}
|
|
else
|
|
{
|
|
// Data frame, update timeout value
|
|
if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
|
|
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
|
|
}
|
|
}
|
|
|
|
bFindEntry = TRUE;
|
|
}
|
|
}
|
|
|
|
// update peer dls table entry
|
|
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && MAC_ADDR_EQUAL(pAddr, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
if (bSTAKeyFrame)
|
|
{
|
|
PMAC_TABLE_ENTRY pEntry = NULL;
|
|
|
|
// STAKey frame, add pairwise key table, and send STAkey Msg-2
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_FINISH;
|
|
RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &TimerCancelled);
|
|
|
|
PairwiseKey.KeyLen = LEN_TKIP_EK;
|
|
NdisMoveMemory(PairwiseKey.Key, &pSTAKey[0], LEN_TKIP_EK);
|
|
NdisMoveMemory(PairwiseKey.TxMic, &pSTAKey[16], LEN_TKIP_RXMICK);
|
|
NdisMoveMemory(PairwiseKey.RxMic, &pSTAKey[24], LEN_TKIP_TXMICK);
|
|
|
|
PairwiseKey.CipherAlg = pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg;
|
|
|
|
pEntry = DlsEntryTableLookup(pAd, pAd->StaCfg.DLSEntry[i].MacAddr, TRUE);
|
|
//AsicAddKeyEntry(pAd, (USHORT)(i + 2), BSS0, 0, &PairwiseKey, TRUE, TRUE); // reserve 0 for multicast, 1 for unicast
|
|
//AsicUpdateRxWCIDTable(pAd, (USHORT)(i + 2), pAddr);
|
|
// Add Pair-wise key to Asic
|
|
AsicAddPairwiseKeyEntry(pAd,
|
|
pAd->StaCfg.DLSEntry[i].MacAddr,
|
|
(UCHAR)pAd->StaCfg.DLSEntry[i].MacTabMatchWCID,
|
|
&PairwiseKey);
|
|
|
|
RTMPAddWcidAttributeEntry(pAd,
|
|
BSS0,
|
|
0,
|
|
PairwiseKey.CipherAlg,
|
|
pEntry);
|
|
NdisMoveMemory(&pEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Receive STAKey Message-1 (Initiator STA MAC Address STAKey)\n"));
|
|
|
|
// If support WPA or WPA2, start STAKey hand shake,
|
|
// If failed hand shake, just tear down peer DLS
|
|
if (RTMPSendSTAKeyHandShake(pAd, pAddr) != NDIS_STATUS_SUCCESS)
|
|
{
|
|
MLME_DLS_REQ_STRUCT MlmeDlsReq;
|
|
USHORT reason = REASON_QOS_CIPHER_NOT_SUPPORT;
|
|
|
|
pAd->StaCfg.DLSEntry[i].Valid = FALSE;
|
|
pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
|
|
DlsParmFill(pAd, &MlmeDlsReq, &pAd->StaCfg.DLSEntry[i], reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - Finish STAKey handshake procedure (Peer side)\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Data frame, update timeout value
|
|
if (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
{
|
|
pAd->StaCfg.DLSEntry[i].CountDownTimer = pAd->StaCfg.DLSEntry[i].TimeOut;
|
|
}
|
|
}
|
|
|
|
bFindEntry = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
return bSTAKeyFrame;
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Check if the frame can be sent through DLS direct link interface
|
|
|
|
Arguments:
|
|
pAd Pointer to adapter
|
|
|
|
Return Value:
|
|
DLS entry index
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
INT RTMPCheckDLSFrame(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA)
|
|
{
|
|
INT rval = -1;
|
|
INT i;
|
|
|
|
if (!pAd->CommonCfg.bDLSCapable)
|
|
return rval;
|
|
|
|
if (!INFRA_ON(pAd))
|
|
return rval;
|
|
|
|
do{
|
|
// check local dls table entry
|
|
for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
|
|
MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
rval = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// check peer dls table entry
|
|
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH) &&
|
|
MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
rval = i;
|
|
break;
|
|
}
|
|
}
|
|
} while (FALSE);
|
|
|
|
return rval;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPSendDLSTearDownFrame(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA)
|
|
{
|
|
PUCHAR pOutBuffer = NULL;
|
|
NDIS_STATUS NStatus;
|
|
HEADER_802_11 DlsTearDownHdr;
|
|
ULONG FrameLen = 0;
|
|
USHORT Reason = REASON_QOS_QSTA_LEAVING_QBSS;
|
|
UCHAR Category = CATEGORY_DLS;
|
|
UCHAR Action = ACTION_DLS_TEARDOWN;
|
|
UCHAR i = 0;
|
|
|
|
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
|
|
RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
|
|
return;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame \n"));
|
|
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR,("ASSOC - RTMPSendDLSTearDownFrame() allocate memory failed \n"));
|
|
return;
|
|
}
|
|
|
|
ActHeaderInit(pAd, &DlsTearDownHdr, pAd->CommonCfg.Bssid, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(HEADER_802_11), &DlsTearDownHdr,
|
|
1, &Category,
|
|
1, &Action,
|
|
6, pDA,
|
|
6, pAd->CurrentAddress,
|
|
2, &Reason,
|
|
END_OF_ARGS);
|
|
|
|
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
// Remove key in local dls table entry
|
|
for (i = 0; i < MAX_NUM_OF_INIT_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
&& MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
|
|
// Remove key in peer dls table entry
|
|
for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH)
|
|
&& MAC_ADDR_EQUAL(pDA, pAd->StaCfg.DLSEntry[i].MacAddr))
|
|
{
|
|
MacTableDeleteDlsEntry(pAd, pAd->StaCfg.DLSEntry[i].MacTabMatchWCID, pAd->StaCfg.DLSEntry[i].MacAddr);
|
|
}
|
|
}
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Send DLS TearDown Frame and remove key in (i=%d) \n", i));
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
NDIS_STATUS RTMPSendSTAKeyRequest(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA)
|
|
{
|
|
UCHAR Header802_3[14];
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen = 0;
|
|
EAPOL_PACKET Packet;
|
|
UCHAR Mic[16];
|
|
UCHAR digest[80];
|
|
PUCHAR pOutBuffer = NULL;
|
|
PNDIS_PACKET pNdisPacket;
|
|
UCHAR temp[64];
|
|
UCHAR DlsPTK[80];
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyRequest() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
|
|
|
|
pAd->Sequence ++;
|
|
MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
|
|
|
|
// Zero message body
|
|
NdisZeroMemory(&Packet, sizeof(Packet));
|
|
Packet.ProVer = EAPOL_VER;
|
|
Packet.ProType = EAPOLKey;
|
|
Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE andPeer MAC address
|
|
|
|
// STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
|
|
if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
|
|
{
|
|
Packet.KeyDesc.Type = WPA1_KEY_DESC;
|
|
}
|
|
else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
|
|
{
|
|
Packet.KeyDesc.Type = WPA2_KEY_DESC;
|
|
}
|
|
|
|
// Key descriptor version
|
|
Packet.KeyDesc.KeyInfo.KeyDescVer =
|
|
(((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
|
|
|
|
Packet.KeyDesc.KeyInfo.KeyMic = 1;
|
|
Packet.KeyDesc.KeyInfo.Secure = 1;
|
|
Packet.KeyDesc.KeyInfo.Request = 1;
|
|
|
|
Packet.KeyDesc.KeyDataLen[1] = 12;
|
|
|
|
// use our own OUI to distinguish proprietary with standard.
|
|
Packet.KeyDesc.KeyData[0] = 0xDD;
|
|
Packet.KeyDesc.KeyData[1] = 0x0A;
|
|
Packet.KeyDesc.KeyData[2] = 0x00;
|
|
Packet.KeyDesc.KeyData[3] = 0x0C;
|
|
Packet.KeyDesc.KeyData[4] = 0x43;
|
|
Packet.KeyDesc.KeyData[5] = 0x03;
|
|
NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
|
|
|
|
NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
|
|
// Allocate buffer for transmitting message
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
return NStatus;
|
|
|
|
// Prepare EAPOL frame for MIC calculation
|
|
// Be careful, only EAPOL frame is counted for MIC calculation
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
Packet.Body_Len[1] + 4, &Packet,
|
|
END_OF_ARGS);
|
|
|
|
// use proprietary PTK
|
|
NdisZeroMemory(temp, 64);
|
|
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
|
|
WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
|
|
|
|
// calculate MIC
|
|
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
|
|
{
|
|
// AES
|
|
NdisZeroMemory(digest, sizeof(digest));
|
|
HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
|
|
NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory(Mic, sizeof(Mic));
|
|
hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
|
|
NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
|
|
}
|
|
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(Header802_3), Header802_3,
|
|
Packet.Body_Len[1] + 4, &Packet,
|
|
END_OF_ARGS);
|
|
|
|
NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
|
|
if (NStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
|
|
STASendPacket(pAd, pNdisPacket);
|
|
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
|
|
}
|
|
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyRequest- Send STAKey request (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
|
|
|
|
return NStatus;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
|
|
IRQL = DISPATCH_LEVEL
|
|
|
|
==========================================================================
|
|
*/
|
|
NDIS_STATUS RTMPSendSTAKeyHandShake(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pDA)
|
|
{
|
|
UCHAR Header802_3[14];
|
|
NDIS_STATUS NStatus;
|
|
ULONG FrameLen = 0;
|
|
EAPOL_PACKET Packet;
|
|
UCHAR Mic[16];
|
|
UCHAR digest[80];
|
|
PUCHAR pOutBuffer = NULL;
|
|
PNDIS_PACKET pNdisPacket;
|
|
UCHAR temp[64];
|
|
UCHAR DlsPTK[80]; // Due to dirver can not get PTK, use proprietary PTK
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE,("DLS - RTMPSendSTAKeyHandShake() to %02x:%02x:%02x:%02x:%02x:%02x\n", pDA[0], pDA[1], pDA[2], pDA[3], pDA[4], pDA[5]));
|
|
|
|
pAd->Sequence ++;
|
|
MAKE_802_3_HEADER(Header802_3, pAd->CommonCfg.Bssid, pAd->CurrentAddress, EAPOL);
|
|
|
|
// Zero message body
|
|
NdisZeroMemory(&Packet, sizeof(Packet));
|
|
Packet.ProVer = EAPOL_VER;
|
|
Packet.ProType = EAPOLKey;
|
|
Packet.Body_Len[1] = sizeof(KEY_DESCRIPTER) - MAX_LEN_OF_RSNIE + 6 + MAC_ADDR_LEN; // data field contain KDE and Peer MAC address
|
|
|
|
// STAKey Message is as EAPOL-Key(1,1,0,0,G/0,0,0, MIC, 0,Peer MAC KDE)
|
|
if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
|
|
{
|
|
Packet.KeyDesc.Type = WPA1_KEY_DESC;
|
|
}
|
|
else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
|
|
{
|
|
Packet.KeyDesc.Type = WPA2_KEY_DESC;
|
|
}
|
|
|
|
// Key descriptor version
|
|
Packet.KeyDesc.KeyInfo.KeyDescVer =
|
|
(((pAd->StaCfg.PairCipher == Ndis802_11Encryption3Enabled) || (pAd->StaCfg.GroupCipher == Ndis802_11Encryption3Enabled)) ? (DESC_TYPE_AES) : (DESC_TYPE_TKIP));
|
|
|
|
Packet.KeyDesc.KeyInfo.KeyMic = 1;
|
|
Packet.KeyDesc.KeyInfo.Secure = 1;
|
|
|
|
Packet.KeyDesc.KeyDataLen[1] = 12;
|
|
|
|
// use our own OUI to distinguish proprietary with standard.
|
|
Packet.KeyDesc.KeyData[0] = 0xDD;
|
|
Packet.KeyDesc.KeyData[1] = 0x0A;
|
|
Packet.KeyDesc.KeyData[2] = 0x00;
|
|
Packet.KeyDesc.KeyData[3] = 0x0C;
|
|
Packet.KeyDesc.KeyData[4] = 0x43;
|
|
Packet.KeyDesc.KeyData[5] = 0x03;
|
|
NdisMoveMemory(&Packet.KeyDesc.KeyData[6], pDA, MAC_ADDR_LEN);
|
|
|
|
NdisMoveMemory(Packet.KeyDesc.ReplayCounter, pAd->StaCfg.DlsReplayCounter, LEN_KEY_DESC_REPLAY);
|
|
|
|
// Allocate buffer for transmitting message
|
|
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
|
|
if (NStatus != NDIS_STATUS_SUCCESS)
|
|
return NStatus;
|
|
|
|
// Prepare EAPOL frame for MIC calculation
|
|
// Be careful, only EAPOL frame is counted for MIC calculation
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
Packet.Body_Len[1] + 4, &Packet,
|
|
END_OF_ARGS);
|
|
|
|
// use proprietary PTK
|
|
NdisZeroMemory(temp, 64);
|
|
NdisMoveMemory(temp, "IEEE802.11 WIRELESS ACCESS POINT", 32);
|
|
WpaCountPTK(pAd, temp, temp, pAd->CommonCfg.Bssid, temp, pAd->CurrentAddress, DlsPTK, LEN_PTK);
|
|
|
|
// calculate MIC
|
|
if (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled)
|
|
{
|
|
// AES
|
|
NdisZeroMemory(digest, sizeof(digest));
|
|
HMAC_SHA1(pOutBuffer, FrameLen, DlsPTK, LEN_EAP_MICK, digest);
|
|
NdisMoveMemory(Packet.KeyDesc.KeyMic, digest, LEN_KEY_DESC_MIC);
|
|
}
|
|
else
|
|
{
|
|
NdisZeroMemory(Mic, sizeof(Mic));
|
|
hmac_md5(DlsPTK, LEN_EAP_MICK, pOutBuffer, FrameLen, Mic);
|
|
NdisMoveMemory(Packet.KeyDesc.KeyMic, Mic, LEN_KEY_DESC_MIC);
|
|
}
|
|
|
|
MakeOutgoingFrame(pOutBuffer, &FrameLen,
|
|
sizeof(Header802_3), Header802_3,
|
|
Packet.Body_Len[1] + 4, &Packet,
|
|
END_OF_ARGS);
|
|
|
|
NStatus = RTMPAllocateNdisPacket(pAd, &pNdisPacket, NULL, 0, pOutBuffer, FrameLen);
|
|
if (NStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
RTMP_SET_PACKET_WCID(pNdisPacket, BSSID_WCID);
|
|
STASendPacket(pAd, pNdisPacket);
|
|
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
|
|
}
|
|
|
|
MlmeFreeMemory(pAd, pOutBuffer);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("RTMPSendSTAKeyHandShake- Send STAKey Message-2 (NStatus=%x, FrameLen=%ld)\n", NStatus, FrameLen));
|
|
|
|
return NStatus;
|
|
}
|
|
|
|
VOID DlsTimeoutAction(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
MLME_DLS_REQ_STRUCT MlmeDlsReq;
|
|
USHORT reason;
|
|
PRT_802_11_DLS pDLS = (PRT_802_11_DLS)FunctionContext;
|
|
PRTMP_ADAPTER pAd = pDLS->pAd;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("DlsTimeout - Tear down DLS links (%02x:%02x:%02x:%02x:%02x:%02x)\n",
|
|
pDLS->MacAddr[0], pDLS->MacAddr[1], pDLS->MacAddr[2], pDLS->MacAddr[3], pDLS->MacAddr[4], pDLS->MacAddr[5]));
|
|
|
|
if ((pDLS) && (pDLS->Valid))
|
|
{
|
|
reason = REASON_QOS_REQUEST_TIMEOUT;
|
|
pDLS->Valid = FALSE;
|
|
pDLS->Status = DLS_NONE;
|
|
DlsParmFill(pAd, &MlmeDlsReq, pDLS, reason);
|
|
MlmeEnqueue(pAd, DLS_STATE_MACHINE, MT2_MLME_DLS_TEAR_DOWN, sizeof(MLME_DLS_REQ_STRUCT), &MlmeDlsReq);
|
|
RT28XX_MLME_HANDLER(pAd);
|
|
}
|
|
}
|
|
|
|
/*
|
|
================================================================
|
|
Description : because DLS and CLI share the same WCID table in ASIC.
|
|
Mesh entry also insert to pAd->MacTab.content[]. Such is marked as ValidAsDls = TRUE.
|
|
Also fills the pairwise key.
|
|
Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert Dls
|
|
from index MAX_AID_BA.
|
|
================================================================
|
|
*/
|
|
MAC_TABLE_ENTRY *MacTableInsertDlsEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pAddr,
|
|
IN UINT DlsEntryIdx)
|
|
{
|
|
PMAC_TABLE_ENTRY pEntry = NULL;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableInsertDlsEntry\n"));
|
|
// if FULL, return
|
|
if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE)
|
|
return NULL;
|
|
|
|
do
|
|
{
|
|
if((pEntry = DlsEntryTableLookup(pAd, pAddr, TRUE)) != NULL)
|
|
break;
|
|
|
|
// allocate one MAC entry
|
|
pEntry = MacTableInsertEntry(pAd, pAddr, DlsEntryIdx + MIN_NET_DEVICE_FOR_DLS, TRUE);
|
|
if (pEntry)
|
|
{
|
|
pAd->StaCfg.DLSEntry[DlsEntryIdx].MacTabMatchWCID = pEntry->Aid;
|
|
pEntry->MatchDlsEntryIdx = DlsEntryIdx;
|
|
pEntry->AuthMode = pAd->StaCfg.AuthMode;
|
|
pEntry->WepStatus = pAd->StaCfg.WepStatus;
|
|
pEntry->PortSecured = WPA_802_1X_PORT_SECURED;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("MacTableInsertDlsEntry - allocate entry #%d, Total= %d\n",pEntry->Aid, pAd->MacTab.Size));
|
|
|
|
// If legacy WEP is used, set pair-wise cipherAlg into WCID attribute table for this entry
|
|
if ((pEntry->ValidAsDls) && (pEntry->WepStatus == Ndis802_11WEPEnabled))
|
|
{
|
|
UCHAR KeyIdx = 0;
|
|
UCHAR CipherAlg = 0;
|
|
|
|
KeyIdx = pAd->StaCfg.DefaultKeyId;
|
|
|
|
CipherAlg = pAd->SharedKey[BSS0][KeyIdx].CipherAlg;
|
|
|
|
RTMPAddWcidAttributeEntry(pAd,
|
|
BSS0,
|
|
pAd->StaCfg.DefaultKeyId,
|
|
pAd->SharedKey[BSS0][pAd->StaCfg.DefaultKeyId].CipherAlg,
|
|
pEntry);
|
|
}
|
|
|
|
break;
|
|
}
|
|
} while(FALSE);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableInsertDlsEntry\n"));
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Delete all Mesh Entry in pAd->MacTab
|
|
==========================================================================
|
|
*/
|
|
BOOLEAN MacTableDeleteDlsEntry(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN USHORT wcid,
|
|
IN PUCHAR pAddr)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("====> MacTableDeleteDlsEntry\n"));
|
|
|
|
if (!VALID_WCID(wcid))
|
|
return FALSE;
|
|
|
|
MacTableDeleteEntry(pAd, wcid, pAddr);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("<==== MacTableDeleteDlsEntry\n"));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
MAC_TABLE_ENTRY *DlsEntryTableLookup(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR pAddr,
|
|
IN BOOLEAN bResetIdelCount)
|
|
{
|
|
ULONG HashIdx;
|
|
MAC_TABLE_ENTRY *pEntry = NULL;
|
|
|
|
RTMP_SEM_LOCK(&pAd->MacTabLock);
|
|
HashIdx = MAC_ADDR_HASH_INDEX(pAddr);
|
|
pEntry = pAd->MacTab.Hash[HashIdx];
|
|
|
|
while (pEntry)
|
|
{
|
|
if ((pEntry->ValidAsDls == TRUE)
|
|
&& MAC_ADDR_EQUAL(pEntry->Addr, pAddr))
|
|
{
|
|
if(bResetIdelCount)
|
|
pEntry->NoDataIdleCount = 0;
|
|
break;
|
|
}
|
|
else
|
|
pEntry = pEntry->pNext;
|
|
}
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MacTabLock);
|
|
return pEntry;
|
|
}
|
|
|
|
MAC_TABLE_ENTRY *DlsEntryTableLookupByWcid(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR wcid,
|
|
IN PUCHAR pAddr,
|
|
IN BOOLEAN bResetIdelCount)
|
|
{
|
|
ULONG DLsIndex;
|
|
PMAC_TABLE_ENTRY pCurEntry = NULL;
|
|
PMAC_TABLE_ENTRY pEntry = NULL;
|
|
|
|
if (!VALID_WCID(wcid))
|
|
return NULL;
|
|
|
|
RTMP_SEM_LOCK(&pAd->MacTabLock);
|
|
|
|
do
|
|
{
|
|
pCurEntry = &pAd->MacTab.Content[wcid];
|
|
|
|
DLsIndex = 0xff;
|
|
if ((pCurEntry) && (pCurEntry->ValidAsDls== TRUE))
|
|
{
|
|
DLsIndex = pCurEntry->MatchDlsEntryIdx;
|
|
}
|
|
|
|
if (DLsIndex == 0xff)
|
|
break;
|
|
|
|
if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr))
|
|
{
|
|
if(bResetIdelCount)
|
|
pCurEntry->NoDataIdleCount = 0;
|
|
pEntry = pCurEntry;
|
|
break;
|
|
}
|
|
} while(FALSE);
|
|
|
|
RTMP_SEM_UNLOCK(&pAd->MacTabLock);
|
|
|
|
return pEntry;
|
|
}
|
|
|
|
INT Set_DlsEntryInfo_Display_Proc(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR arg)
|
|
{
|
|
INT i;
|
|
|
|
printk("\n%-19s%-8s\n", "MAC", "TIMEOUT\n");
|
|
for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
|
|
{
|
|
if ((pAd->StaCfg.DLSEntry[i].Valid) && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
|
|
{
|
|
PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pAd->StaCfg.DLSEntry[i].MacTabMatchWCID];
|
|
|
|
printk("%02x:%02x:%02x:%02x:%02x:%02x ",
|
|
pAd->StaCfg.DLSEntry[i].MacAddr[0], pAd->StaCfg.DLSEntry[i].MacAddr[1], pAd->StaCfg.DLSEntry[i].MacAddr[2],
|
|
pAd->StaCfg.DLSEntry[i].MacAddr[3], pAd->StaCfg.DLSEntry[i].MacAddr[4], pAd->StaCfg.DLSEntry[i].MacAddr[5]);
|
|
printk("%-8d\n", pAd->StaCfg.DLSEntry[i].TimeOut);
|
|
|
|
printk("\n");
|
|
printk("\n%-19s%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n",
|
|
"MAC", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC");
|
|
printk("%02X:%02X:%02X:%02X:%02X:%02X ",
|
|
pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2],
|
|
pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]);
|
|
printk("%-4d", (int)pEntry->Aid);
|
|
printk("%-4d", (int)pEntry->apidx);
|
|
printk("%-4d", (int)pEntry->PsMode);
|
|
printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE));
|
|
printk("%-8d", (int)pEntry->MmpsMode);
|
|
printk("%-7d", pEntry->RssiSample.AvgRssi0);
|
|
printk("%-7d", pEntry->RssiSample.AvgRssi1);
|
|
printk("%-7d", pEntry->RssiSample.AvgRssi2);
|
|
printk("%-10s", GetPhyMode(pEntry->HTPhyMode.field.MODE));
|
|
printk("%-6s", GetBW(pEntry->HTPhyMode.field.BW));
|
|
printk("%-6d", pEntry->HTPhyMode.field.MCS);
|
|
printk("%-6d", pEntry->HTPhyMode.field.ShortGI);
|
|
printk("%-6d", pEntry->HTPhyMode.field.STBC);
|
|
printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount,
|
|
(pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0);
|
|
printk("\n");
|
|
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT Set_DlsAddEntry_Proc(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR arg)
|
|
{
|
|
UCHAR mac[MAC_ADDR_LEN];
|
|
USHORT Timeout;
|
|
char *token, sepValue[] = ":", DASH = '-';
|
|
INT i;
|
|
RT_802_11_DLS Dls;
|
|
|
|
if(strlen(arg) < 19) //Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and timeout value in decimal format.
|
|
return FALSE;
|
|
|
|
token = strchr(arg, DASH);
|
|
if ((token != NULL) && (strlen(token)>1))
|
|
{
|
|
Timeout = simple_strtol((token+1), 0, 10);
|
|
|
|
*token = '\0';
|
|
for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++)
|
|
{
|
|
if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1))))
|
|
return FALSE;
|
|
AtoH(token, (PUCHAR)(&mac[i]), 1);
|
|
}
|
|
if(i != 6)
|
|
return FALSE;
|
|
|
|
printk("\n%02x:%02x:%02x:%02x:%02x:%02x-%d", mac[0], mac[1],
|
|
mac[2], mac[3], mac[4], mac[5], (int)Timeout);
|
|
|
|
NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
|
|
Dls.TimeOut = Timeout;
|
|
COPY_MAC_ADDR(Dls.MacAddr, mac);
|
|
Dls.Valid = 1;
|
|
|
|
MlmeEnqueue(pAd,
|
|
MLME_CNTL_STATE_MACHINE,
|
|
RT_OID_802_11_SET_DLS_PARAM,
|
|
sizeof(RT_802_11_DLS),
|
|
&Dls);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
INT Set_DlsTearDownEntry_Proc(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PUCHAR arg)
|
|
{
|
|
UCHAR macAddr[MAC_ADDR_LEN];
|
|
CHAR *value;
|
|
INT i;
|
|
RT_802_11_DLS Dls;
|
|
|
|
if(strlen(arg) != 17) //Mac address acceptable format 01:02:03:04:05:06 length 17
|
|
return FALSE;
|
|
|
|
for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":"))
|
|
{
|
|
if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
|
|
return FALSE; //Invalid
|
|
|
|
AtoH(value, &macAddr[i++], 2);
|
|
}
|
|
|
|
printk("\n%02x:%02x:%02x:%02x:%02x:%02x", macAddr[0], macAddr[1],
|
|
macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
|
|
|
|
NdisZeroMemory(&Dls, sizeof(RT_802_11_DLS));
|
|
COPY_MAC_ADDR(Dls.MacAddr, macAddr);
|
|
Dls.Valid = 0;
|
|
|
|
MlmeEnqueue(pAd,
|
|
MLME_CNTL_STATE_MACHINE,
|
|
RT_OID_802_11_SET_DLS_PARAM,
|
|
sizeof(RT_802_11_DLS),
|
|
&Dls);
|
|
|
|
return TRUE;
|
|
}
|
|
|