/* ======================================================================== Routine Description: Build the traffic response frame body. Arguments: pAd - WLAN control block pointer pFrameBuf - frame pFrameLen - frame length pTDLS - TDLS link entry Return Value: None Note: ======================================================================== */ static VOID TDLS_UAPSD_TrafficRspBuild( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN PRT_802_11_TDLS pTDLS, IN UCHAR PeerToken) { /* fill action code */ TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_PEER_TRAFFIC_RESPONSE); /* fill Dialog Token */ TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, PeerToken); /* 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); } }
/* ======================================================================== Routine Description: Build the traffic indication frame payload. Arguments: pAd - WLAN control block pointer pFrameBuf - frame pFrameLen - frame length pTDLS - TDLS link entry Return Value: None Note: ======================================================================== */ static VOID TDLS_UAPSD_TrafficIndPayloadBuild( IN PRTMP_ADAPTER pAd, OUT PUCHAR pFrameBuf, OUT PULONG pFrameLen, IN PRT_802_11_TDLS pTDLS) { UCHAR RemoteFrameType = PROTO_NAME_TDLS; ULONG TempLen; UCHAR Token; // Dialog token /* fill remote frame type */ MakeOutgoingFrame(pFrameBuf, &TempLen, 1, &RemoteFrameType, END_OF_ARGS); *pFrameLen = TempLen; /* fill action code */ TDLS_InsertActField(pAd, (pFrameBuf + *pFrameLen), pFrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_PEER_TRAFFIC_INDICATION); /* fill Dialog Token */ TDLS_UAPSD_DIALOG_GET(pAd, Token); TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, Token); /* 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); /* fill PU buffer status */ TDLS_InsertPuBufferStatus(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->MacAddr); }
/* ======================================================================== Routine Description: Simulate to receive a TDLS Traffic indication from a peer. Arguments: pAd - WLAN control block pointer Argc - the number of input parameters *pArgv - input parameters Return Value: None Note: 1. Command Format: iwpriv ra0 set tdls=53_[PEER MAC] ======================================================================== */ static VOID TDLS_UAPSD_CmdSimTrafficIndRcv( IN PRTMP_ADAPTER pAd, IN INT32 Argc, IN CHAR *pArgv) { UCHAR PeerMac[6]; MLME_QUEUE_ELEM *pElem = NULL; PUCHAR pOutBuffer = NULL; ULONG FrameLen = 0; INT32 LinkId; RT_802_11_TDLS *pTDLS = NULL; NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; UCHAR RemoteFrameType = PROTO_NAME_TDLS; ULONG TempLen; UCHAR Token; // Dialog token /* get MAC address */ TDLS_UAPSD_CmdUtilMacGet(&pArgv, PeerMac); /* allocate resources */ NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); if (NStatus != NDIS_STATUS_SUCCESS) goto LabelExit; /* make up a virtual traffic indication frame */ /* search TDLS entry */ LinkId = TDLS_SearchLinkId(pAd, PeerMac); if (TDLS_UAPSD_IS_LINK_INVALID(LinkId)) { DBGPRINT(RT_DEBUG_ERROR, ("%s: can not find the LinkId!\n", __FUNCTION__)); TDLS_UAPSD_REBUILD_LINK(pAd, PeerMac); goto LabelExit; } pTDLS = TDLS_UAPSD_ENTRY_GET(pAd, LinkId); /* build the frame */ /* fill remote frame type */ MakeOutgoingFrame(pOutBuffer, &TempLen, 1, &RemoteFrameType, END_OF_ARGS); FrameLen = TempLen; /* fill action code */ TDLS_InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_TDLS, TDLS_ACTION_CODE_SETUP_REQUEST); /* fill Dialog Token */ TDLS_UAPSD_DIALOG_GET(pAd, Token); TDLS_InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, Token); /* fill link identifier */ TDLS_InsertLinkIdentifierIE(pAd, (pOutBuffer + FrameLen), &FrameLen, pTDLS->MacAddr, pAd->CurrentAddress); /* fill PU buffer status */ TDLS_InsertPuBufferStatus(pAd, (pOutBuffer + FrameLen), &FrameLen, pTDLS->MacAddr); if (FrameLen <= 0) goto LabelExit; /* hex_dump("TDLS traffic indication send pack", pOutBuffer, FrameLen); */ /* allocate resources */ os_alloc_mem(NULL, (UCHAR **)&pElem, sizeof(MLME_QUEUE_ELEM)); if (pElem == NULL) goto LabelExit; /* copy the indication frame */ FrameLen += LENGTH_802_11 + LENGTH_802_1_H; pElem->MsgLen = LENGTH_802_11 + LENGTH_802_1_H + FrameLen; /* copy payload */ memcpy(pElem->Msg + LENGTH_802_11 + LENGTH_802_1_H, pOutBuffer, FrameLen); /* handle it */ TDLS_UAPSD_PeerTrafficIndAction(pAd, pElem); /* free resources */ LabelExit: if (pElem != NULL) os_free_mem(NULL, pElem); if (pOutBuffer != NULL) MlmeFreeMemory(pAd, pOutBuffer); }
/* ========================================================================== 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.TdlsDialogToken++; if (pAd->StaCfg.TdlsDialogToken == 0) pAd->StaCfg.TdlsDialogToken++; pTDLS->Token = pAd->StaCfg.TdlsDialogToken; TDLS_InsertDialogToken(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS->Token); /* fill link identifier */ TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); // fill capability TDLS_InsertCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill ssid TDLS_InsertSSIDIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill support rate TDLS_InsertSupportRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill ext rate TDLS_InsertExtRateIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // fill Qos Capability TDLS_InsertQosCapIE(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 Extended Capabilities (7.3.2.27) TDLS_InsertExtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); // TPK Handshake if RSNA Enabled // Pack TPK Message 1 here! if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))) { UCHAR CipherTmp[64] = {0}; UCHAR CipherTmpLen = 0; FT_FTIE FtIe; ULONG KeyLifetime = TDLS_KEY_TIMEOUT; // sec ULONG tmp; UCHAR Length; // RSNIE (7.3.2.25) CipherTmpLen = CipherSuiteTDLSLen; if (pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskTkip, CipherTmpLen); else NdisMoveMemory(CipherTmp, CipherSuiteTDLSWpa2PskAes, CipherTmpLen); // update AKM if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) CipherTmp[19] = TDLS_AKM_SUITE_1X; // Insert RSN_IE to outgoing frame MakeOutgoingFrame((pFrameBuf + *pFrameLen), &tmp, CipherTmpLen, &CipherTmp, END_OF_ARGS); *pFrameLen = *pFrameLen + tmp; // 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; } // ==>> 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_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 link identifier */ TDLS_InsertLinkIdentifierIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pAd->CurrentAddress, pTDLS->MacAddr); // fill Qos Capability TDLS_InsertEDCAParameterSetIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, pTDLS); #ifdef DOT11_N_SUPPORT // fill HT Capability TDLS_InsertHtCapIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen); #endif // DOT11_N_SUPPORT // // TPK Handshake if RSNA Enabled // Pack TPK Message 3 here! if (((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK)) && ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) || (pAd->StaCfg.WepStatus == Ndis802_11Encryption3Enabled))) { 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, 20, (pRsnIe + 2), 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), (PUCHAR)ft, 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); } }