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

3807 lines
109 KiB
C
Raw Permalink Blame History

/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, 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:
tdls.h
Abstract:
Revision History:
Who When What
--------- ---------- ----------------------------------------------
Arvin Tai 17-04-2009 created for 802.11z
*/
#ifdef DOT11Z_TDLS_SUPPORT
#include "rt_config.h"
UCHAR TdlsZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
UCHAR CipherSuiteTDLSWpa2PskAes[] = {
0x30, // RSN IE
0x14, // Length
0x01, 0x00, // Version
0x00, 0x0F, 0xAC, 0x07, // no group cipher
0x01, 0x00, // number of pairwise
0x00, 0x0f, 0xAC, 0x04, // unicast, AES
0x01, 0x00, // number of authentication method
0x00, 0x0f, 0xAC, TDLS_AKM_SUITE_PSK, // TDLS authentication
0x00, 0x02, // RSN capability, peer key enabled
};
UCHAR CipherSuiteTDLSLen = sizeof(CipherSuiteTDLSWpa2PskAes)/ sizeof(UCHAR);
/*
==========================================================================
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 TDLS_StateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *Sm,
OUT STATE_MACHINE_FUNC Trans[])
{
UCHAR i;
StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, (ULONG)MAX_TDLS_STATE,
(ULONG)MAX_TDLS_MSG, (STATE_MACHINE_FUNC)Drop, TDLS_IDLE, TDLS_MACHINE_BASE);
/* the first column */
StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_SETUP_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeSetupReqAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_REQ, (STATE_MACHINE_FUNC)TDLS_PeerSetupReqAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_RSP, (STATE_MACHINE_FUNC)TDLS_PeerSetupRspAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_SETUP_CONF,(STATE_MACHINE_FUNC)TDLS_PeerSetupConfAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_TEAR_DOWN, (STATE_MACHINE_FUNC)TDLS_MlmeTearDownAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_TEAR_DOWN, (STATE_MACHINE_FUNC)TDLS_PeerTearDownAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_DISCOVER_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeDiscoveryReqAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_DISCOVER_REQ, (STATE_MACHINE_FUNC)TDLS_PeerDiscoveryReqAction);
#ifdef WFD_SUPPORT
StateMachineSetAction(Sm, TDLS_IDLE, MT2_MLME_TDLS_TUNNELED_REQ, (STATE_MACHINE_FUNC)TDLS_MlmeTunneledReqAction);
StateMachineSetAction(Sm, TDLS_IDLE, MT2_PEER_TDLS_TUNNELED_REQ, (STATE_MACHINE_FUNC)TDLS_PeerTunneledReqRspAction);
#endif /* WFD_SUPPORT */
for (i = 0; i < MAX_NUMBER_OF_DLS_ENTRY; i++)
{
pAd->StaCfg.TdlsInfo.TDLSEntry[i].pAd = pAd;
RTMPInitTimer(pAd, &pAd->StaCfg.TdlsInfo.TDLSEntry[i].Timer, GET_TIMER_FUNCTION(TDLS_TimeoutAction),
&pAd->StaCfg.TdlsInfo.TDLSEntry[i], FALSE);
}
#ifdef UAPSD_SUPPORT
TDLS_UAPSDP_Init(pAd, Sm);
#endif /* UAPSD_SUPPORT */
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_BuildSetupRequest(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PRT_802_11_TDLS pTDLS)
{
ULONG Timeout = TDLS_TIMEOUT;
BOOLEAN TimerCancelled;
/* fill action code */
TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen,
CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST);
/* fill Dialog Token */
pAd->StaCfg.TdlsInfo.TdlsDialogToken++;
if (pAd->StaCfg.TdlsInfo.TdlsDialogToken == 0)
pAd->StaCfg.TdlsInfo.TdlsDialogToken++;
pTDLS->Token = pAd->StaCfg.TdlsInfo.TdlsDialogToken;
TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token);
// fill capability
TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill support rate
TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill country
TDLS_InsertCountryIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill ext rate
TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill support channels
TDLS_InsertSupportChannelIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill RSN if security is not NONE
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
UCHAR CipherTmp[64] = {0};
UCHAR CipherTmpLen = 0;
ULONG tmp;
// RSNIE (7.3.2.25)
CipherTmpLen = CipherSuiteTDLSLen;
NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen);
// Insert RSN_IE to outgoing frame
MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp,
CipherTmpLen, &CipherTmp,
END_OF_ARGS);
*pFrameLen = *pFrameLen + tmp;
}
// fill Extended Capabilities (7.3.2.27)
TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill Qos Capability
//TDLS_InsertQosCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// TPK Handshake if RSNA Enabled
// Pack TPK Message 1 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
FT_FTIE FtIe;
UINT32 KeyLifetime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime; // sec
UCHAR Length;
/* FTIE (7.3.2.48) */
NdisZeroMemory(&FtIe, sizeof(FtIe));
Length = sizeof(FtIe);
/* generate SNonce */
GenRandom(pAd, pAd->CurrentAddress, FtIe.SNonce);
hex_dump("TDLS - Generate SNonce ", FtIe.SNonce, 32);
NdisMoveMemory(pTDLS->SNonce, FtIe.SNonce, 32);
TDLS_InsertFTIE(pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
Length,
FtIe.MICCtr,
FtIe.MIC,
FtIe.ANonce,
FtIe.SNonce);
/* Timeout Interval (7.3.2.49) */
TDLS_InsertTimeoutIntervalIE(pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
2, /* key lifetime interval */
KeyLifetime);
pTDLS->KeyLifetime = KeyLifetime;
}
// fill Supported Regulatory Classes
TDLS_SupportedRegulatoryClasses(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#ifdef DOT11_N_SUPPORT
// fill HT Capability
TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill 20/40 BSS Coexistence (7.3.2.61)
#ifdef DOT11N_DRAFT3
TDLS_InsertBSSCoexistenceIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#endif // DOT11N_DRAFT3 //
#endif // DOT11_N_SUPPORT //
/* fill link identifier */
TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr);
// fill WMM
TDLS_InsertWMMIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, TRUE);
#ifdef WFD_SUPPORT
{
ULONG WfdIeLen = 0, WfdIeBitmap;
WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) |
(0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR);
WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen);
*pFrameLen += WfdIeLen;
}
#endif /* WFD_SUPPORT */
// ==>> Set sendout timer
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
RTMPSetTimer(&pTDLS->Timer, Timeout);
// ==>> State Change
pTDLS->Status = TDLS_MODE_WAIT_RESPONSE;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_BuildSetupResponse(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PRT_802_11_TDLS pTDLS,
IN UCHAR RsnLen,
IN PUCHAR pRsnIe,
IN UCHAR FTLen,
IN PUCHAR pFTIe,
IN UCHAR TILen,
IN PUCHAR pTIIe,
IN UINT16 StatusCode)
{
/* fill action code */
TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen,
CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_RESPONSE);
/* fill status code */
TDLS_InsertStatusCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, StatusCode);
/* fill Dialog Token */
TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token);
if (StatusCode == MLME_SUCCESS)
{
/* fill fill capability */
TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill support rate
TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill country
TDLS_InsertCountryIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
/* fill ext rate */
TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill support channels
TDLS_InsertSupportChannelIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill Qos Capability
//TDLS_InsertQosCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill RSN
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
ULONG tmp;
/* RSNIE (7.3.2.25) */
/* Insert RSN_IE of the Peer TDLS to outgoing frame */
MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp,
RsnLen, pRsnIe,
END_OF_ARGS);
*pFrameLen = *pFrameLen + tmp;
}
// fill Extended Capabilities (7.3.2.27)
TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill WMM
TDLS_InsertWMMIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen,TRUE);
// TPK Handshake if RSNA Enabled
// Pack TPK Message 2 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
FT_FTIE *ft;
UINT key_len = 16;
// FTIE (7.3.2.48)
// Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce)
// point to the element of IE
ft = (FT_FTIE *)(pFTIe + 2);
// generate ANonce
GenRandom(pAd, pAd->CurrentAddress, ft->ANonce);
hex_dump("TDLS - Generate ANonce ", ft->ANonce, 32);
// set MIC field to zero before MIC calculation
NdisZeroMemory(ft->MIC, 16);
// copy SNonce from peer TDLS
NdisMoveMemory(ft->SNonce, pTDLS->SNonce, 32);
// copy ANonce to TDLS entry
NdisMoveMemory(pTDLS->ANonce, ft->ANonce, 32);
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* Derive TPK-KCK for MIC key, TPK-TK for direct link data */
TDLS_FTDeriveTPK(
pTDLS->MacAddr, /* MAC Address of Initiator */
pAd->CurrentAddress, /* I am Responder */
pTDLS->ANonce,
pTDLS->SNonce,
pAd->CommonCfg.Bssid,
key_len,
pTDLS->TPK,
pTDLS->TPKName);
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/*////////////////////////////////////////////////////////////////////*/
/* The MIC field of FTIE shall be calculated on the concatenation, in the following order, of */
/* 1. MAC_I (6 bytes) */
/* 2. MAC_R (6 bytes) */
/* 3. Transaction Sequence = 2 (1 byte) */
/* 4. Link Identifier (20 bytes) */
/* 5. RSN IE without the IE header (20 bytes) */
/* 6. Timeout Interval IE (7 bytes) */
/* 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) */
{
UCHAR content[512];
ULONG c_len = 0;
ULONG tmp_len = 0;
UCHAR Seq = 2;
UCHAR mic[16];
UCHAR LinkIdentifier[20];
UINT tmp_aes_len = 0;
NdisZeroMemory(LinkIdentifier, 20);
LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER;
LinkIdentifier[1] = 18;
NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6);
NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6);
NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6);
NdisZeroMemory(mic, sizeof(mic));
/* make a header frame for calculating MIC. */
MakeOutgoingFrame(content, &tmp_len,
MAC_ADDR_LEN, pTDLS->MacAddr,
MAC_ADDR_LEN, pAd->CurrentAddress,
1, &Seq,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Link Identifier */
MakeOutgoingFrame(content + c_len, &tmp_len,
20, LinkIdentifier,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate RSNIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
RsnLen, pRsnIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Timeout Interval IE */
MakeOutgoingFrame(content + c_len, &tmp_len,
7, pTIIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate FTIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
(sizeof(FT_FTIE) + 2), pFTIe,
END_OF_ARGS);
c_len += tmp_len;
/* Calculate MIC */
/*AES_128_CMAC(pTDLS->TPK, content, c_len, mic); */
/* Compute AES-128-CMAC over the concatenation */
tmp_aes_len = AES_KEY128_LENGTH;
AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len);
/* Fill Mic to ft struct */
NdisMoveMemory(ft->MIC, mic, 16);
}
/*////////////////////////////////////////////////////////////////////*/
/* Insert FT_IE to outgoing frame */
TDLS_InsertFTIE(
pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
sizeof(FT_FTIE),
ft->MICCtr,
ft->MIC,
ft->ANonce,
ft->SNonce);
/* Timeout Interval (7.3.2.49) */
/* Insert TI_IE to outgoing frame */
TDLS_InsertTimeoutIntervalIE(
pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
2, /* key lifetime interval */
pTDLS->KeyLifetime);
}
// fill Supported Regulatory Classes
TDLS_SupportedRegulatoryClasses(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#ifdef DOT11_N_SUPPORT
// fill HT Capability
TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
// fill 20/40 BSS Coexistence (7.3.2.61)
#ifdef DOT11N_DRAFT3
TDLS_InsertBSSCoexistenceIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#endif // DOT11N_DRAFT3 //
#endif // DOT11_N_SUPPORT //
/* fill link identifier */
TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress);
#ifdef WFD_SUPPORT
{
ULONG WfdIeLen = 0, WfdIeBitmap;
WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) |
(0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR);
WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen);
*pFrameLen += WfdIeLen;
}
#endif /* WFD_SUPPORT */
}
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_BuildSetupConfirm(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PRT_802_11_TDLS pTDLS,
IN UCHAR RsnLen,
IN PUCHAR pRsnIe,
IN UCHAR FTLen,
IN PUCHAR pFTIe,
IN UCHAR TILen,
IN PUCHAR pTIIe,
IN UINT16 StatusCode)
{
/* fill action code */
TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen,
CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_CONFIRM);
/* fill status code */
TDLS_InsertStatusCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, StatusCode);
/* fill Dialog Token */
TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token);
// fill Qos Capability
//TDLS_InsertEDCAParameterSetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS);
// TPK Handshake if RSNA Enabled
// Pack TPK Message 3 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
FT_FTIE *ft;
ULONG tmp;
/* RSNIE (7.3.2.25) */
/* Insert RSN_IE of the Peer TDLS to outgoing frame */
MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp,
RsnLen, pRsnIe,
END_OF_ARGS);
*pFrameLen = *pFrameLen + tmp;
/* FTIE (7.3.2.48) */
/* Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) */
/* point to the element of IE */
ft = (FT_FTIE *)(pFTIe + 2);
/* set MIC field to zero before MIC calculation */
NdisZeroMemory(ft->MIC, 16);
/*
The MIC field of FTIE shall be calculated on the concatenation, in the following order, of
1. MAC_I (6 bytes)
2. MAC_R (6 bytes)
3. Transaction Sequence = 2 (1 byte)
4. Link Identifier (20 bytes)
5. RSN IE without the IE header (20 bytes)
6. Timeout Interval IE (7 bytes)
7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes)
*/
{
UCHAR content[512];
ULONG c_len = 0;
ULONG tmp_len = 0;
UCHAR Seq = 3;
UCHAR mic[16];
UCHAR LinkIdentifier[20];
UINT tmp_aes_len = 0;
NdisZeroMemory(LinkIdentifier, 20);
LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER;
LinkIdentifier[1] = 18;
NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6);
NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6);
NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6);
NdisZeroMemory(mic, sizeof(mic));
/* make a header frame for calculating MIC. */
MakeOutgoingFrame(content, &tmp_len,
MAC_ADDR_LEN, pAd->CurrentAddress,
MAC_ADDR_LEN, pTDLS->MacAddr,
1, &Seq,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Link Identifier */
MakeOutgoingFrame(content + c_len, &tmp_len,
20, LinkIdentifier,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate RSNIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
RsnLen, pRsnIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Timeout Interval IE */
MakeOutgoingFrame(content + c_len, &tmp_len,
7, pTIIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate FTIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
(sizeof(FT_FTIE) + 2), pFTIe,
END_OF_ARGS);
c_len += tmp_len;
/* Calculate MIC */
/* AES_128_CMAC(pTDLS->TPK, content, c_len, mic); */
/* Compute AES-128-CMAC over the concatenation */
tmp_aes_len = AES_KEY128_LENGTH;
AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len);
/* Fill Mic to ft struct */
NdisMoveMemory(ft->MIC, mic, 16);
}
/*////////////////////////////////////////////////////////////////////*/
/* Insert FT_IE to outgoing frame */
TDLS_InsertFTIE(
pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
sizeof(FT_FTIE),
ft->MICCtr,
ft->MIC,
ft->ANonce,
ft->SNonce);
/* Timeout Interval (7.3.2.49) */
/* Insert TI_IE to outgoing frame */
TDLS_InsertTimeoutIntervalIE(
pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
2, /* key lifetime interval */
pTDLS->KeyLifetime);
}
#ifdef DOT11_N_SUPPORT
// fill HT Capability
TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#endif // DOT11_N_SUPPORT //
/* fill link identifier */
TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr);
// fill WMM Parameter IE
TDLS_InsertWMMParameterIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen);
#ifdef WFD_SUPPORT
{
ULONG WfdIeLen = 0, WfdIeBitmap;
WfdIeBitmap = (0x1 << SUBID_WFD_DEVICE_INFO) | (0x1 << SUBID_WFD_ASSOCIATED_BSSID) |
(0x1 << SUBID_WFD_COUPLED_SINK_INFO) | (0x1 << SUBID_WFD_LOCAL_IP_ADDR);
WfdMakeWfdIE(pAd, WfdIeBitmap, (pFrameBuf + *pFrameLen), &WfdIeLen);
*pFrameLen += WfdIeLen;
}
#endif /* WFD_SUPPORT */
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_BuildTeardown(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PRT_802_11_TDLS pTDLS,
IN UINT16 ReasonCode)
{
/* fill action code */
TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen,
CATEGORY_TDLS, TDLS_ACTION_CODE_TEARDOWN);
/* fill reason code */
TDLS_InsertReasonCode(pAd, (pFrameBuf + *pFrameLen), pFrameLen, ReasonCode);
// FTIE includes if RSNA Enabled
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
UCHAR FTIe[128];
FT_FTIE *ft = NULL;
UCHAR content[256];
ULONG c_len = 0;
ULONG tmp_len = 0;
UCHAR seq = 4;
UCHAR mic[16];
UCHAR LinkIdentifier[20];
UINT tmp_aes_len = 0;
NdisZeroMemory(LinkIdentifier, 20);
LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER;
LinkIdentifier[1] = 18;
NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6);
if (pTDLS->bInitiator)
{
NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6);
NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6);
}
else
{
NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6);
NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6);
}
/* FTIE (7.3.2.48) */
/* The contents of FTIE in the TDLS Teardown frame shall be the same as that included */
/* in the TPK Handshake Message3 with the exception of the MIC field. */
/* Construct FTIE (IE + Length + MIC Control + MIC + ANonce + SNonce) */
/* point to the element of IE */
NdisZeroMemory(FTIe, sizeof(FTIe));
FTIe[0] = IE_FT_FTIE;
FTIe[1] = sizeof(FT_FTIE);
ft = (PFT_FTIE)&FTIe[2];
NdisMoveMemory(ft->ANonce, pTDLS->ANonce, 32);
NdisMoveMemory(ft->SNonce, pTDLS->SNonce, 32);
/*
The MIC field of FTIE shall be calculated on the concatenation, in the following order, of
1. Link Identifier (20 bytes)
2. Reason Code (2 bytes)
3. Dialog token (1 byte)
4. Transaction Sequence = 4 (1 byte)
5. FTIE with the MIC field of FTIE set to zero (84 bytes)
*/
/* concatenate Link Identifier, Reason Code, Dialog token, Transaction Sequence */
MakeOutgoingFrame(content, &tmp_len,
sizeof(LinkIdentifier), LinkIdentifier,
2, &ReasonCode,
1, &pTDLS->Token,
1, &seq,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate FTIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
FTIe[1] + 2, FTIe,
END_OF_ARGS);
c_len += tmp_len;
/* Calculate MIC */
NdisZeroMemory(mic, sizeof(mic));
/*AES_128_CMAC(pTDLS->TPK, content, c_len, mic); */
/* Compute AES-128-CMAC over the concatenation */
tmp_aes_len = AES_KEY128_LENGTH;
AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len);
/* Fill Mic to ft struct */
NdisMoveMemory(ft->MIC, mic, 16);
/* Insert FT_IE to outgoing frame */
TDLS_InsertFTIE(
pAd,
(pFrameBuf + *pFrameLen),
pFrameLen,
FTIe[1],
ft->MICCtr,
ft->MIC,
ft->ANonce,
ft->SNonce);
}
/* fill link identifier */
if (pTDLS->bInitiator)
TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr, pAd->CurrentAddress);
else
TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr);
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
USHORT TDLS_TPKMsg1Process(
IN PRTMP_ADAPTER pAd,
#ifdef WFD_SUPPORT
IN ULONG WfdSubelementLen,
#endif /* WFD_SUPPORT */
IN PRT_802_11_TDLS pTDLS,
IN PUCHAR pRsnIe,
IN UCHAR RsnLen,
IN PUCHAR pFTIe,
IN UCHAR FTLen,
IN PUCHAR pTIIe,
IN UCHAR TILen)
{
USHORT StatusCode = MLME_SUCCESS;
UCHAR CipherTmp[64] = {0};
UCHAR CipherTmpLen = 0;
FT_FTIE *ft = NULL;
/* Validate RsnIE */
/* */
if (RsnLen == 0) /* RSN not exist */
return MLME_INVALID_INFORMATION_ELEMENT;
if (pRsnIe[2] < 1) /* Smaller version */
return MLME_NOT_SUPPORT_RSN_VERSION;
CipherTmpLen = CipherSuiteTDLSLen;
NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen);
if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM
return MLME_INVALID_AKMP;
//if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability
if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0))
return MLME_INVALID_RSN_CAPABILITIES;
//if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, RsnLen) == 0)) // Invalid Pairwise Cipher
// todo make check
//if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0))
// return REASON_UCIPHER_NOT_VALID;
// Validate FTIE
//
ft = (PFT_FTIE)(pFTIe + 2); // point to the element of IE
if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 ||
(RTMPEqualMemory(ft->MIC, TdlsZeroSsid, 16) == 0) || (RTMPEqualMemory(ft->ANonce, TdlsZeroSsid, 32) == 0))
return REASON_FT_INVALID_FTIE;
// Validate TIIE
//
//if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < keyLifeTime))
if ((TILen != 7) || (pTIIe[2] != 2))
return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME;
return StatusCode;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
USHORT TDLS_TPKMsg2Process(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS,
IN PUCHAR pRsnIe,
IN UCHAR RsnLen,
IN PUCHAR pFTIe,
IN UCHAR FTLen,
IN PUCHAR pTIIe,
IN UCHAR TILen,
OUT PUCHAR pTPK,
OUT PUCHAR pTPKName)
{
USHORT StatusCode = MLME_SUCCESS;
UCHAR CipherTmp[64] = {0};
UCHAR CipherTmpLen = 0;
FT_FTIE *ft = NULL;
UCHAR oldMic[16];
UCHAR LinkIdentifier[20];
UINT key_len = 16;
UINT32 keyLifeTime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime;
/* Validate RsnIE */
/* */
if (RsnLen == 0) /* RSN not exist */
return MLME_INVALID_INFORMATION_ELEMENT;
if (pRsnIe[2] < 1) /* Smaller version */
return MLME_NOT_SUPPORT_RSN_VERSION;
CipherTmpLen = CipherSuiteTDLSLen;
NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen);
if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM
return MLME_INVALID_AKMP;
//if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability
if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0))
return MLME_INVALID_RSN_CAPABILITIES;
// todo make check
//if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, RsnLen) == 0)) // Invalid Pairwise Cipher
//if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0))
//return REASON_UCIPHER_NOT_VALID;
/* Validate FTIE */
ft = (PFT_FTIE)(pFTIe + 2); /* point to the element of IE */
if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 ||
(RTMPEqualMemory(ft->SNonce, pTDLS->SNonce, 32) == 0))
return REASON_FT_INVALID_FTIE;
/* Validate TIIE */
if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < TDLS_KEY_TIMEOUT))
return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME;
/* Validate the MIC field of FTIE */
/* point to the element of IE */
ft = (PFT_FTIE)(pFTIe + 2);
/* backup MIC fromm the peer TDLS */
NdisMoveMemory(oldMic, ft->MIC, 16);
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* Derive TPK-KCK for MIC key, TPK-TK for direct link data */
TDLS_FTDeriveTPK(
pAd->CurrentAddress, /* I am Initiator */
pTDLS->MacAddr, /* MAC Address of Responder */
ft->ANonce,
ft->SNonce,
pAd->CommonCfg.Bssid,
key_len,
pTPK,
pTPKName);
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* set MIC field to zero before MIC calculation */
NdisZeroMemory(ft->MIC, 16);
/* Construct LinkIdentifier (IE + Length + BSSID + Initiator MAC + Responder MAC) */
NdisZeroMemory(LinkIdentifier, 20);
LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER;
LinkIdentifier[1] = 18;
NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6);
NdisMoveMemory(&LinkIdentifier[8], pAd->CurrentAddress, 6);
NdisMoveMemory(&LinkIdentifier[14], pTDLS->MacAddr, 6);
/*////////////////////////////////////////////////////////////////////*/
/* The MIC field of FTIE shall be calculated on the concatenation, in the following order, of */
/* 1. MAC_I (6 bytes) */
/* 2. MAC_R (6 bytes) */
/* 3. Transaction Sequence = 2 (1 byte) */
/* 4. Link Identifier (20 bytes) */
/* 5. RSN IE without the IE header (20 bytes) */
/* 6. Timeout Interval IE (7 bytes) */
/* 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) */
{
UCHAR content[512];
ULONG c_len = 0;
ULONG tmp_len = 0;
UCHAR Seq = 2;
UCHAR mic[16];
UINT tmp_aes_len = 0;
NdisZeroMemory(mic, sizeof(mic));
/* make a header frame for calculating MIC. */
MakeOutgoingFrame(content, &tmp_len,
MAC_ADDR_LEN, pAd->CurrentAddress,
MAC_ADDR_LEN, pTDLS->MacAddr,
1, &Seq,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Link Identifier */
MakeOutgoingFrame(content + c_len, &tmp_len,
20, LinkIdentifier,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate RSNIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
RsnLen, pRsnIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Timeout Interval IE */
MakeOutgoingFrame(content + c_len, &tmp_len,
7, pTIIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate FTIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
(sizeof(FT_FTIE) + 2), pFTIe,
END_OF_ARGS);
c_len += tmp_len;
/* Calculate MIC */
/* AES_128_CMAC(pTPK, content, c_len, mic); */
/* Compute AES-128-CMAC over the concatenation */
tmp_aes_len = AES_KEY128_LENGTH;
AES_CMAC(content, c_len, pTPK, 16, mic, &tmp_aes_len);
NdisMoveMemory(ft->MIC, mic, 16);
}
/*////////////////////////////////////////////////////////////////////*/
if (RTMPEqualMemory(oldMic, ft->MIC, 16) == 0)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS_TPKMsg2Process() MIC Error!!! \n"));
return MLME_REQUEST_DECLINED;
}
return StatusCode;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
USHORT TDLS_TPKMsg3Process(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS,
IN PUCHAR pRsnIe,
IN UCHAR RsnLen,
IN PUCHAR pFTIe,
IN UCHAR FTLen,
IN PUCHAR pTIIe,
IN UCHAR TILen)
{
USHORT StatusCode = MLME_SUCCESS;
UCHAR CipherTmp[64] = {0};
UCHAR CipherTmpLen = 0;
FT_FTIE *ft = NULL;
UCHAR oldMic[16];
UCHAR LinkIdentifier[20];
/* Validate RsnIE */
/* */
if (RsnLen == 0) /* RSN not exist */
return MLME_INVALID_INFORMATION_ELEMENT;
if (pRsnIe[2] < 1) /* Smaller version */
return MLME_NOT_SUPPORT_RSN_VERSION;
CipherTmpLen = CipherSuiteTDLSLen;
NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen);
if ( RTMPEqualMemory(&pRsnIe[16], &CipherTmp[16], 4) == 0) // Invalid TDLS AKM
return MLME_INVALID_AKMP;
//if ( RTMPEqualMemory(&pRsnIe[20], &CipherTmp[20], 2) == 0) // Invalid RSN capability
if (((pRsnIe[20] & 0x2) != 0) || ((pRsnIe[21] & 0x2) == 0))
return MLME_INVALID_RSN_CAPABILITIES;
// todo make check
//if ((RsnLen != 22) || (RTMPEqualMemory(pRsnIe, CipherTmp, (RsnLen - 2)) == 0)) // Invalid Pairwise Cipher
//return REASON_UCIPHER_NOT_VALID;
/* Validate FTIE */
ft = (PFT_FTIE)(pFTIe + 2); /* point to the element of IE */
if ((FTLen != (sizeof(FT_FTIE) + 2)) || RTMPEqualMemory(&ft->MICCtr, TdlsZeroSsid, 2) == 0 ||
(RTMPEqualMemory(ft->SNonce, pTDLS->SNonce, 32) == 0) || (RTMPEqualMemory(ft->ANonce, pTDLS->ANonce, 32) == 0))
return REASON_FT_INVALID_FTIE;
/* Validate TIIE */
/* */
if ((TILen != 7) || (pTIIe[2] != 2) || ( le2cpu32(*((PULONG) (pTIIe + 3))) < pTDLS->KeyLifetime))
return TDLS_STATUS_CODE_UNACCEPTABLE_LIFETIME;
/* Validate the MIC field of FTIE */
/* point to the element of IE */
ft = (PFT_FTIE)(pFTIe + 2);
/* backup MIC fromm the peer TDLS */
NdisMoveMemory(oldMic, ft->MIC, 16);
/* set MIC field to zero before MIC calculation */
NdisZeroMemory(ft->MIC, 16);
/* Construct LinkIdentifier (IE + Length + BSSID + Initiator MAC + Responder MAC) */
NdisZeroMemory(LinkIdentifier, 20);
LinkIdentifier[0] = IE_TDLS_LINK_IDENTIFIER;
LinkIdentifier[1] = 18;
NdisMoveMemory(&LinkIdentifier[2], pAd->CommonCfg.Bssid, 6);
NdisMoveMemory(&LinkIdentifier[8], pTDLS->MacAddr, 6);
NdisMoveMemory(&LinkIdentifier[14], pAd->CurrentAddress, 6);
/*////////////////////////////////////////////////////////////////////*/
/* The MIC field of FTIE shall be calculated on the concatenation, in the following order, of */
/* 1. MAC_I (6 bytes) */
/* 2. MAC_R (6 bytes) */
/* 3. Transaction Sequence = 3 (1 byte) */
/* 4. Link Identifier (20 bytes) */
/* 5. RSN IE without the IE header (20 bytes) */
/* 6. Timeout Interval IE (7 bytes) */
/* 7. FTIE without the IE header, with the MIC field of FTIE set to zero (82 bytes) */
{
UCHAR content[512];
ULONG c_len = 0;
ULONG tmp_len = 0;
UCHAR Seq = 3;
UCHAR mic[16];
UINT tmp_aes_len = 0;
NdisZeroMemory(mic, sizeof(mic));
/* make a header frame for calculating MIC. */
MakeOutgoingFrame(content, &tmp_len,
MAC_ADDR_LEN, pTDLS->MacAddr,
MAC_ADDR_LEN, pAd->CurrentAddress,
1, &Seq,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Link Identifier */
MakeOutgoingFrame(content + c_len, &tmp_len,
20, LinkIdentifier,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate RSNIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
RsnLen, pRsnIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate Timeout Interval IE */
MakeOutgoingFrame(content + c_len, &tmp_len,
7, pTIIe,
END_OF_ARGS);
c_len += tmp_len;
/* concatenate FTIE */
MakeOutgoingFrame(content + c_len, &tmp_len,
(sizeof(FT_FTIE) + 2), pFTIe,
END_OF_ARGS);
c_len += tmp_len;
/* Calculate MIC */
//AES_128_CMAC(pTDLS->TPK, content, c_len, mic);
/* Compute AES-128-CMAC over the concatenation */
tmp_aes_len = AES_KEY128_LENGTH;
AES_CMAC(content, c_len, pTDLS->TPK, 16, mic, &tmp_aes_len);
NdisMoveMemory(ft->MIC, mic, 16);
}
/*////////////////////////////////////////////////////////////////////*/
if (RTMPEqualMemory(oldMic, ft->MIC, 16) == 0)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS_TPKMsg3Process() MIC Error!!! \n"));
return MLME_REQUEST_DECLINED;
}
return StatusCode;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
NDIS_STATUS
TDLS_DiscoveryReqAction(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMacAddr)
{
UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d};
UCHAR Header802_3[14];
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
ULONG TempLen;
UCHAR RemoteFrameType = PROTO_NAME_TDLS;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("TDLS ===> TDLS_DiscoveryReqAction\n"));
MAKE_802_3_HEADER(Header802_3, pMacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE);
// Allocate buffer for transmitting message
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return NStatus;
MakeOutgoingFrame(pOutBuffer, &TempLen,
1, &RemoteFrameType,
END_OF_ARGS);
FrameLen = FrameLen + TempLen;
/* fill action code */
TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
CATEGORY_TDLS, TDLS_ACTION_CODE_DISCOVERY_REQUEST);
/* fill Dialog Token */
pAd->StaCfg.TdlsInfo.TdlsDialogToken++;
if (pAd->StaCfg.TdlsInfo.TdlsDialogToken == 0)
pAd->StaCfg.TdlsInfo.TdlsDialogToken++;
TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, pAd->StaCfg.TdlsInfo.TdlsDialogToken);
/* fill link identifier */
TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pAd->CurrentAddress, pMacAddr);
RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3,
LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE);
hex_dump("TDLS discovery request send pack", pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("TDLS <=== TDLS_DiscoveryReqAction\n"));
return NStatus;
}
NDIS_STATUS
TDLS_DiscoveryRspAction(
IN PRTMP_ADAPTER pAd,
IN UCHAR PeerToken,
IN PUCHAR pPeerMac)
{
PUCHAR pOutBuffer = NULL;
FRAME_ACTION_HDR Frame;
ULONG FrameLen = 0;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_DiscoveryRspAction\n"));
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); //Get an unused nonpaged memory
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_DiscoveryRspAction() allocate memory failed \n"));
return NStatus;
}
ActHeaderInit(pAd, &Frame.Hdr, pPeerMac, pAd->CurrentAddress, pAd->CommonCfg.Bssid);
Frame.Category = CATEGORY_PUBLIC;
Frame.Action = ACTION_TDLS_DISCOVERY_RSP;
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(FRAME_ACTION_HDR), &Frame,
END_OF_ARGS);
/* fill action code */
//TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_TDLS, 14);
/* fill Dialog Token */
TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, PeerToken);
// fill capability
TDLS_InsertCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
// fill support rate
TDLS_InsertSupportRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
// fill ext rate
TDLS_InsertExtRateIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
// fill support channels
TDLS_InsertSupportChannelIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
UCHAR CipherTmp[64] = {0};
UCHAR CipherTmpLen = 0;
ULONG tmp;
// RSNIE (7.3.2.25)
CipherTmpLen = CipherSuiteTDLSLen;
NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen);
// Insert RSN_IE to outgoing frame
MakeOutgoingFrame((pOutBuffer + FrameLen), &tmp,
CipherTmpLen, &CipherTmp,
END_OF_ARGS);
FrameLen = FrameLen + tmp;
}
// fill Extended Capabilities (7.3.2.27)
TDLS_InsertExtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
// TPK Handshake if RSNA Enabled
// Pack TPK Message 1 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
FT_FTIE FtIe;
ULONG KeyLifetime = pAd->StaCfg.TdlsInfo.TdlsKeyLifeTime; // sec
UCHAR Length;
UCHAR SNonce[32]; // Generated in Message 2, random variable
// FTIE (7.3.2.48)
NdisZeroMemory(&FtIe, sizeof(FtIe));
Length = sizeof(FtIe);
// generate SNonce
GenRandom(pAd, pAd->CurrentAddress, FtIe.SNonce);
hex_dump("TDLS - Generate SNonce ", FtIe.SNonce, 32);
NdisMoveMemory(SNonce, FtIe.SNonce, 32);
TDLS_InsertFTIE(pAd,
(pOutBuffer + FrameLen),
&FrameLen,
Length,
FtIe.MICCtr,
FtIe.MIC,
FtIe.ANonce,
FtIe.SNonce);
// Timeout Interval (7.3.2.49)
TDLS_InsertTimeoutIntervalIE(pAd,
(pOutBuffer + FrameLen),
&FrameLen,
2, /* key lifetime interval */
KeyLifetime);
}
// fill Supported Regulatory Classes
TDLS_SupportedRegulatoryClasses(pAd, (pOutBuffer + FrameLen), &FrameLen);
#ifdef DOT11_N_SUPPORT
// fill HT Capability
TDLS_InsertHtCapIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
// fill 20/40 BSS Coexistence (7.3.2.61)
#ifdef DOT11N_DRAFT3
TDLS_InsertBSSCoexistenceIE(pAd, (pOutBuffer + FrameLen), &FrameLen);
#endif // DOT11N_DRAFT3 //
#endif // DOT11_N_SUPPORT //
/* fill link identifier */
TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pPeerMac, pAd->CurrentAddress);
hex_dump("TDLS discovery response send pack", pOutBuffer, FrameLen);
MiniportMMRequest(pAd, QID_AC_VI, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_DiscoveryRspAction\n"));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
NDIS_STATUS
TDLS_SetupRequestAction(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS)
{
UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d};
UCHAR Header802_3[14];
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
ULONG TempLen;
UCHAR RemoteFrameType = PROTO_NAME_TDLS;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("====> TDLS_SetupRequestAction\n"));
MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE);
/* Allocate buffer for transmitting message */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_SetupRequestAction() allocate memory failed \n"));
return NStatus;
}
/* enter ACTIVE mode */
TDLS_CHANGE_TO_ACTIVE(pAd);
MakeOutgoingFrame(pOutBuffer, &TempLen,
1, &RemoteFrameType,
END_OF_ARGS);
FrameLen = FrameLen + TempLen;
TDLS_BuildSetupRequest(pAd, pOutBuffer, &FrameLen, pTDLS);
RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3,
LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE);
hex_dump("TDLS setup request send pack", pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("<==== TDLS_SetupRequestAction\n"));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
NDIS_STATUS
TDLS_SetupResponseAction(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS,
IN UCHAR RsnLen,
IN PUCHAR pRsnIe,
IN UCHAR FTLen,
IN PUCHAR pFTIe,
IN UCHAR TILen,
IN PUCHAR pTIIe,
IN UINT16 StatusCode)
{
UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d};
UCHAR Header802_3[14];
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
ULONG TempLen;
UCHAR RemoteFrameType = PROTO_NAME_TDLS;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("====> TDLS_SetupResponseAction\n"));
MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE);
/* Allocate buffer for transmitting message */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_SetupResponseAction() allocate memory failed \n"));
return NStatus;
}
MakeOutgoingFrame(pOutBuffer, &TempLen,
1, &RemoteFrameType,
END_OF_ARGS);
FrameLen = FrameLen + TempLen;
TDLS_BuildSetupResponse(pAd, pOutBuffer, &FrameLen, pTDLS, RsnLen, pRsnIe, FTLen, pFTIe, TILen, pTIIe, StatusCode);
RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3,
LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE);
hex_dump("TDLS send setup response pack", pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("<==== TDLS_SetupResponseAction\n"));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
NDIS_STATUS
TDLS_SetupConfirmAction(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS,
IN UCHAR RsnLen,
IN PUCHAR pRsnIe,
IN UCHAR FTLen,
IN PUCHAR pFTIe,
IN UCHAR TILen,
IN PUCHAR pTIIe,
IN UINT16 StatusCode)
{
UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d};
UCHAR Header802_3[14];
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
ULONG TempLen;
UCHAR RemoteFrameType = PROTO_NAME_TDLS;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("====> TDLS_SetupConfirmAction\n"));
MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE);
/* Allocate buffer for transmitting message */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_SetupConfirmAction() allocate memory failed \n"));
return NStatus;
}
MakeOutgoingFrame(pOutBuffer, &TempLen,
1, &RemoteFrameType,
END_OF_ARGS);
FrameLen = FrameLen + TempLen;
TDLS_BuildSetupConfirm(pAd, pOutBuffer, &FrameLen, pTDLS, RsnLen, pRsnIe, FTLen, pFTIe, TILen, pTIIe, StatusCode);
RTMPToWirelessSta(pAd, &pAd->MacTab.Content[BSSID_WCID], Header802_3,
LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE);
hex_dump("TDLS setup confirm pack", pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
TDLS_RECOVER_POWER_SAVE(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("<==== TDLS_SetupConfirmAction\n"));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_LinkTearDown(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN bDirect)
{
UCHAR idx;
BOOLEAN TimerCancelled;
PRT_802_11_TDLS pTDLS = NULL;
DBGPRINT(RT_DEBUG_TRACE, ("====> TDLS_LinkTearDown\n"));
/* tear down tdls table entry */
for (idx = 0; idx < MAX_NUM_OF_TDLS_ENTRY; idx++)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (pTDLS->Valid && (pTDLS->Status >= TDLS_MODE_CONNECTED))
{
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
pTDLS->Token = 0;
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
if (!VALID_WCID(pTDLS->MacTabMatchWCID))
return;
if (pAd->StaCfg.bRadio == TRUE)
{
if (bDirect)
TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON, TRUE);
else
TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_DUE_TO_PEER_STA_UNREACHABLE, FALSE);
}
MacTableDeleteEntry(pAd,pTDLS->MacTabMatchWCID, pTDLS->MacAddr);
}
else if (pTDLS->Valid)
{
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
pTDLS->Token = 0;
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
}
}
#ifdef TDLS_AUTOLINK_SUPPORT
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
TDLS_ClearEntryList(&pAd->StaCfg.TdlsInfo.TdlsBlackList);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
#endif /* TDLS_AUTOLINK_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("<==== TDLS_LinkTearDown\n"));
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_TearDownPeerLink(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pPeerAddr,
IN BOOLEAN bDirect)
{
UCHAR EntryIdx;
BOOLEAN TimerCancelled;
PRT_802_11_TDLS pTDLS = NULL;
DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_TearDownPeerLink\n"));
// tear down tdls table entry
for (EntryIdx = 0; EntryIdx < MAX_NUM_OF_TDLS_ENTRY; EntryIdx++)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[EntryIdx];
if ((pTDLS->Valid) && (pTDLS->Status >= TDLS_MODE_CONNECTED) && MAC_ADDR_EQUAL(pPeerAddr, pTDLS->MacAddr))
{
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
if (!VALID_WCID(pTDLS->MacTabMatchWCID))
return;
if (bDirect)
TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON, TRUE);
else
TDLS_TearDownAction(pAd, pTDLS, TDLS_REASON_CODE_TEARDOWN_DUE_TO_PEER_STA_UNREACHABLE, FALSE);
MacTableDeleteEntry(pAd,pTDLS->MacTabMatchWCID, pTDLS->MacAddr);
break;
}
}
if (EntryIdx == MAX_NUM_OF_TDLS_ENTRY)
{
DBGPRINT(RT_DEBUG_ERROR, ("Peer MAC - not found !!!\n"));
}
DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_TearDownPeerLink\n"));
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
NDIS_STATUS
TDLS_TearDownAction(
IN PRTMP_ADAPTER pAd,
IN PRT_802_11_TDLS pTDLS,
IN UINT16 ReasonCode,
IN BOOLEAN bDirect)
{
UCHAR TDLS_ETHERTYPE[] = {0x89, 0x0d};
UCHAR Header802_3[14];
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
ULONG TempLen;
UCHAR idx = 1;
UCHAR RemoteFrameType = PROTO_NAME_TDLS;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
DBGPRINT(RT_DEBUG_TRACE, ("====> TDLS_TearDownAction\n"));
MAKE_802_3_HEADER(Header802_3, pTDLS->MacAddr, pAd->CurrentAddress, TDLS_ETHERTYPE);
/* Allocate buffer for transmitting message */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("ACT - TDLS_TearDownAction() allocate memory failed \n"));
return NStatus;
}
MakeOutgoingFrame(pOutBuffer, &TempLen,
1, &RemoteFrameType,
END_OF_ARGS);
FrameLen = FrameLen + TempLen;
TDLS_BuildTeardown(pAd, pOutBuffer, &FrameLen, pTDLS, ReasonCode);
if (bDirect == TRUE)
idx = pTDLS->MacTabMatchWCID;
else
idx = BSSID_WCID;
RTMPToWirelessSta(pAd, &pAd->MacTab.Content[idx], Header802_3,
LENGTH_802_3, pOutBuffer, (UINT)FrameLen, FALSE);
hex_dump("TDLS teardown send pack", pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE, ("<==== TDLS_TearDownAction\n"));
return NStatus;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeDiscoveryReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR PeerMacAddr[MAC_ADDR_LEN];
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
#ifdef TDLS_AUTOLINK_SUPPORT
PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL;
#endif // TDLS_AUTOLINK_SUPPORT //
DBGPRINT(RT_DEBUG_ERROR,("===> TDLS_MlmeDiscoveryReqAction() \n"));
NdisMoveMemory(PeerMacAddr, Elem->Msg, MAC_ADDR_LEN);
if (INFRA_ON(pAd))
{
DBGPRINT(RT_DEBUG_ERROR, ("Send Discovery Request to Peer ::%02x:%02x:%02x:%02x:%02x:%02x !!!\n",
PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2],
PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5]));
/* Build TDLS Discovery Request Frame */
NStatus = TDLS_DiscoveryReqAction(pAd, PeerMacAddr);
if (NStatus != NDIS_STATUS_SUCCESS)
{
#ifdef TDLS_AUTOLINK_SUPPORT
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, PeerMacAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
#endif // TDLS_AUTOLINK_SUPPORT //
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeDiscoveryReqAction() Build Discovery Setup Request Fail !!!\n"));
}
else
{
#ifdef TDLS_AUTOLINK_SUPPORT
pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, PeerMacAddr);
#endif // TDLS_AUTOLINK_SUPPORT //
}
}
else
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeDiscoveryReqAction() Build Discovery Setup Request Fail, Because STA is not connect to AP!!!\n"));
}
DBGPRINT(RT_DEBUG_ERROR,("<=== TDLS_MlmeDiscoveryReqAction() \n"));
return;
}
#ifdef WFD_SUPPORT
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeTunneledReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR PeerMacAddr[MAC_ADDR_LEN];
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
#ifdef TDLS_AUTOLINK_SUPPORT
PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsDiscovPeerList;
PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL;
#endif // TDLS_AUTOLINK_SUPPORT //
DBGPRINT(RT_DEBUG_ERROR,("===> TDLS_MlmeTunneledProbeReqAction() \n"));
NdisMoveMemory(PeerMacAddr, Elem->Msg, MAC_ADDR_LEN);
if (INFRA_ON(pAd))
{
DBGPRINT(RT_DEBUG_ERROR, ("Send Tunneled Probe Request to Peer ::%02x:%02x:%02x:%02x:%02x:%02x !!!\n",
PeerMacAddr[0], PeerMacAddr[1], PeerMacAddr[2],
PeerMacAddr[3], PeerMacAddr[4], PeerMacAddr[5]));
/* Build TDLS Tunneled Probe Request Frame */
NStatus = TDLS_TunneledProbeRequest(pAd, PeerMacAddr);
if (NStatus != NDIS_STATUS_SUCCESS)
{
#ifdef TDLS_AUTOLINK_SUPPORT
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsDiscovPeerListSemLock);
TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, PeerMacAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsDiscovPeerListSemLock);
#endif // TDLS_AUTOLINK_SUPPORT //
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTunneledProbeReqAction() Build Tunneled Probe Request Fail !!!\n"));
}
else
{
#ifdef TDLS_AUTOLINK_SUPPORT
pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscoveryEnList, PeerMacAddr);
#endif // TDLS_AUTOLINK_SUPPORT //
}
}
else
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTunneledProbeReqAction() Build Tunneled Probe Request Fail, Because STA is not connect to AP!!!\n"));
}
DBGPRINT(RT_DEBUG_ERROR,("<=== TDLS_MlmeTunneledProbeReqAction() \n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerTunneledReqRspAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
ULONG RemainLen = Elem->MsgLen;
PFRAME_802_11 pFrame;
pFrame = (PFRAME_802_11)Elem->Msg;
CHAR *Ptr =(CHAR *)Elem->Msg;
PRT_802_11_TDLS pTDLS = NULL;
BOOLEAN TimerCancelled;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerTunneledReqRspAction() \n"));
/* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes)
TDLS Action header(payload type + category + action)(3 bytes) and Payload (variable)
*/
if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + 3))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("TDLS_PeerTunneledReq/RspAction --> Invaild packet length - (action header) \n"));
return;
}
// Offset to Payload Type
Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 1);
RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 1);
DBGPRINT(RT_DEBUG_ERROR, ("TDLS_PeerTunneledReqRspAction --> Gategory = %02x. OUI = %02x-%02x-%02x.\n", *Ptr, *(Ptr+1), *(Ptr+2), *(Ptr+3)));
// Get the value of token from payload and advance the pointer
if (RemainLen < 1)
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (dialog token) \n"));
return;
}
/* Frame Body Type */
Ptr += 4;
RemainLen -= 4;
if (RemainLen < 7)
{
DBGPRINT(RT_DEBUG_ERROR, ("PeerTdlsDiscovReqSanity --> remain length is not enough = %d.\n", RemainLen));
return;
}
if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr3, pAd->CommonCfg.Bssid))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsTunneledReqSanity --> It's not my BSSID[%02x:%02x:%02x:%02x:%02x:%02x] Addr3[%02x:%02x:%02x:%02x:%02x:%02x]\n", PRINT_MAC(pAd->CommonCfg.Bssid), PRINT_MAC(pFrame->Hdr.Addr3)));
//return;
}
NdisMoveMemory(PeerAddr, pFrame->Hdr.Addr3, MAC_ADDR_LEN);
if ((*Ptr == WFD_TUNNELED_PROBE_REQ) ||
(*Ptr == WFD_TUNNELED_PROBE_RSP))
{
PWFD_DEVICE_INFO pWfd_info;
SHORT idx;
for (idx = MAX_NUM_OF_TDLS_ENTRY - 1; idx >= 0; idx--)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (pTDLS->Valid && MAC_ADDR_EQUAL(PeerAddr, pTDLS->MacAddr))
{
DBGPRINT(RT_DEBUG_TRACE,("%s::find the same entry and discard it\n", __FUNCTION__));
break;
}
}
if (idx < 0)
{
for (idx = (MAX_NUM_OF_TDLS_ENTRY - 1); idx >= 0; idx--)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (!pTDLS->Valid)
{
RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled);
pTDLS->Valid = TRUE;
NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN);
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqRspAction() create a new entry \n"));
break;
}
}
}
if (idx < 0)
{
// Table full !!!!!
DBGPRINT(RT_DEBUG_ERROR,("%s::TDLSEntry table full(only can support %d TDLS session) \n",
__FUNCTION__, MAX_NUM_OF_TDLS_ENTRY));
}
else if (pTDLS)
{
UCHAR Addr2[6], SsidLen = 0;
UCHAR Ssid[32];
ULONG Peerip;
UCHAR DsChannel = 0;
ULONG P2PSubelementLen = 0;
PUCHAR P2pSubelement = NULL;
ULONG WfdSubelementLen = 0;
PUCHAR WfdSubelement = NULL;
os_alloc_mem(pAd, &P2pSubelement, MAX_VIE_LEN);
if (P2pSubelement == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN));
return;
}
os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN);
if (WfdSubelement == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN));
os_free_mem(pAd, P2pSubelement);
return;
}
(TDLS_PeerTunneledProbeReqRspSanity(pAd,
Elem->Msg,
Elem->MsgLen,
Addr2,
Ssid,
&SsidLen,
&Peerip,
&DsChannel,
&P2PSubelementLen,
P2pSubelement,
&WfdSubelementLen,
WfdSubelement));
if (WfdSubelementLen > 0)
{
WfdParseSubElmt(pAd,
&pTDLS->WfdEntryInfo,
(PVOID)WfdSubelement,
WfdSubelementLen);
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s:: WFD Element IE Len is 0.\n", __FUNCTION__));
if (P2pSubelement)
os_free_mem(pAd, P2pSubelement);
if (WfdSubelement)
os_free_mem(pAd, WfdSubelement);
if (*Ptr == WFD_TUNNELED_PROBE_REQ)
{
DBGPRINT(RT_DEBUG_ERROR,("Receive Tunneled probe request frame\n"));
/* Build TDLS Discovery Response Frame */
NStatus = TDLS_TunneledProbeResponse(pAd, PeerAddr);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerTunneledReqRspAction() Build Tunneled Response Fail !!!\n"));
}
}
else
DBGPRINT(RT_DEBUG_ERROR,("Receive Tunneled probe response frame\n"));
}
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s::unknown Type = %02x.\n", __FUNCTION__, *Ptr+4));
return;
}
#endif /* WFD_SUPPORT */
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerDiscoveryReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
ULONG RemainLen = Elem->MsgLen;
CHAR *Ptr =(CHAR *)Elem->Msg;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerDiscoveryReqAction() \n"));
/* Message contains 802.11 header (24 bytes), LLC_SNAP (8 bytes)
TDLS Action header(payload type + category + action)(3 bytes) and Payload (variable)
*/
if (RemainLen < (LENGTH_802_11 + LENGTH_802_1_H + 3))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (action header) \n"));
return;
}
// Offset to Dialog Token
Ptr += (LENGTH_802_11 + LENGTH_802_1_H + 3);
RemainLen -= (LENGTH_802_11 + LENGTH_802_1_H + 3);
// Get the value of token from payload and advance the pointer
if (RemainLen < 1)
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (dialog token) \n"));
return;
}
Token = *Ptr;
// Offset to Link Identifier
Ptr += 1;
RemainLen -= 1;
// Get BSSID, SA and DA from payload and advance the pointer
if ((RemainLen < 20) || (Ptr[0] != IE_TDLS_LINK_IDENTIFIER) || (Ptr[1] != 18))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> Invaild packet length - (link identifier) \n"));
return;
}
if (!MAC_ADDR_EQUAL(Ptr+2, pAd->CommonCfg.Bssid))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my BSSID\n"));
return;
}
else if (!MAC_ADDR_EQUAL(Ptr+14, pAd->CurrentAddress))
{
DBGPRINT_RAW(RT_DEBUG_WARN, ("PeerTdlsDiscovReqSanity --> It's not my MAC address\n"));
return;
}
NdisMoveMemory(PeerAddr, Ptr+8, MAC_ADDR_LEN);
/* Build TDLS Discovery Response Frame */
NStatus = TDLS_DiscoveryRspAction(pAd, Token, PeerAddr);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerDiscoveryReqAction() Build Discovery Response Fail !!!\n"));
}
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID TDLS_DiscoveryRspPublicAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem,
IN VOID *Msg,
IN ULONG MsgLen)
{
USHORT StatusCode = MLME_SUCCESS;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
USHORT CapabilityInfo;
UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen, LinkIdentLen;
UCHAR RsnIe[64], FTIe[128], TIIe[7];
HT_CAPABILITY_IE HtCap;
EXT_CAP_INFO_ELEMENT ExtCap;
TDLS_LINK_IDENT_ELEMENT LinkIdent;
PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg;
DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_DiscoveryRspPublicAction() \n"));
hex_dump("TDLS discovery response receive pack", Msg, MsgLen);
if (!PeerTdlsDiscovRspSanity(
pAd,
Msg,
MsgLen,
&Token,
PeerAddr,
&CapabilityInfo,
&SupRateLen,
&SupRate[0],
&ExtRateLen,
&ExtRate[0],
&HtCapLen,
&HtCap,
&ExtCapLen,
&ExtCap,
&RsnLen,
RsnIe,
&FTLen,
FTIe,
&TILen,
TIIe,
&LinkIdentLen,
&LinkIdent))
{
StatusCode = MLME_REQUEST_DECLINED;
}
COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr2);
if (StatusCode == MLME_SUCCESS)
{
#ifdef TDLS_AUTOLINK_SUPPORT
if (pAd->StaCfg.TdlsInfo.TdlsAutoLink)
{
PLIST_HEADER pTdlsDiscovryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
PTDLS_DISCOVERY_ENTRY pTdlsPeer = NULL;
pTdlsPeer = TDLS_FindDiscoveryEntry(pTdlsDiscovryEnList, PeerAddr);
if (pTdlsPeer)
{
PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
CHAR Rssi = -99;
Rssi = RTMPMaxRssi(pAd,
ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0, Elem->AntSel, BW_20),
ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1, Elem->AntSel, BW_20),
ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2, Elem->AntSel, BW_20));
DBGPRINT(RT_DEBUG_ERROR, ("Discovery Response Rssi = %d !!!\n" , Rssi));
if (pTdlsPeer->bConnected)
{
if ((pTdlsPeer->bConnectedFirstTime) && (pTdlsPeer->RetryCount == 1))
{
pTdlsPeer->AvgRssi0 = Rssi;
pTdlsPeer->RetryCount--;
pTdlsPeer->bConnectedFirstTime = FALSE;
DBGPRINT(RT_DEBUG_ERROR,("Connected first time discovery !!!\n"));
}
else
{
if (pTdlsPeer->RetryCount == 1)
{
if ((Rssi < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold) &&
(pTdlsPeer->AvgRssi0 < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold))
{
/* Tear Down */
if (INFRA_ON(pAd))
{
MLME_TDLS_REQ_STRUCT MlmeTdlsReq;
USHORT Reason = REASON_UNSPECIFY;
INT idx;
DBGPRINT(RT_DEBUG_ERROR,("\n !!! Will tear down %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
pTdlsPeer->Responder[0],
pTdlsPeer->Responder[1],
pTdlsPeer->Responder[2],
pTdlsPeer->Responder[3],
pTdlsPeer->Responder[4],
pTdlsPeer->Responder[5]));
idx = TDLS_SearchLinkId(pAd, pTdlsPeer->Responder);
if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - can not find or full the LinkId!\n"));
}
else if (idx >= 0)
{
Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON;
pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE;
pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE;
TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE);
MlmeEnqueue(pAd,
TDLS_STATE_MACHINE,
MT2_MLME_TDLS_TEAR_DOWN,
sizeof(MLME_TDLS_REQ_STRUCT),
&MlmeTdlsReq,
0);
}
}
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_DelDiscoveryEntryByMAC(pTdlsDiscovryEnList, PeerAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
}
else
{
pTdlsPeer->AvgRssi0 = Rssi;
pTdlsPeer->RetryCount--;
}
}
else if (pTdlsPeer->RetryCount > 1)
{
if (Rssi < pAd->StaCfg.TdlsInfo.TdlsAutoTeardownRssiThreshold)
{
/* Tear Down */
if (INFRA_ON(pAd))
{
MLME_TDLS_REQ_STRUCT MlmeTdlsReq;
USHORT Reason = REASON_UNSPECIFY;
INT idx;
DBGPRINT(RT_DEBUG_ERROR,("\n !!! Will tear down %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
pTdlsPeer->Responder[0],
pTdlsPeer->Responder[1],
pTdlsPeer->Responder[2],
pTdlsPeer->Responder[3],
pTdlsPeer->Responder[4],
pTdlsPeer->Responder[5]));
idx = TDLS_SearchLinkId(pAd, pTdlsPeer->Responder);
if (idx == -1 || idx == MAX_NUM_OF_TDLS_ENTRY)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - can not find or full the LinkId!\n"));
}
else if (idx >= 0)
{
Reason = TDLS_REASON_CODE_TEARDOWN_FOR_UNSPECIFIED_REASON;
pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Valid = FALSE;
pAd->StaCfg.TdlsInfo.TDLSEntry[idx].Status = TDLS_MODE_NONE;
TDLS_MlmeParmFill(pAd, &MlmeTdlsReq, &pAd->StaCfg.TdlsInfo.TDLSEntry[idx], Reason, FALSE);
MlmeEnqueue(pAd,
TDLS_STATE_MACHINE,
MT2_MLME_TDLS_TEAR_DOWN,
sizeof(MLME_TDLS_REQ_STRUCT),
&MlmeTdlsReq,
0);
}
}
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_DelDiscoveryEntryByMAC(pTdlsDiscovryEnList, PeerAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
}
else
{
pTdlsPeer->AvgRssi0 = Rssi;
pTdlsPeer->RetryCount = 0;
}
}
}
}
else
{
if (pTdlsPeer->CurrentState == TDLS_DISCOVERY_IDLE)
{
pTdlsPeer->CurrentState = TDLS_DISCOVERY_FIRST_TIME;
pTdlsPeer->AvgRssi0 = Rssi;
}
else if (pTdlsPeer->CurrentState == TDLS_DISCOVERY_FIRST_TIME)
{
if ((pTdlsPeer->AvgRssi0 > pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold) &&
(Rssi > pAd->StaCfg.TdlsInfo.TdlsAutoSetupRssiThreshold))
{
if (INFRA_ON(pAd) && (pTdlsPeer->bConnected == FALSE))
{
INT LinkId = 0xff;
LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
{
RT_802_11_TDLS Tdls;
DBGPRINT(RT_DEBUG_ERROR,("\n!!! Auto Setup TDLS to %02x:%02x:%02x:%02x:%02x:%02x !!!\n",
pTdlsPeer->Responder[0],
pTdlsPeer->Responder[1],
pTdlsPeer->Responder[2],
pTdlsPeer->Responder[3],
pTdlsPeer->Responder[4],
pTdlsPeer->Responder[5]));
NdisZeroMemory(&Tdls, sizeof(RT_802_11_TDLS));
Tdls.TimeOut = 0;
COPY_MAC_ADDR(Tdls.MacAddr, pTdlsPeer->Responder);
Tdls.Valid = 1;
pTdlsPeer->CurrentState = TDLS_DISCOVERY_TO_SETUP;
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
RT_OID_802_11_SET_TDLS_PARAM,
sizeof(RT_802_11_TDLS),
&Tdls,
0);
}
else
{
PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL;
PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList;
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, PeerAddr, TRUE);
pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, PeerAddr);
if (pPeerEntry)
{
pPeerEntry->bConnectedFirstTime = TRUE;
pPeerEntry->bConnected = TRUE;
pPeerEntry->RetryCount = 0;
pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE;
}
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, PeerAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
}
}
}
else
{
pTdlsPeer->CurrentState = TDLS_DISCOVERY_TO_SETUP_FAIL;
}
}
}
}
else
{
DBGPRINT(RT_DEBUG_ERROR,("Can't find discovery entry on discovery table !!!\n"));
}
}
#endif // TDLS_AUTOLINK_SUPPORT //
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_DiscoveryRspPublicAction() \n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeSetupReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PRT_802_11_TDLS pTDLS = NULL;
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
MLME_TDLS_REQ_STRUCT *pInfo;
DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_MlmeSetupReqAction() \n"));
pInfo = (MLME_TDLS_REQ_STRUCT *)Elem->Msg;
pTDLS = pInfo->pTDLS;
if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE)
{
DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_MlmeSetupReqAction() AP Prohibited TDLS !!!\n"));
return;
}
/* Build TDLS Setup Request Frame */
NStatus = TDLS_SetupRequestAction(pAd, pTDLS);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeSetupReqAction() Build Setup Request Fail !!!\n"));
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_MlmeSetupReqAction() \n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerSetupReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
USHORT StatusCode = MLME_SUCCESS;
SHORT idx;
ULONG Timeout = TDLS_TIMEOUT;
BOOLEAN TimerCancelled;
PRT_802_11_TDLS pTDLS = NULL;
RT_802_11_TDLS TmpTDLS;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
USHORT CapabilityInfo;
UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen, LinkIdentLen;
UCHAR RsnIe[64], FTIe[128], TIIe[7];
UCHAR QosCapability;
HT_CAPABILITY_IE HtCap;
EXT_CAP_INFO_ELEMENT ExtCap;
BOOLEAN bDiscard = FALSE;
BOOLEAN bWmmCapable;
TDLS_LINK_IDENT_ELEMENT LinkIdent;
#ifdef WFD_SUPPORT
ULONG WfdSubelementLen = 0;
PUCHAR WfdSubelement = NULL;
#endif /* WFD_SUPPORT */
#ifdef WFD_SUPPORT
os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN);
if (WfdSubelement == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN));
return;
}
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupReqAction\n"));
// Not TDLS Capable, ignore it
if (!IS_TDLS_SUPPORT(pAd))
goto CleanUp;
// Not BSS mode, ignore it
if (!INFRA_ON(pAd))
goto CleanUp;
if (pAd->StaActive.ExtCapInfo.TDLSProhibited == TRUE)
{
DBGPRINT(RT_DEBUG_OFF,("TDLS - TDLS_PeerSetupReqAction() AP Prohibited TDLS !!!\n"));
goto CleanUp;
}
// Init all kinds of fields within the packet
NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo));
NdisZeroMemory(&HtCap, sizeof(HtCap));
NdisZeroMemory(&ExtCap, sizeof(ExtCap));
NdisZeroMemory(RsnIe, sizeof(RsnIe));
NdisZeroMemory(FTIe, sizeof(FTIe));
NdisZeroMemory(TIIe, sizeof(TIIe));
NdisZeroMemory(&LinkIdent, sizeof(LinkIdent));
hex_dump("TDLS setup request receive pack", Elem->Msg, Elem->MsgLen);
if (!PeerTdlsSetupReqSanity(
pAd,
Elem->Msg,
Elem->MsgLen,
#ifdef WFD_SUPPORT
&WfdSubelementLen,
WfdSubelement,
#endif /* WFD_SUPPORT */
&Token,
PeerAddr,
&CapabilityInfo,
&SupRateLen,
&SupRate[0],
&ExtRateLen,
&ExtRate[0],
&bWmmCapable,
&QosCapability,
&HtCapLen,
&HtCap,
&ExtCapLen,
&ExtCap,
&RsnLen,
RsnIe,
&FTLen,
FTIe,
&TILen,
TIIe,
&LinkIdentLen,
&LinkIdent))
{
StatusCode = MLME_REQUEST_DECLINED;
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() received a request from %02x:%02x:%02x:%02x:%02x:%02x\n",
PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5]));
if ((pAd->StaCfg.WepStatus != Ndis802_11WEPDisabled) && (RsnLen == 0))
{
StatusCode = MLME_INVALID_SECURITY_POLICY;
}
#ifdef WFD_SUPPORT
/* WFD spec. 4.5.3 Establish WFD Connection using TDLS
* If an associated infrastructure AP uses WEP or WPA for the link between the AP and the WFD device,
* the WFD device shall not accept the TDLS Setup Request frame for WFD connection but reject it by
* sending TDLS Setup Response frame with indicating status code as 5 (<28><>Security disabled<65><64>).
*/
if ((pAd->StaCfg.WfdCfg.bWfdEnable) && WfdSubelementLen)
{
if (RsnLen == 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::No RSN IE and peer is WFD device, return weak security(5)!\n", __FUNCTION__));
StatusCode = MLME_SECURITY_WEAK;
}
if ((pAd->StaCfg.AuthMode != Ndis802_11AuthModeWPA2PSK) ||
(pAd->StaCfg.WepStatus != Ndis802_11Encryption3Enabled)) // Pairwise cipher suite is not AES
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::AP Security is not WPA2PSK/AES and peer is WFD device, return weak security(5)!\n", __FUNCTION__));
StatusCode = MLME_SECURITY_WEAK;
}
}
#endif /* WFD_SUPPORT */
#ifdef TDLS_AUTOLINK_SUPPORT
if (pAd->StaCfg.TdlsInfo.TdlsAutoLink)
{
PTDLS_BLACK_ENTRY pTdlsBlackEntry = NULL;
PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList;
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
pTdlsBlackEntry = TDLS_FindBlackEntry(pTdlsBlackEnList, PeerAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
if (pTdlsBlackEntry)
{
if (pTdlsBlackEntry->CurrentState == TDLS_BLACK_TDLS_BY_TEARDOWN)
StatusCode = MLME_REQUEST_DECLINED;
}
}
#endif // TDLS_AUTOLINK_SUPPORT //
/* Find table to update parameters. */
if (StatusCode == MLME_SUCCESS)
{
for (idx = MAX_NUM_OF_TDLS_ENTRY - 1; idx >= 0; idx--)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (pTDLS->Valid && MAC_ADDR_EQUAL(PeerAddr, pTDLS->MacAddr))
{
if (pTDLS->Status == TDLS_MODE_WAIT_RESPONSE)
{
if (RTMPCompareMemory(PeerAddr, pAd->CurrentAddress, MAC_ADDR_LEN) == 2)
{
/*
11.20.2 TDLS Link Establishment
4. The TDLS setup request frame is received after sending a TDLS Setup Request frame and before
receiving the corresponding TDLS Setup Response frame, and the source address of the received
TDLS Setup Request frame is lower than its own MAC address. In this case, the TDLS responder
STA shall terminate the TDLS setup it initiated. The TDLS responder STA shall send a response
frame.
*/
RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled);
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN);
pTDLS->Status = TDLS_MODE_NONE;
idx = -1;
//pTDLS = pTmpTDLS;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() find the same entry \n"));
}
else
{
/*
11.20.2 TDLS Link Establishment
3. The TDLS setup request is received after sending a TDLS Setup Request frame and before
receiving the corresponding TDLS Setup Response frame, and the source address of the received
TDLS Setup Request frame is higher than its own MAC address, in which case the TDLS
responder STA shall silently discard the message and the TDLS responder STA shall send no
TDLS Setup Response frame.
*/
bDiscard = TRUE;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() find the same entry and discard it\n"));
}
}
else if (pTDLS->Status == TDLS_MODE_CONNECTED)
{
if(pTDLS->bInitiator == FALSE)
{
/*
If a TDLS Setup Request frame is received from a TDLS responder STA with
which a currently active TDLS session exists, then the receiving STA shall
tear down the existing TDLS direct link as if a TDLS Teardown frame was received,
and respond with a TDLS Setup Response frame.
*/
if (!VALID_WCID(pTDLS->MacTabMatchWCID))
goto CleanUp;
MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, pTDLS->MacAddr);
RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled);
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN);
pTDLS->Status = TDLS_MODE_NONE;
}
}
break;
}
}
if (bDiscard == TRUE)
goto CleanUp;
if (idx >= 0)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (pTDLS->Token == Token)
{
DBGPRINT(RT_DEBUG_WARN, ("TDLS - PeerTdlsSetupReqAction() receive the same token TDLS request !!!\n"));
goto CleanUp;;
}
}
/* Can not find in table, create a new one */
if (idx < 0)
{
for (idx = (MAX_NUM_OF_TDLS_ENTRY - 1); idx >= 0; idx--)
{
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[idx];
if (!pTDLS->Valid)
{
RTMPCancelTimer(&(pTDLS->Timer), &TimerCancelled);
pTDLS->Valid = TRUE;
NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN);
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() create a new entry \n"));
break;
}
}
}
if (idx < 0)
{
// Table full !!!!!
StatusCode = MLME_REQUEST_DECLINED;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupReqAction() TDLSEntry table full(only can support %d TDLS session) \n",
MAX_NUM_OF_TDLS_ENTRY));
}
else if (pTDLS)
{
//
// Process TPK Handshake Message 1 here!
//
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
USHORT Result;
// RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49)
Result = TDLS_TPKMsg1Process(pAd,
#ifdef WFD_SUPPORT
WfdSubelementLen,
#endif /* WFD_SUPPORT */
pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen);
if (Result != MLME_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_TPKMsg1Process() Failed, reason=%d \n", Result));
if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore
{
goto CleanUp;
}
else
{
StatusCode = Result;
goto send_out;
}
}
// Copy SNonce, Key lifetime
pTDLS->KeyLifetime = le2cpu32(*((PULONG) (TIIe + 3)));
NdisMoveMemory(pTDLS->SNonce, &FTIe[52], 32);
}
//
// Update temporarliy settings. Try to match Initiator's capabilities
//
pTDLS->Token = Token;
// I am Responder.And peer are Initiator
pTDLS->bInitiator = TRUE;
pTDLS->CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO;
// Copy Initiator's supported rate and filter out not supported rate
pTDLS->SupRateLen = SupRateLen;
NdisMoveMemory(pTDLS->SupRate, SupRate, SupRateLen);
RTMPCheckRates(pAd, pTDLS->SupRate, &pTDLS->SupRateLen);
pTDLS->ExtRateLen = ExtRateLen;
NdisMoveMemory(pTDLS->ExtRate, ExtRate, ExtRateLen);
RTMPCheckRates(pAd, pTDLS->ExtRate, &pTDLS->ExtRateLen);
// Filter out un-supported ht rates
if ((HtCapLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
// HtCapability carries Responder's capability, so not copy from Initiator here.
RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE);
pTDLS->HtCapabilityLen = SIZE_HT_CAP_IE;
NdisMoveMemory(&pTDLS->HtCapability, &HtCap, SIZE_HT_CAP_IE);
}
else
{
pTDLS->HtCapabilityLen = 0;
RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE);
}
// Copy extended capability
NdisMoveMemory(&pTDLS->TdlsExtCap, &ExtCap, sizeof(EXT_CAP_INFO_ELEMENT));
// Copy QOS related information
pTDLS->QosCapability = QosCapability;
pTDLS->bWmmCapable = bWmmCapable;
#ifdef WFD_SUPPORT
if ((pAd->StaCfg.WfdCfg.bWfdEnable) &&
WfdSubelementLen > 0)
{
WfdParseSubElmt(pAd,
&pTDLS->WfdEntryInfo,
(PVOID)WfdSubelement,
WfdSubelementLen);
/* WFD spec. 4.5.3 Establish WFD Connection using TDLS
* If the type of WFD device indicated in WFD Device Type bits (B1B0) in WFD Device Information field in
* WFD IE within the received TDLS Setup Request frame is different from the expected value,
* the recipient should respond using TDLS Setup Response frame with setting Status Code to 38
* (The request has not been successful as one or more parameters have invalid values).
*/
if (pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SOURCE_PRIMARY_SINK)
StatusCode = MLME_REQUEST_WITH_INVALID_PARAM;
else
{
switch (pAd->StaCfg.WfdCfg.DeviceType)
{
case WFD_SOURCE:
if (pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SOURCE)
StatusCode = MLME_REQUEST_WITH_INVALID_PARAM;
break;
case WFD_PRIMARY_SINK:
case WFD_SECONDARY_SINK:
if ((pTDLS->WfdEntryInfo.wfd_devive_type == WFD_PRIMARY_SINK) ||
(pTDLS->WfdEntryInfo.wfd_devive_type == WFD_SECONDARY_SINK))
StatusCode = MLME_REQUEST_WITH_INVALID_PARAM;
break;
}
}
if (StatusCode == MLME_REQUEST_WITH_INVALID_PARAM)
DBGPRINT(RT_DEBUG_ERROR, ("%s:: Peer device type is not the expected value,\nMy WFD Device Type = %d, Peer WFD Device Type = %d\n",
__FUNCTION__, pAd->StaCfg.WfdCfg.DeviceType, pTDLS->WfdEntryInfo.wfd_devive_type));
else
DBGPRINT(RT_DEBUG_TRACE, ("%s:: My WFD Device Type = %d, Peer WFD Device Type = %d\n", __FUNCTION__,
pAd->StaCfg.WfdCfg.DeviceType, pTDLS->WfdEntryInfo.wfd_devive_type));
}
#endif /* WFD_SUPPORT */
}
}
send_out:
if (StatusCode != MLME_SUCCESS)
{
NdisZeroMemory(&TmpTDLS, sizeof(RT_802_11_TDLS));
pTDLS = &TmpTDLS;
NdisMoveMemory(pTDLS->MacAddr, PeerAddr, MAC_ADDR_LEN);
pTDLS->Token = Token;
}
TDLS_SetupResponseAction(pAd, pTDLS, RsnLen, RsnIe, FTLen, FTIe, TILen, TIIe, StatusCode);
if (StatusCode == MLME_SUCCESS)
{
/* Set sendout timer */
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
RTMPSetTimer(&pTDLS->Timer, Timeout);
pTDLS->Valid = TRUE;
/* State Change */
pTDLS->Status = TDLS_MODE_WAIT_CONFIRM;
}
CleanUp:
#ifdef WFD_SUPPORT
os_free_mem(pAd, WfdSubelement);
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupReqAction\n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerSetupRspAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
USHORT StatusCode = MLME_SUCCESS, LocalStatusCode = MLME_SUCCESS;
BOOLEAN TimerCancelled;
PRT_802_11_TDLS pTDLS = NULL;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
USHORT CapabilityInfo;
UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRate[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR SupRateLen, ExtRateLen, HtCapLen, ExtCapLen, RsnLen, FTLen, TILen, LinkIdentLen;
UCHAR RsnIe[64], FTIe[128], TIIe[7];
UCHAR QosCapability;
BOOLEAN bWmmCapable;
HT_CAPABILITY_IE HtCap;
EXT_CAP_INFO_ELEMENT ExtCap;
INT LinkId = 0xff;
UCHAR TPK[LEN_PMK], TPKName[LEN_PMK_NAME];
PMAC_TABLE_ENTRY pMacEntry = NULL;
TDLS_LINK_IDENT_ELEMENT LinkIdent;
PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg;
#ifdef WFD_SUPPORT
ULONG WfdSubelementLen = 0;
PUCHAR WfdSubelement = NULL;
#endif /* WFD_SUPPORT */
#ifdef WFD_SUPPORT
os_alloc_mem(pAd, &WfdSubelement, MAX_VIE_LEN);
if (WfdSubelement == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Allocate memory size(=%d) failed\n", __FUNCTION__, MAX_VIE_LEN));
return;
}
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupRspAction\n"));
// Not TDLS Capable, ignore it
if (!IS_TDLS_SUPPORT(pAd))
goto CleanUp;
// Not BSS mode, ignore it
if (!INFRA_ON(pAd))
goto CleanUp;
hex_dump("TDLS setup response receive pack", Elem->Msg, Elem->MsgLen);
// Init all kinds of fields within the packet
NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo));
NdisZeroMemory(&HtCap, sizeof(HtCap));
NdisZeroMemory(&ExtCap, sizeof(ExtCap));
NdisZeroMemory(RsnIe, sizeof(RsnIe));
NdisZeroMemory(FTIe, sizeof(FTIe));
NdisZeroMemory(TIIe, sizeof(TIIe));
NdisZeroMemory(&LinkIdent, sizeof(LinkIdent));
if (!PeerTdlsSetupRspSanity(
pAd,
Elem->Msg,
Elem->MsgLen,
#ifdef WFD_SUPPORT
&WfdSubelementLen,
WfdSubelement,
#endif /* WFD_SUPPORT */
&Token,
PeerAddr,
&CapabilityInfo,
&SupRateLen,
SupRate,
&ExtRateLen,
ExtRate,
&bWmmCapable,
&QosCapability,
&HtCapLen,
&HtCap,
&ExtCapLen,
&ExtCap,
&StatusCode,
&RsnLen,
RsnIe,
&FTLen,
FTIe,
&TILen,
TIIe,
&LinkIdentLen,
&LinkIdent))
{
LocalStatusCode = MLME_REQUEST_DECLINED;
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() received a response from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d\n",
PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5], StatusCode));
if (StatusCode != MLME_SUCCESS)
{
COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3);
}
// Drop not within my TDLS Table that created before !
LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerSetupRspAction() can not find the LinkId!\n"));
goto CleanUp;
}
// Point to the current Link ID
pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];
// Cancel the timer since the received packet to me.
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
// Received a error code from the Peer TDLS.
// Let's terminate the setup procedure right now.
if (StatusCode != MLME_SUCCESS)
{
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
#ifdef WFD_SUPPORT
if ((pAd->StaCfg.WfdCfg.bWfdEnable) &&
(StatusCode == MLME_SECURITY_WEAK))
pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_WEAK_SECURITY;
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() received a failed StatusCode, terminate the setup procedure \n"));
goto CleanUp;
}
else
StatusCode = LocalStatusCode;
//
// Validate the content on Setup Response Frame
//
while (StatusCode == MLME_SUCCESS)
{
// Invalid TDLS State
if (pTDLS->Status != TDLS_MODE_WAIT_RESPONSE)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() Not in TDLS_MODE_WAIT_RESPONSE STATE\n"));
StatusCode = MLME_REQUEST_DECLINED;
break;
}
// Is the same Dialog Token?
if (pTDLS->Token != Token)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() Not match with Dialig Token my token = %d, peer token = %d\n",
pTDLS->Token, Token));
StatusCode = MLME_REQUEST_DECLINED;
break;
}
// Process TPK Handshake Message 2 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
USHORT Result;
// RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49)
Result = TDLS_TPKMsg2Process(pAd, pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen, TPK, TPKName);
if (Result != MLME_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_TPKMsg2Process() Failed, reason=%d \n", Result));
if (Result == MLME_REQUEST_DECLINED) // if mic error , ignore
{
goto CleanUp;
}
else
{
StatusCode = Result;
goto send_out;
}
}
// Copy ANonce, Key lifetime, TPK, TPK Name
pTDLS->KeyLifetime = le2cpu32(*((PULONG) (TIIe + 3)));
NdisMoveMemory(pTDLS->ANonce, &FTIe[20], 32);
NdisMoveMemory(pTDLS->TPK, TPK, LEN_PMK);
NdisMoveMemory(pTDLS->TPKName, TPKName, LEN_PMK_NAME);
}
// Update parameters
if (StatusCode == MLME_SUCCESS)
{
// I am Initiator. And peer are Responder
pTDLS->bInitiator = FALSE;
// Capabilities
pTDLS->CapabilityInfo = CapabilityInfo;
pTDLS->SupRateLen = SupRateLen;
pTDLS->ExtRateLen = ExtRateLen;
// Copy ht capabilities from the Peer TDLS
if ((HtCapLen > 0) && (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED))
{
NdisMoveMemory(&pTDLS->HtCapability, &HtCap, HtCapLen);
pTDLS->HtCapabilityLen = HtCapLen;
}
else
{
pTDLS->HtCapabilityLen = 0;
RTMPZeroMemory(&pTDLS->HtCapability, SIZE_HT_CAP_IE);
}
// Copy extended capability
NdisMoveMemory(&pTDLS->TdlsExtCap, &ExtCap, sizeof(EXT_CAP_INFO_ELEMENT));
// Copy QOS related information
pTDLS->QosCapability = QosCapability;
pTDLS->bWmmCapable = bWmmCapable;
// Copy TPK related information
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
// SNonce, Key lifetime
}
#ifdef WFD_SUPPORT
if (WfdSubelementLen > 0)
{
WfdParseSubElmt(pAd,
&pTDLS->WfdEntryInfo,
(PVOID)WfdSubelement,
WfdSubelementLen);
}
#endif /* WFD_SUPPORT */
}
break;
}
//
// Insert into mac table
//
if (StatusCode == MLME_SUCCESS)
{
// allocate one MAC entry
pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr);
if (pMacEntry && IS_ENTRY_TDLS(pMacEntry))
DBGPRINT(RT_DEBUG_ERROR,("TDLS - MacTable Entry exist !!!\n"));
else
pMacEntry = MacTableInsertEntry(pAd, pTDLS->MacAddr, BSS0 + MIN_NET_DEVICE_FOR_TDLS, OPMODE_STA, TRUE);
if (pMacEntry)
{
pTDLS->MacTabMatchWCID = pMacEntry->Aid;
pMacEntry->AuthMode = pAd->StaCfg.AuthMode;
pMacEntry->WepStatus = pAd->StaCfg.WepStatus;
pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED;
pMacEntry->Sst = SST_ASSOC;
#ifdef UAPSD_SUPPORT
/* update UAPSD */
UAPSD_AssocParse(pAd, pMacEntry, &QosCapability,
pAd->StaCfg.UapsdInfo.bAPSDCapable);
#endif /* UAPSD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("MacTableInsertTDlsEntry - allocate entry #%d, Total= %d\n",pMacEntry->Aid, pAd->MacTab.Size));
// Set WMM capability
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable))
{
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
DBGPRINT(RT_DEBUG_ERROR, ("TDLS - WMM Capable\n"));
}
else
{
CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
}
TDLS_InitPeerEntryRateCapability(pAd,
pMacEntry,
&CapabilityInfo,
SupRateLen,
SupRate,
HtCapLen,
&HtCap);
RTMPSetSupportMCS(pAd,
OPMODE_STA,
pMacEntry,
SupRate,
SupRateLen,
ExtRate,
ExtRateLen,
&HtCap,
HtCapLen);
//
// Install Peer Key if RSNA Enabled
//
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
// Write to ASIC on-chip table.
if ( pMacEntry->Aid > 1)
{
CIPHER_KEY PairwiseKey;
PairwiseKey.CipherAlg = CIPHER_AES;
// Set Peer Key
PairwiseKey.KeyLen = LEN_TK;
NdisMoveMemory(PairwiseKey.Key, &pTDLS->TPK[16], LEN_TK);
RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd,
pMacEntry->Aid,
&PairwiseKey);
RTMP_SET_WCID_SEC_INFO(pAd,
BSS0,
0,
PairwiseKey.CipherAlg,
pMacEntry->Aid,
PAIRWISEKEYTABLE);
NdisMoveMemory(&pMacEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
pMacEntry->AuthMode = Ndis802_11AuthModeWPA2PSK;
pMacEntry->WepStatus = Ndis802_11Encryption3Enabled;
pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED;
pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
}
}
}
else
{
StatusCode = MLME_REQUEST_DECLINED;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupRspAction() MacTableInsertEntry failed\n"));
}
}
else
StatusCode = MLME_REQUEST_DECLINED;
send_out:
if (StatusCode == MLME_SUCCESS)
{
TDLS_SetupConfirmAction(pAd, pTDLS, RsnLen, RsnIe, FTLen, FTIe, TILen, TIIe, StatusCode);
pTDLS->ChSwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime;
pTDLS->ChSwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout;
pTDLS->Status = TDLS_MODE_CONNECTED;
TDLS_UAPSD_ENTRY_INIT(pTDLS);
#ifdef TDLS_AUTOLINK_SUPPORT
if (pAd->StaCfg.TdlsInfo.TdlsAutoLink)
{
PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL;
PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList;
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, pTDLS->MacAddr, TRUE);
pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, pTDLS->MacAddr);
if (pPeerEntry)
{
pPeerEntry->bConnectedFirstTime = TRUE;
pPeerEntry->bConnected = TRUE;
pPeerEntry->RetryCount = 0;
pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE;
}
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, pTDLS->MacAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
}
#endif // TDLS_AUTOLINK_SUPPORT //
}
else
{
if ((pTDLS->Status >= TDLS_MODE_CONNECTED) && (pTDLS->Token == Token))
{
DBGPRINT(RT_DEBUG_WARN, ("TDLS - PeerTdlsSetupRspAction() receive the same token TDLS response !!!\n"));
goto CleanUp;
}
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
}
//pAd->StaCfg.TdlsCurrentOperateChannel = pAd->CommonCfg.Channel;
CleanUp:
#ifdef WFD_SUPPORT
os_free_mem(pAd, WfdSubelement);
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupRspAction\n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerSetupConfAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
USHORT StatusCode = MLME_SUCCESS, LocalStatusCode = MLME_SUCCESS;
BOOLEAN TimerCancelled;
PRT_802_11_TDLS pTDLS = NULL;
UCHAR Token;
UCHAR PeerAddr[MAC_ADDR_LEN];
USHORT CapabilityInfo;
EDCA_PARM EdcaParm;
INT LinkId = 0xff;
UCHAR RsnLen, FTLen, TILen, LinkIdentLen;
UCHAR RsnIe[64], FTIe[128], TIIe[7];
PMAC_TABLE_ENTRY pMacEntry = NULL;
TDLS_LINK_IDENT_ELEMENT LinkIdent;
ADD_HT_INFO_IE AddHtInfo;
UCHAR AddHtInfoLen;
PFRAME_802_11 pFrame = (PFRAME_802_11)Elem->Msg;
DBGPRINT(RT_DEBUG_ERROR, ("TDLS ===> TDLS_PeerSetupConfAction\n"));
// Not TDLS Capable, ignore it
if (!IS_TDLS_SUPPORT(pAd))
return;
// Not BSS mode, ignore it
if (!INFRA_ON(pAd))
return;
hex_dump("TDLS setup confirm receive pack", Elem->Msg, Elem->MsgLen);
// Init all kinds of fields within the packet
NdisZeroMemory(&EdcaParm, sizeof(EdcaParm));
NdisZeroMemory(&CapabilityInfo, sizeof(CapabilityInfo));
NdisZeroMemory(RsnIe, sizeof(RsnIe));
NdisZeroMemory(FTIe, sizeof(FTIe));
NdisZeroMemory(TIIe, sizeof(TIIe));
NdisZeroMemory(&LinkIdent, sizeof(LinkIdent));
if (!PeerTdlsSetupConfSanity(
pAd,
Elem->Msg,
Elem->MsgLen,
&Token,
PeerAddr,
&CapabilityInfo,
&EdcaParm,
&StatusCode,
&RsnLen,
RsnIe,
&FTLen,
FTIe,
&TILen,
TIIe,
&LinkIdentLen,
&LinkIdent,
&AddHtInfoLen,
&AddHtInfo))
{
LocalStatusCode = MLME_REQUEST_DECLINED;
}
if (StatusCode != MLME_SUCCESS)
{
COPY_MAC_ADDR(PeerAddr, &pFrame->Hdr.Addr3);
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() received a confirm from %02x:%02x:%02x:%02x:%02x:%02x with StatusCode=%d\n",
PeerAddr[0], PeerAddr[1], PeerAddr[2], PeerAddr[3], PeerAddr[4], PeerAddr[5], StatusCode));
// Drop not within my TDLS Table that created before !
LinkId = TDLS_SearchLinkId(pAd, PeerAddr);
if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
return;
// Point to the current Link ID
pTDLS = (PRT_802_11_TDLS)&pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];
// Cancel the timer since the received packet to me.
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
// Received a error code from the Peer TDLS.
// Let's terminate the setup procedure right now.
if (StatusCode != MLME_SUCCESS)
{
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Valid = FALSE;
#ifdef WFD_SUPPORT
if ((pAd->StaCfg.WfdCfg.bWfdEnable) &&
(StatusCode == MLME_SECURITY_WEAK))
pAd->StaCfg.WfdCfg.TdlsSecurity = WFD_TDLS_WEAK_SECURITY;
#endif /* WFD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() received a failed StatusCode, terminate the setup procedure \n"));
return;
}
else
StatusCode = LocalStatusCode;
//
// Validate the content on Setup Confirm Frame
//
while (StatusCode == MLME_SUCCESS)
{
// Invalid TDLS State
if (pTDLS->Status != TDLS_MODE_WAIT_CONFIRM)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() Not in TDLS_MODE_WAIT_CONFIRM STATE\n"));
StatusCode = MLME_REQUEST_DECLINED;
break;
}
// Is the same Dialog Token?
if (pTDLS->Token != Token)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsSetupConfAction() Not match with Dialig Token \n"));
StatusCode = MLME_REQUEST_DECLINED;
break;
}
// Process TPK Handshake Message 3 here!
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
USHORT Result;
// RSNIE (7.3.2.25), FTIE (7.3.2.48), Timeout Interval (7.3.2.49)
Result = TDLS_TPKMsg3Process(pAd, pTDLS, RsnIe, RsnLen, FTIe, FTLen, TIIe, TILen);
if (Result != MLME_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TPKMsg3Process() Failed, reason=%d \n", Result));
StatusCode = Result;
break;
}
}
// Update parameters
if (StatusCode == MLME_SUCCESS)
{
// I am Responder.And peer are Initiator
pTDLS->bInitiator = TRUE;
// Copy EDCA Parameters
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable))
NdisMoveMemory(&pTDLS->EdcaParm, &EdcaParm, sizeof(EDCA_PARM));
else
NdisZeroMemory(&pTDLS->EdcaParm, sizeof(EDCA_PARM));
// Copy TPK related information
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
// SNonce, Key lifetime
}
}
break;
}
//
// Insert into mac table
//
if (StatusCode == MLME_SUCCESS)
{
// allocate one MAC entry
pMacEntry = MacTableLookup(pAd, pTDLS->MacAddr);
if (pMacEntry && IS_ENTRY_TDLS(pMacEntry))
DBGPRINT(RT_DEBUG_ERROR,("TDLS - MacTable Entry exist !!!\n"));
else
pMacEntry = MacTableInsertEntry(pAd, pTDLS->MacAddr, BSS0 + MIN_NET_DEVICE_FOR_TDLS, OPMODE_STA, TRUE);
if (pMacEntry)
{
pTDLS->MacTabMatchWCID = pMacEntry->Aid;
pMacEntry->AuthMode = pAd->StaCfg.AuthMode;
pMacEntry->WepStatus = pAd->StaCfg.WepStatus;
pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED;
pMacEntry->Sst = SST_ASSOC;
pMacEntry->MatchTdlsEntryIdx = LinkId;
#ifdef UAPSD_SUPPORT
/* update UAPSD */
pTDLS->QosCapability |= (pTDLS->EdcaParm.EdcaUpdateCount & 0x0f);
UAPSD_AssocParse(pAd, pMacEntry, &pTDLS->QosCapability,
pAd->StaCfg.UapsdInfo.bAPSDCapable);
#endif /* UAPSD_SUPPORT */
DBGPRINT(RT_DEBUG_ERROR, ("MacTableInsertTDlsEntry - allocate entry #%d, Total= %d\n",pMacEntry->Aid, pAd->MacTab.Size));
// Set WMM capability
if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) || (pAd->CommonCfg.bWmmCapable))
{
CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
DBGPRINT(RT_DEBUG_ERROR, ("TDLS - WMM Capable\n"));
}
else
{
CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE);
}
TDLS_InitPeerEntryRateCapability(pAd,
pMacEntry,
&pTDLS->CapabilityInfo,
pTDLS->SupRateLen,
pTDLS->SupRate,
pTDLS->HtCapabilityLen,
&pTDLS->HtCapability);
RTMPSetSupportMCS(pAd,
OPMODE_STA,
pMacEntry,
pTDLS->SupRate,
pTDLS->SupRateLen,
pTDLS->ExtRate,
pTDLS->ExtRateLen,
&pTDLS->HtCapability,
pTDLS->HtCapabilityLen);
//
// Install Peer Key if RSNA Enabled
//
if (pAd->StaCfg.WepStatus != Ndis802_11EncryptionDisabled)
{
// Write to ASIC on-chip table.
if ( pMacEntry->Aid > 1)
{
CIPHER_KEY PairwiseKey;
PairwiseKey.CipherAlg = CIPHER_AES;
// Set Peer Key
PairwiseKey.KeyLen = LEN_TK;
NdisMoveMemory(PairwiseKey.Key, &pTDLS->TPK[16], LEN_TK);
RTMP_ASIC_PAIRWISE_KEY_TABLE(pAd,
pMacEntry->Aid,
&PairwiseKey);
RTMP_SET_WCID_SEC_INFO(pAd,
BSS0,
0,
PairwiseKey.CipherAlg,
pMacEntry->Aid,
PAIRWISEKEYTABLE);
NdisMoveMemory(&pMacEntry->PairwiseKey, &PairwiseKey, sizeof(CIPHER_KEY));
pMacEntry->AuthMode = Ndis802_11AuthModeWPA2PSK;
pMacEntry->WepStatus = Ndis802_11Encryption3Enabled;
pMacEntry->PortSecured = WPA_802_1X_PORT_SECURED;
pMacEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll;
}
}
pTDLS->Status = TDLS_MODE_CONNECTED;
pTDLS->ChSwitchTime = pAd->StaCfg.TdlsInfo.TdlsSwitchTime;
pTDLS->ChSwitchTimeout = pAd->StaCfg.TdlsInfo.TdlsSwitchTimeout;
TDLS_UAPSD_ENTRY_INIT(pTDLS);
#ifdef TDLS_AUTOLINK_SUPPORT
if (pAd->StaCfg.TdlsInfo.TdlsAutoLink)
{
PTDLS_DISCOVERY_ENTRY pPeerEntry = NULL;
PLIST_HEADER pTdlsDiscovEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList;
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_InsertDiscoveryPeerEntryByMAC(pTdlsDiscovEnList, pTDLS->MacAddr, TRUE);
pPeerEntry = TDLS_FindDiscoveryEntry(pTdlsDiscovEnList, pTDLS->MacAddr);
if (pPeerEntry)
{
pPeerEntry->bConnectedFirstTime = TRUE;
pPeerEntry->bConnected = TRUE;
pPeerEntry->RetryCount = 0;
pPeerEntry->CurrentState = TDLS_DISCOVERY_TO_SETUP_DONE;
}
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
TDLS_DelBlackEntryByMAC(pTdlsBlackEnList, pTDLS->MacAddr);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
}
#endif // TDLS_AUTOLINK_SUPPORT //
}
else
{
StatusCode = MLME_REQUEST_DECLINED;
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_PeerSetupConfAction() MacTableInsertEntry failed\n"));
}
}
else
{
if ((pTDLS->Status >= TDLS_MODE_CONNECTED) && (pTDLS->Token == Token))
{
DBGPRINT(RT_DEBUG_WARN, ("TDLS - TDLS_PeerSetupConfAction() receive the same token TDLS confirm !!!\n"));
return;
}
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
StatusCode = MLME_REQUEST_DECLINED;
}
pAd->StaCfg.TdlsInfo.TdlsDialogToken = Token;
//pAd->StaCfg.TdlsCurrentOperateChannel = pAd->CommonCfg.Channel;
DBGPRINT(RT_DEBUG_ERROR, ("TDLS <=== TDLS_PeerSetupConfAction\n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_MlmeTearDownAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS;
PRT_802_11_TDLS pTDLS = NULL;
UINT16 ReasonCode;
BOOLEAN IsViaAP = FALSE;
DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_MlmeTearDownAction() \n"));
if (!MlmeTdlsReqSanity(pAd, Elem->Msg, Elem->MsgLen, &pTDLS, &ReasonCode, &IsViaAP))
return;
/* Build TDLS Setup Request Frame via direct link*/
NStatus = TDLS_TearDownAction(pAd, pTDLS, ReasonCode, TRUE);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - TDLS_MlmeTearDownAction() Build Setup Request Fail !!!\n"));
}
else
{
BOOLEAN TimerCancelled;
if (!VALID_WCID(pTDLS->MacTabMatchWCID))
return;
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, pTDLS->MacAddr);
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_MlmeTearDownAction() \n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID
TDLS_PeerTearDownAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
UCHAR SA[MAC_ADDR_LEN];
USHORT ReasonCode;
PRT_802_11_TDLS pTDLS = NULL;
INT LinkId = 0xff;
BOOLEAN IsInitator;
//UINT i;
BOOLEAN TimerCancelled;
UCHAR FTLen, LinkIdentLen;
UCHAR FTIe[128];
TDLS_LINK_IDENT_ELEMENT LinkIdent;
PHEADER_802_11 pHdr;
DBGPRINT(RT_DEBUG_ERROR,("TDLS ===> TDLS_PeerTearDownAction() \n"));
// Not TDLS Capable, ignore it
if (!IS_TDLS_SUPPORT(pAd))
return;
if (!INFRA_ON(pAd))
return;
hex_dump("TDLS TearDown receive pack", Elem->Msg, Elem->MsgLen);
// Init FTIe
NdisZeroMemory(FTIe, sizeof(FTIe));
NdisZeroMemory(&LinkIdent, sizeof(LinkIdent));
if (!PeerTdlsTearDownSanity(pAd,
Elem->Msg,
Elem->MsgLen,
SA,
&IsInitator,
&ReasonCode,
&FTLen,
FTIe,
&LinkIdentLen,
&LinkIdent))
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x Sanity Check Fail\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
return;
}
pHdr = (PHEADER_802_11)Elem->Msg;
if (pHdr->FC.FrDs == 1)
{
COPY_MAC_ADDR(SA, &pHdr->Addr3);
}
else
{
COPY_MAC_ADDR(SA, &pHdr->Addr2);
}
DBGPRINT(RT_DEBUG_OFF,("TDLS - PeerTdlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x with ReasonCode=%d\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], ReasonCode));
// Drop not within my TDLS Table that created before !
LinkId = TDLS_SearchLinkId(pAd, SA);
if (LinkId == -1 || LinkId == MAX_NUM_OF_TDLS_ENTRY)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() can not find from %02x:%02x:%02x:%02x:%02x:%02x on TDLS entry !!!\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
return;
}
// Point to the current Link ID
pTDLS = &pAd->StaCfg.TdlsInfo.TDLSEntry[LinkId];
// Cancel the timer since the received packet to me.
//RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
// Drop mismatched identifier.
if (pTDLS->bInitiator != IsInitator)
{
DBGPRINT(RT_DEBUG_ERROR,("TDLS - PeerTdlsTearDownAction() pTDLS->bInitiator = %x parse = %x !!!\n",
pTDLS->bInitiator, IsInitator));
return;
}
// clear tdls table entry
if (pTDLS->Valid && MAC_ADDR_EQUAL(SA, pTDLS->MacAddr))
{
#ifdef TDLS_AUTOLINK_SUPPORT
PLIST_HEADER pTdlsBlackEnList = &pAd->StaCfg.TdlsInfo.TdlsBlackList;
PLIST_HEADER pTdlsDiscoveryEnList = &pAd->StaCfg.TdlsInfo.TdlsDiscovPeerList;
#endif // TDLS_AUTOLINK_SUPPORT //
pTDLS->Status = TDLS_MODE_NONE;
pTDLS->Token = 0;
pTDLS->Valid = FALSE;
RTMPCancelTimer(&pTDLS->Timer, &TimerCancelled);
MacTableDeleteEntry(pAd, pTDLS->MacTabMatchWCID, SA);
#ifdef TDLS_AUTOLINK_SUPPORT
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
TDLS_InsertBlackEntryByMAC(pTdlsBlackEnList, SA, TDLS_BLACK_TDLS_BY_TEARDOWN);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsBlackListSemLock);
RTMP_SEM_LOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
TDLS_DelDiscoveryEntryByMAC(pTdlsDiscoveryEnList, SA);
RTMP_SEM_UNLOCK(&pAd->StaCfg.TdlsInfo.TdlsDiscovPeerListSemLock);
#endif // TDLS_AUTOLINK_SUPPORT //
}
DBGPRINT(RT_DEBUG_ERROR,("TDLS <=== TDLS_PeerTearDownAction() \n"));
return;
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID TDLS_TimeoutAction(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext;
PRTMP_ADAPTER pAd;
DBGPRINT(RT_DEBUG_TRACE, ("TdlsTimeout - Failed to wait for the response, terminate the setup procedure (%02x:%02x:%02x:%02x:%02x:%02x)\n",
pTDLS->MacAddr[0], pTDLS->MacAddr[1], pTDLS->MacAddr[2], pTDLS->MacAddr[3], pTDLS->MacAddr[4], pTDLS->MacAddr[5]));
/*
11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA
When no corresponding TDLS Peer Traffic Response frame has been
received within dot11TDLSResponseTimeout after sending a TDLS Peer
Traffic Indication frame, the STA shall tear down the direct link.
*/
pAd = pTDLS->pAd;
if (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE)
{
/* timeout for traffic response frame */
/* TODO: tear down the link with the peer */
DBGPRINT(RT_DEBUG_OFF, ("tdls uapsd> traffic rsp timeout!!!\n"));
pTDLS->FlgIsWaitingUapsdTraRsp = FALSE;
TDLS_TearDownPeerLink(pAd, pTDLS->MacAddr, FALSE);
return;
}
if ((pTDLS) && (pTDLS->Valid) && (pTDLS->Status < TDLS_MODE_CONNECTED))
{
pTDLS->Valid = FALSE;
pTDLS->Status = TDLS_MODE_NONE;
}
}
/*
==========================================================================
Description:
IRQL = PASSIVE_LEVEL
==========================================================================
*/
VOID TDLS_LinkTimeoutAction(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
PRT_802_11_TDLS pTDLS = (PRT_802_11_TDLS)FunctionContext;
PRTMP_ADAPTER pAd;
DBGPRINT(RT_DEBUG_TRACE, ("TdlsTimeout - Failed to wait for the response, terminate the setup procedure (%02x:%02x:%02x:%02x:%02x:%02x)\n",
pTDLS->MacAddr[0], pTDLS->MacAddr[1], pTDLS->MacAddr[2], pTDLS->MacAddr[3], pTDLS->MacAddr[4], pTDLS->MacAddr[5]));
/*
11.2.1.14.1 Peer U-APSD Behavior at the PU buffer STA
When no corresponding TDLS Peer Traffic Response frame has been
received within dot11TDLSResponseTimeout after sending a TDLS Peer
Traffic Indication frame, the STA shall tear down the direct link.
*/
pAd = pTDLS->pAd;
if (pTDLS->FlgIsWaitingUapsdTraRsp == TRUE)
{
/* timeout for traffic response frame */
/* TODO: tear down the link with the peer */
DBGPRINT(RT_DEBUG_OFF, ("tdls uapsd> traffic rsp timeout!!!\n"));
pTDLS->FlgIsWaitingUapsdTraRsp = FALSE;
TDLS_TearDownPeerLink(pAd, pTDLS->MacAddr, FALSE);
return;
}
if ((pTDLS) && (pTDLS->Valid) && (pTDLS->Status < TDLS_MODE_CONNECTED))
{
pTDLS->Valid = FALSE;
pTDLS->Status = TDLS_MODE_NONE;
}
}
#endif /* DOT11Z_TDLS_SUPPORT */